stevenrwalter

Kata Game of Life

Nov 25th, 2013
242
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import Data.List (nub)
  2.  
  3. type Coord = (Int, Int)
  4. type Grid = [Coord]
  5.  
  6. alive :: Grid -> Coord -> Bool
  7. alive grid coord = coord `elem` grid
  8.  
  9. data Cell = Alive | Dead deriving Eq
  10.  
  11. cellNextState :: Cell -> Int -> Cell
  12. cellNextState Dead 3 = Alive
  13. cellNextState Dead _ = Dead
  14.  
  15. cellNextState Alive neighbors
  16.     | neighbors < 2 = Dead
  17.     | neighbors > 3 = Dead
  18.     | otherwise = Alive
  19.  
  20. adjacentCoords :: Coord -> [Coord]
  21. adjacentCoords (x0,y0) =
  22.     [(x,y) | x <- [x0-1..x0+1], y <- [y0-1..y0+1]]
  23.  
  24. count p = length . filter p
  25.  
  26. countNeighbors :: Grid -> Coord -> Int
  27. countNeighbors grid coord =
  28.     count (alive grid) $ filter (/= coord) $ adjacentCoords coord
  29.  
  30. nextGenCellAlive :: Grid -> Coord -> Bool
  31. nextGenCellAlive grid coord =
  32.     cellNextState cell (countNeighbors grid coord) == Alive
  33.     where cell =
  34.         if alive grid coord then Alive else Dead
  35.  
  36. nextGeneration :: Grid -> Grid
  37. nextGeneration grid =
  38.     nub $ filter (nextGenCellAlive grid) consideredCoords
  39.     where consideredCoords =
  40.         nub $ concatMap adjacentCoords grid
  41.  
  42. readGrid :: String -> Int -> Int -> Grid
  43. readGrid s 0 _ = []
  44. readGrid s rows cols =
  45.     readRow (take cols s) cols rows ++ readGrid (drop (cols+1) s) (rows-1) cols
  46.  
  47. readRow :: String -> Int -> Int -> Grid
  48. readRow s 0 _ = []
  49. readRow (x:xs) cols row =
  50.     if x == '*' then
  51.         readRow xs (cols-1) row ++ [(cols-1,row-1)]
  52.     else
  53.         readRow xs (cols-1) row
  54.  
  55. rowToStr :: Grid -> Int -> Int -> String
  56. rowToStr g _ 0 = ""
  57. rowToStr g row cols =
  58.     char ++ rowToStr g row (cols-1)
  59.     where char =
  60.         if alive g (cols-1,row-1) then "*" else "."
  61.  
  62. gridToStr :: Grid -> Int -> Int -> [String]
  63. gridToStr g 0 _ = []
  64. gridToStr g rows cols =
  65.     [rowToStr g rows cols] ++ gridToStr g (rows-1) cols
  66.  
  67. main = do
  68.     header <- getLine
  69.     s <- getContents
  70.     let x = words header
  71.     let rows = read (x !! 0)
  72.     let cols = read (x !! 1)
  73.     let grid = readGrid s rows cols
  74.     putStrLn $ (show rows) ++ " " ++ (show cols)
  75.     mapM_ putStrLn $ gridToStr (nextGeneration grid) rows cols
Advertisement
Add Comment
Please, Sign In to add comment