Skip to content

Instantly share code, notes, and snippets.

@zach-klippenstein
Created October 31, 2009 21:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zach-klippenstein/223257 to your computer and use it in GitHub Desktop.
Save zach-klippenstein/223257 to your computer and use it in GitHub Desktop.
Problem 4 solution attempt for 2009 ACM North American Programming competition
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