Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Game of Life in Haskell, using list monad heaps.

  • Loading branch information...
commit b521accf3df42aea7f16eb623306dfa816875921 1 parent f41e4ea
@xaviershay authored
Showing with 63 additions and 0 deletions.
  1. +63 −0 misc/game_of_life.hs
View
63 misc/game_of_life.hs
@@ -0,0 +1,63 @@
+import Data.List
+import Control.Monad
+
+type Cell = (Int, Int)
+type Grid = [Cell]
+
+-- Game Logic
+
+neighbours :: Cell -> Grid
+neighbours (x, y) = do
+ dx <- [-1..1]
+ dy <- [-1..1]
+ guard (dx /= 0 || dy /= 0)
+ return (x + dx, y + dy)
+
+step :: Grid -> Grid
+step cells = do
+ (newCell, n) <- frequencies $ concatMap neighbours cells
+ guard $ (n == 3) || (n == 2 && newCell `elem` cells)
+ return newCell
+
+-- This is the only deviation from the Clojure version, since it is not a
+-- built-in in Haskell.
+frequencies :: Ord a => [a] -> [(a, Int)]
+frequencies xs = do
+ x <- group $ sort xs
+ return (head x, length x)
+
+
+-- UI
+
+-- Feel like I'm missing a concept. Not so happy with this function:
+-- * Can `eol` be done a better way? I tried nested maps but it was urgh.
+-- * `marker` seems long for a simple tenary. Same issue as `eol` I guess.
+formatGrid :: Grid -> String
+formatGrid grid = do
+ y <- ys
+ x <- xs
+ [marker x y] ++ eol x
+ where
+ marker x y
+ | (x, y) `elem` grid = '*'
+ | otherwise = ' '
+ eol x
+ | x == maximum xs = ['\n']
+ | otherwise = []
+
+ xs = gridRange fst
+ ys = gridRange snd
+ gridRange f = [min grid .. max grid]
+ where
+ min = minimum . map f
+ max = maximum . map f
+
+main = do
+ mapM_ printGrid . take 3 $ iterate step beacon
+ where
+ beacon = [(0, 0), (1, 0), (0, 1), (3, 3), (2, 3), (3, 2)]
+
+ printGrid :: Grid -> IO ()
+ printGrid grid = do
+ putStrLn $ formatGrid grid
+ putStrLn ""

0 comments on commit b521acc

Please sign in to comment.
Something went wrong with that request. Please try again.