X-Git-Url: https://git.njae.me.uk/?p=advent-of-code-19.git;a=blobdiff_plain;f=advent24%2Fsrc%2Fadvent24v.hs;fp=advent24%2Fsrc%2Fadvent24v.hs;h=7707dee81eef4f71c072bff7c6a948d1e8872798;hp=0000000000000000000000000000000000000000;hb=887e4c9e5607a078269338087bac136c0a143d28;hpb=387c497d86487090d551a398247936ec0c55bc08 diff --git a/advent24/src/advent24v.hs b/advent24/src/advent24v.hs new file mode 100644 index 0000000..7707dee --- /dev/null +++ b/advent24/src/advent24v.hs @@ -0,0 +1,78 @@ + + +import Control.Concurrent (threadDelay) + + +import Data.Functor.Compose (Compose(..)) +import Data.Vector (Vector, (!), generate) +import Data.Bool (bool) +import Data.Distributive (Distributive(..)) +import Data.Functor.Rep (Representable(..), distributeRep) +import Data.Functor.Identity (Identity(..)) +import Control.Comonad.Representable.Store (Store(..), StoreT(..), store, experiment) +import Control.Comonad (Comonad(..)) +import Control.Monad (forM_) + +type Coord = (Int, Int) +type Grid = Store (Compose Vector Vector) Bool +type Rule = Grid -> Bool + +instance Distributive Vector where + distribute = distributeRep + +instance Representable Vector where + type Rep Vector = Int + index v i = v ! (i `mod` gridSize) + tabulate = generate gridSize + +gridSize :: Int +gridSize = 20 + +neighbourCoords :: [Coord] +neighbourCoords = [(x, y) | x <- [-1, 0, 1], y <- [-1, 0, 1], (x, y) /= (0, 0)] + +addCoords :: Coord -> Coord -> Coord +addCoords (x, y) (x', y') = (x + x', y + y') + +basicRule :: Rule +basicRule g = numNeighboursAlive == 3 || (alive && numNeighboursAlive == 2) + where + alive = extract g + neighbours = experiment (at neighbourCoords) g + numNeighboursAlive = length (filter id neighbours) + +step :: Rule -> Grid -> Grid +step = extend + +render :: Grid -> String +render (StoreT (Identity (Compose g)) _) = foldMap ((++ "\n") . foldMap (bool "." "#")) g + +mkGrid :: [Coord] -> Grid +mkGrid xs = store (`elem` xs) (0, 0) + +at :: [Coord] -> Coord -> [Coord] +coords `at` origin = map (addCoords origin) coords + +glider, blinker, beacon :: [Coord] +glider = [(1, 0), (2, 1), (0, 2), (1, 2), (2, 2)] +blinker = [(0, 0), (1, 0), (2, 0)] +beacon = [(0, 0), (1, 0), (0, 1), (3, 2), (2, 3), (3, 3)] + + + + + + +tickTime :: Int +tickTime = 200000 + +start :: Grid +start = mkGrid $ + glider `at` (0, 0) + ++ beacon `at` (15, 5) + +main :: IO () +main = forM_ (iterate (step basicRule) start) $ \grid -> do + putStr "\ESC[2J" -- Clear terminal screen + putStrLn (render grid) + threadDelay tickTime \ No newline at end of file