I'm implementing Conway's Life in Haskell; my basic implementation is attached. Does anyone have suggestions for optimizations (or alternative representations)? It's interesting to note that the difference between this with no ghc optimization, -O, and -O2 is pretty striking; on my computer, it's about seven seconds, two seconds, and one second runtime, respectively. Abe module Main where import Data.Array.IArray import Data.Array.Unboxed import Data.Ix import System.Random type Grid = UArray (Int, Int) Int randomGrid :: (RandomGen g) => g -> Int -> Grid randomGrid g s = listArray b $ map (\x -> if x then 1 else 0) $ take (rangeSize b) $ randoms g where b = ((0,0),(s-1,s-1)) getCell :: Grid -> (Int, Int) -> Int getCell g c@(x,y) = if (x < xmin) || (x > xmax) || (y < ymin) || (y >= ymax) then 0 else g ! c where ((xmin, ymin), (xmax, ymax)) = bounds g update :: Grid -> Grid update g = array (bounds g) $ map aux $ assocs g where aux (c@(x,y),e) = let around = map (getCell g) $ filter (/= (x,y)) $ range ((x-1,y-1),(x+1,y+1)) in (c,rule (sum around) e) rule 2 e = e rule 3 e = 1 rule _ _ = 0 printGrid :: Grid -> IO () printGrid g = do let ((xmin, ymin), (xmax, ymax)) = bounds g mapM_ aux $ map (\x -> range ((x,ymin),(x,ymax))) [xmin..xmax] putStrLn "" where aux ixs = do mapM_ (putStr . show) $ map (g!) ixs putStrLn "" main :: IO () main = printGrid $ (iterate update (randomGrid (mkStdGen 0) 50)) !! 100
I'll answer my own question; I've got a much better implementation, along with an HOpenGL-based frontend, at "http://ofb.net/~abe/hlife/hlife-0.1.tar.gz". It uses a FiniteMap of 5x5 UArrays that are created and destroyed as needed; this gives it a good balance of size (the grid is only bounded by the max values of an Int) and speed (my test program runs 100 generations in about three seconds). Abe
participants (1)
-
Abraham Egnor