/* 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 converted to Tango by Sean Kelly */ import tango.stdc.stdio, tango.stdc.stdlib, tango.core.Thread, tango.util.locks.Semaphore; void main(char[][] args) { int meetings, n = args.length > 1 ? atoi((args[1] ~ '\0').ptr) : 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.join(); meetings += c.creaturesMet; } printf("%d\n", meetings); } enum Colour { blue, red, yellow, faded } Colour[] colours = [ Colour.blue, Colour.red, Colour.yellow, Colour.blue ]; class MeetingPlace { private static Semaphore mustWait; private Colour first, second; private bool firstCall = true; private int n; private bool second_was_here = false; this(int maxMeetings) { n = maxMeetings; mustWait = new Semaphore(1); //sem_init(&mustWait;,0,1); } private Colour OtherCreaturesColour(Colour me) { Colour other = Colour.faded; mustWait.acquire(); //sem_wait(&mustWait;); if(firstCall) { if(n) { first = me; firstCall = false; second_was_here = false; mustWait.release(); //sem_post(&mustWait;); assert( second_was_here, "second must was be here" ); other = second; n--; } mustWait.release(); //sem_post(&mustWait;); } else { firstCall = true; second = me; second_was_here = true; other = first; } return other; } } class Creature : Thread { private MeetingPlace m; private int creaturesMet = 0; private Colour me; this(MeetingPlace m, Colour c) { super(&run); this.m = m; this.me = c; } void 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; } }