import Control.Applicative import Data.List ((\\)) import Data.Maybe (fromMaybe) import Matrix type Cell = Int type Grid = Mat Cell -- | Print a grid gprint :: Grid -> IO () gprint = putStrLn . map replace . show where replace '1' = '■' replace '0' = '.' replace a = a -- | Get the state of a cell -- 0 when out of the grid (!) :: Grid -> Pos -> Cell (Mat g) ! (x, y) = fromMaybe 0 (g ?? y >>= (?? x)) -- | List of neighbours cells near :: Grid -> Pos -> [Cell] near g (x, y) = map state $ neighbours \\ [(0,0)] where neighbours = liftA2 (,) [-1..1] [-1..1] state (x', y') = g ! (x+x', y+y') -- | Find if a cell will be alive in the next generation alive :: Grid -> Pos -> Cell alive g p | v == 0 && n == 3 = 1 | v == 1 && (n == 2 || n == 3) = 1 | otherwise = 0 where (n, v) = (sum (near g p), g ! p) -- | Compute next generation next :: Grid -> Grid next g = alive g <$> indeces g main :: IO () main = mapM_ gprint (iterate next grid) grid = Mat [ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] , [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0] , [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0] , [0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0] , [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] , [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] , [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] ]