Created
October 31, 2009 21:34
-
-
Save zach-klippenstein/223257 to your computer and use it in GitHub Desktop.
Problem 4 solution attempt for 2009 ACM North American Programming competition
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.io.*; | |
import java.util.Scanner; | |
import java.util.HashMap; | |
import java.util.Collection; | |
public class Contest09Problem4 | |
{ | |
enum State | |
{ | |
running, | |
waiting, | |
zombie | |
}; | |
private static class Process | |
{ | |
public int pid; | |
public Process parent; | |
public State state; | |
public ProcessList children; | |
public Process(int pid, Process parent) | |
{ | |
this.pid = pid; | |
this.parent = parent; | |
state = State.running; | |
children = new ProcessList(); | |
} | |
public int fork() | |
{ | |
Process p = new Process(g_procList.getNextPID(), this); | |
g_procList.set(p.pid, p); | |
children.set(p.pid, p); | |
return p.pid; | |
} | |
private boolean reapOne() | |
{ | |
for (Process p : children.values()) | |
{ | |
if (p.state == State.zombie) | |
{ | |
p.parent = null; | |
children.remove(p.pid); | |
g_procList.remove(p.pid); | |
state = State.running; | |
return true; | |
} | |
} | |
return false; | |
} | |
public void pwait() | |
{ | |
if (!reapOne()) | |
{ | |
if (!children.isEmpty()) | |
{ | |
state = State.waiting; | |
} | |
} | |
} | |
public void exit() | |
{ | |
state = State.zombie; | |
if (null != parent) | |
{ | |
if (parent.state == State.waiting) | |
{ | |
parent.reapOne(); | |
} | |
} | |
else | |
{ | |
g_procList.remove(pid); | |
} | |
for (Process p : children.values()) | |
{ | |
p.parent = null; | |
} | |
} | |
} | |
private static class ProcessList | |
{ | |
int currPID; | |
HashMap<Integer, Process> procs; | |
public ProcessList() | |
{ | |
procs = new HashMap<Integer, Process>(); | |
currPID = 0; | |
} | |
public int getNextPID() | |
{ | |
return ++currPID; | |
} | |
public void set(int pid, Process proc) | |
{ | |
procs.put(new Integer(pid), proc); | |
} | |
public Process get(int pid) | |
{ | |
return procs.get(new Integer(pid)); | |
} | |
boolean isEmpty() | |
{ | |
return procs.isEmpty(); | |
} | |
void remove(int pid) | |
{ | |
procs.remove(new Integer(pid)); | |
} | |
Collection<Process> values() | |
{ | |
return procs.values(); | |
} | |
ProcessList getProcsInState(State state) | |
{ | |
ProcessList rtn = new ProcessList(); | |
for (Process p : values()) | |
{ | |
if (state == p.state) | |
rtn.set(p.pid, p); | |
} | |
return rtn; | |
} | |
public String toString() | |
{ | |
String rtn = ""; | |
Collection<Process> vals = values(); | |
int i = 0; | |
for (Process p : vals) | |
{ | |
rtn += Integer.toString(p.pid); | |
if (i < vals.size() - 1) | |
rtn += ", "; | |
i++; | |
} | |
return rtn; | |
} | |
public int size() | |
{ | |
return procs.size(); | |
} | |
public void reapAll() | |
{ | |
ProcessList zombies = getProcsInState(State.zombie); | |
for (Process p : zombies.values()) | |
{ | |
remove(p.pid); | |
} | |
} | |
} | |
// --- | |
// VARIABLES | |
// --- | |
public static ProcessList g_procList; | |
public static Process g_firstProc; | |
public static void initGlobalProcs() | |
{ | |
g_procList = new ProcessList(); | |
g_firstProc = new Process(g_procList.getNextPID(), null); | |
g_procList.set(g_firstProc.pid, g_firstProc); | |
} | |
// Returns false if done | |
public static boolean execLine(String line) | |
{ | |
String[] tokens = line.split("\\s"); | |
int pid; | |
String command; | |
Process proc; | |
if (1 == tokens.length) | |
{ | |
if (tokens[0].equals("0")) | |
return false; | |
} | |
else if (2 <= tokens.length) | |
{ | |
pid = Integer.parseInt(tokens[0]); | |
command = tokens[1]; | |
proc = g_procList.get(pid); | |
if (null != proc) | |
{ | |
if (command.equals("fork")) | |
{ | |
proc.fork(); | |
} | |
else if (command.equals("wait")) | |
{ | |
proc.pwait(); | |
} | |
else if (command.equals("exit")) | |
{ | |
proc.exit(); | |
} | |
} | |
} | |
return true; | |
} | |
public static void printEndState(int caseNum) | |
{ | |
String prefix = " "; // 3 spaces indent | |
ProcessList procs; | |
System.out.printf("Case %d:\n", caseNum); | |
if (g_procList.isEmpty()) | |
{ | |
System.out.println(prefix + "No processes."); | |
} | |
else | |
{ | |
procs = g_procList.getProcsInState(State.running); | |
System.out.printf("%s%d Running: %s\n", prefix, procs.size(), procs); | |
procs = g_procList.getProcsInState(State.zombie); | |
System.out.printf("%s%d Zombie: %s\n", prefix, procs.size(), procs); | |
procs = g_procList.getProcsInState(State.waiting); | |
System.out.printf("%s%d Waiting: %s\n", prefix, procs.size(), procs); | |
} | |
System.out.println(); | |
} | |
public static void main( String[] args ) | |
{ | |
Scanner kbd = new Scanner(System.in); | |
String line; | |
boolean running = true; | |
int caseNum = 0; | |
while (kbd.hasNextLine()) | |
{ | |
//System.err.printf("Starting new case: %d\n", caseNum); | |
initGlobalProcs(); | |
caseNum++; | |
// This block required to detect double 0s | |
line = kbd.nextLine(); | |
running = execLine(line); | |
if (!running) | |
break; | |
//System.err.printf("Read first line...\n"); | |
while (kbd.hasNextLine()) | |
{ | |
line = kbd.nextLine(); | |
running = execLine(line); | |
if (!running) | |
break; | |
//System.err.printf("line=%s, running=%s\n", line, running); | |
} | |
g_procList.reapAll(); | |
printEndState(caseNum); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment