In today’s Programming Praxis exercise, our goal is to simulate a Galton board and display the frequencies of the different bins as a histogram. Let’s get started, shall we?
import Control.Applicative import Control.Monad import System.Random
When dropping a single marble we simulate a number of coin tosses to see which bin the marble ends up in.
marble :: Int -> IO Int marble bins = sum . take (bins - 1) . randomRs (0, 1) <$> newStdGen
When dropping multiple marbles we count how often each bucket is hit.
marbles :: Num a => Int -> Int -> IO [a] marbles n bins = flip fmap (replicateM n $ marble bins) (\results -> map (fromIntegral . length . flip filter results . (==)) [0..bins - 1])
Displaying the histogram is a matter of scaling the values and printing the appropriate amount of asterisks. You can choose the horizontal scaling to get more or less detailed results.
histogram :: RealFrac a => a -> [a] -> IO () histogram w cols = mapM_ (\n -> putStrLn $ replicate (ceiling $ n * w / maximum cols) '*') cols
The program itself consists of printing the results of the simulation as a histogram.
main :: IO () main = histogram 20 =<< marbles 1000 8