class Table {
	Semaphore forkInUse[];
	
	public Table(int seats) {
		int forks = (seats==1?2:seats);
		
		forkInUse = new Semaphore[forks];
		for (int i=0; i<forks; i++)
			forkInUse[i] = new Semaphore(1);
	} //constructor

	private int left(int i)	{
		return i;
	} //left()

	private int right(int i) {
		if (i+1 < forkInUse.length) {
			return (i+1);
		} //if
		else {
			return 0;
		} //else
	} //right()
	
	public void useFork(int seat)	{
		forkInUse[left(seat)].p();
		System.out.println("Philosopher #"+Thread.currentThread().getName()+" received left fork");
		forkInUse[right(seat)].p();
		System.out.println("Philosopher #"+Thread.currentThread().getName()+" received right fork");
	} //useFork()
	
	public void releaseFork(int seat) {
		forkInUse[left(seat)].v();
		System.out.println("Philosopher #"+Thread.currentThread().getName()+" released left fork");
		forkInUse[right(seat)].v();
		System.out.println("Philosopher #"+Thread.currentThread().getName()+" released right fork");
	} //relaeaseFork()
} //class Table
	
class Philosopher implements Runnable
{
	Table myTable;
	int seat;
	
	public Philosopher(Table table, int seat)
	{
		myTable = table;
		this.seat = seat;
	} //constructor
	
	public void run()
	{
		while(true)
		{
			think(seat);
			myTable.useFork(seat);
			eat(seat);
			myTable.releaseFork(seat);
		} //loop endlessly
	} //run()
		
	void think(int seat)	{
		System.out.println("Philosopher #"+Thread.currentThread().getName()+" is thinking");
		try
		{
			Thread.sleep( (int) (Math.random() * 0) );
		} //try
		catch (InterruptedException ie)
		{
			System.out.println("An InterruptedException caught\n"+ie.getMessage());
			ie.printStackTrace();
			System.exit(1);
		} //catch()
	} //think()

	void eat(int seat)
	{
		System.out.println("Philosopher #"+Thread.currentThread().getName()+" is eating");
		try
		{
			Thread.sleep( (int) (Math.random() * 0) );
		} //try
		catch (InterruptedException ie)
		{
			System.out.println("An InterruptedException caught\n"+ie.getMessage());
			ie.printStackTrace();
			System.exit(1);
		} //catch()
		System.out.println("Philosopher #"+Thread.currentThread().getName()+" finished eating");
	} //eat()
} //class Philosopher

public class HungryPhilosophers4
{
	public static void main(String argv[])
	{
		int hungryPhilosophers = Integer.parseInt(argv[0]);
		Table table = new Table( hungryPhilosophers );
		for (int i=0; i<hungryPhilosophers; i++)
		{
			new Thread(new Philosopher(table, i),""+(i+1)).start();
		} //for
	} //main()
} //class HungryPhilosophers4