Posts Tagged ‘spectacular’

Programming Praxis – Spectacular Seven

May 4, 2010

In today’s Programming Praxis exercise our task is to run a simulation of a ballgame to see if the scoring mechanic is fair. The provided Scheme solution clocks in at 25 lines. Let’s see if we can do any better.

First, some imports.

import Control.Applicative
import Control.Monad
import Data.List
import System.Random

After a match, the winner gets a point and the loser is moved to the end of the queue.

match :: Int -> [(a, Int)] -> Int -> [(a, Int)]
match ps ~(x:y:r) w = (p,s + if ps > 7 then 2 else 1) : r ++ [c]
    where ((p,s), c) = if w == 0 then (x,y) else (y,x)

A game ends when one of the teams has 7 or more points.

game :: IO Int
game = f 0 (zip [1..8] [0,0..]) . randomRs (0,1) <$> newStdGen
       where f ps a ~(x:xs) = maybe (f (ps+1) (match ps a x) xs) fst $
                              find ((>= 7) . snd) a

To simulate the game, we play a number of games and calculate the winning percentages of each team.

simulate :: Int -> IO [Float]
simulate n = (\ws -> map (\x -> 100 * (l x - 1) / l ws) . group .
                     sort $ ws ++ [1..8]) <$> replicateM n game
             where l = fromIntegral . length

All that’s left is to run the simulation.

main :: IO ()
main = mapM_ print =<< simulate 10000

That leaves us with 7 lines, more than a two thirds reduction compared to the Scheme solution. That’ll do nicely.