1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
|
{- The Computer Language Shootout
http://shootout.alioth.debian.org/
Written by Tom Pledger, 13 Nov 2006. modified by Don Stewart -}
import Control.Concurrent (forkIO,yield)
#if defined(STRICT)
import Control.Concurrent.MVar.Strict
#else
import Control.Concurrent.MVar
#endif
import Control.Monad
import System
data Colour = Blue | Red | Yellow
complement a b = case (a,b) of
(Red,Yellow) -> Blue
(Red,Blue) -> Yellow
(Red,Red) -> Red
(Yellow,Blue) -> Red
(Yellow,Red) -> Blue
(Yellow,Yellow) -> Yellow
(Blue,Red) -> Yellow
(Blue,Yellow) -> Red
(Blue,Blue) -> Blue
colors = [Blue, Red, Yellow]
data MP = MP !Int !(Maybe Colour) ![Int]
main = do n <- getArgs >>= readIO . head
waker <- newEmptyMVar
mpv <- newMVar $ MP n Nothing []
let arrive c t = do
MP q w d <- takeMVar mpv
case w of
_ | q == 0 -> if length d /= 3 then putMVar mpv $ MP 0 w (t:d)
else print $ t + sum d
Nothing -> do putMVar mpv $ MP q (Just c) d
c' <- takeMVar waker
arrive c' $! t+1
Just k -> do let c' = complement k c
-- this should cause a space leak:
putMVar waker c'
putMVar mpv $ MP (q-1) Nothing d
arrive c' $! t+1
mapM_ (forkIO . flip arrive 0) colors
arrive Blue 0
replicateM_ 3 yield
|