import tango.core.Thread; import tango.util.locks.Condition; import tango.util.locks.Mutex; import tango.text.convert.Integer; import tango.io.Stdout; typedef int Color; const Color BLUE = 0; const Color RED = 1; const Color YELLOW = 2; const Color FADED = 3; class MeetingPlace { this( int maxMeetings ) { remaining_ = maxMeetings; lock_ = new Mutex; condition_ = new Condition( lock_ ); } Color meet( Color my ) { Color other = FADED; scope localLock = new ScopedLock( lock_ ); if( firstCall_ ) { if( remaining_ > 0 ) { first_ = my; firstCall_ = false; condition_.wait(); other = second_; --remaining_; } } else { firstCall_ = true; second_ = my; other = first_; condition_.notify(); } return other; } private : int remaining_; Mutex lock_; Condition condition_; bool firstCall_ = true; Color first_, second_; } class Creature : Thread { this( Color my, MeetingPlace meetingPlace ) { super( &run ); my_ = my; meetingPlace_ = meetingPlace; } void run() { while( true ) { Color other = meetingPlace_.meet( my_ ); if( FADED != other ) { my_ = complement( other ); ++creaturesMeet_; } else break; } } int total() { return creaturesMeet_; } private : Color my_; MeetingPlace meetingPlace_; int creaturesMeet_ = 0; Color complement( Color other ) { switch( my_ ) { case BLUE: return other == RED ? YELLOW : RED; case RED: return other == BLUE ? YELLOW : BLUE; case YELLOW: return other == BLUE ? RED : BLUE; default: break; } return my_; } } void main( char[][] args ) { auto meetings = 2 == args.length ? parse( args[ 1 ], 10 ) : 100; auto colors = [ BLUE, RED, YELLOW, BLUE ]; auto meetingPlace = new MeetingPlace( meetings ); Creature[] group; foreach( color; colors ) { Creature creature = new Creature( color, meetingPlace ); group ~= creature; creature.start; } int total = 0; foreach( c; group ) { c.join; total += c.total; } Stdout( total ).newline; } // vim:ts=2:sts=2:sw=2:expandtab:fenc=utf-8: