/* The Great Computer Language Shootout
http://shootout.alioth.debian.org/
Reference implementation in C# contributed by Isaac Gouy
converted to D by Dave Fladebo
compile: dmd -O -inline -release chameneos.d
*/
import std.stdio, std.string, std.thread, std.c.linux.linux;
void main(char[][] args)
{
int meetings, n = args.length > 1 ? atoi(args[1]) : 1;
MeetingPlace m = new MeetingPlace(n);
Creature[] creatures = new Creature[colours.length];
foreach(int i, inout Creature c; creatures)
{
c = new Creature(m,colours[i]);
c.start();
}
foreach(Creature c; creatures)
{
c.wait();
meetings += c.creaturesMet;
}
writefln(meetings);
}
enum Colour { blue, red, yellow, faded }
Colour[] colours = [ Colour.blue, Colour.red, Colour.yellow, Colour.blue ];
class MeetingPlace
{
private static sem_t mustWait;
private Colour first, second;
private bool firstCall = true;
private int n;
this(int maxMeetings)
{
n = maxMeetings;
sem_init(&mustWait,0,1);
}
private Colour OtherCreaturesColour(Colour me)
{
Colour other = Colour.faded;
sem_wait(&mustWait);
if(firstCall)
{
if(n)
{
first = me;
firstCall = false;
sem_post(&mustWait);
other = second;
n--;
}
sem_post(&mustWait);
} else {
firstCall = true;
second = me;
other = first;
}
return other;
}
}
class Creature : Thread
{
private MeetingPlace m;
private int creaturesMet = 0;
private Colour me;
this(MeetingPlace m, Colour c)
{
this.m = m; this.me = c;
}
int run()
{
while(me != Colour.faded) MeetOtherCreature();
return 0;
}
private void MeetOtherCreature()
{
Colour other = m.OtherCreaturesColour(me);
if(other == Colour.faded)
{
me = other;
} else {
me = Complement(other);
creaturesMet++;
}
}
private Colour Complement(Colour other)
{
switch(me)
{
case Colour.blue:
return other == Colour.red ? Colour.yellow : Colour.red;
case Colour.red:
return other == Colour.blue ? Colour.yellow : Colour.blue;
case Colour.yellow:
return other == Colour.blue ? Colour.red : Colour.blue;
default:
break;
}
return me;
}
}