Skip to content

Instantly share code, notes, and snippets.

@anargu
Created March 2, 2021 03:01
Show Gist options
  • Save anargu/ddacadc2d185311a286410b0988a3675 to your computer and use it in GitHub Desktop.
Save anargu/ddacadc2d185311a286410b0988a3675 to your computer and use it in GitHub Desktop.
asciified_tiny_gol
...........
...oo.oo...
...oo.oo...
....o.o....
..o.o.o.o..
..o.o.o.o..
..oo...oo..
...........
...........
import System.Environment
import Control.Concurrent
import Data.Maybe
-- Any live cell with fewer than two live neighbors dies, as if by under-population.
-- Any live cell with two or three live neighbors lives on to the next generation.
-- Any live cell with more than three live neighbors dies, as if by overpopulation.
-- Any dead cell with exactly three live neighbors becomes a live cell, as if by reproduction.
type Point = (Int, Int)
type Status = Bool
type Node = (Point, Status)
type Game = [Node]
type Generation = Integer
isCharLiving :: Char -> Bool
isCharLiving char
| char == 'o' = True
| otherwise = False
makeRow :: String -> Int -> [Node]
makeRow row y =
[((x,y), isCharLiving $ row !! x) | x <- [0..length row - 1]]
prepareData :: [String] -> Game
prepareData rawData =
concat [ makeRow (rawData !! y) y | y <- [0..length rawData - 1]]
nextState :: Game -> Game
nextState game = map (`makeNode` game) game
makeNode :: Node -> Game -> Node
makeNode node game =
(
fst node,
nextNodeState (aliveNeighbours game node directions 0) (snd node)
)
nextNodeState :: Integer -> Bool -> Bool
nextNodeState aliveNeighbours status
| aliveNeighbours == 3 && not status = True
| aliveNeighbours == 2 && status = True
| aliveNeighbours == 3 && status = True
| otherwise = False
aliveNeighbours :: Game -> Node -> [Point] -> Integer -> Integer
aliveNeighbours game ((x,y), status) dirs count
| null dirs = count
| isAlive game (x + fst (head dirs), y + snd (head dirs))
= aliveNeighbours game ((x, y), status) (tail dirs) (count + 1)
| otherwise = aliveNeighbours game ((x, y), status) (tail dirs) count
directions :: [Point]
directions = [(0,-1), (1,-1), (1,0), (1,1), (0,1), (-1,1), (-1,0), (-1,-1)]
isAlive :: Game -> Point -> Bool
isAlive game node
| isNothing(getCell node game) = False
| snd(fromJust(getCell node game)) = True
| otherwise = False
type Cell = Node
getCell :: Point -> Game -> Maybe Node
getCell pos [] = Nothing
getCell pos (((x,y), status) : rest)
| pos == (x,y) = Just ((x,y), status)
| otherwise = getCell pos rest
main :: IO()
main = do
rawData <- readFile "./pentadecathlon"
get (prepareData $ lines rawData)
representation :: Status -> String
representation cell
| cell = "[●]"
| otherwise = "[ ]"
putCell :: Cell -> IO()
putCell cell
| fst (fst cell) == 0 = putStr $ "\n" ++ representation (snd cell)
| otherwise = putStr $ representation (snd cell)
clearScreen :: IO()
clearScreen = putStr "\ESC[2J"
get :: Game -> IO()
get game = do
sequence_ [putCell cell | cell <- game]
clearScreen
threadDelay 200000
get (nextState game)
-- input file pentadecathlon:
-- ...........
-- ...oo.oo...
-- ...oo.oo...
-- ....o.o....
-- ..o.o.o.o..
-- ..o.o.o.o..
-- ..oo...oo..
-- ...........
-- ...........
-- execute this: ghc -o tiny_gol src/tiny_gol.hs && ./tiny_gol
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment