1 {-# LANGUAGE NegativeLiterals #-}
2 {-# LANGUAGE FlexibleContexts #-}
3 {-# LANGUAGE OverloadedStrings #-}
4 {-# LANGUAGE TypeFamilies #-}
5 {-# LANGUAGE BangPatterns #-}
7 import Prelude hiding (Left, Right)
9 import qualified Data.Set as S
11 type Point = (Int, Int)
12 type Infection = S.Set Point
14 data Direction = Up | Right | Down | Left deriving (Show, Eq, Enum)
22 delta :: Direction -> Point
28 (+:) :: Point -> Point -> Point
29 (+:) (r, c) (dr, dc) = (r + dr, c + dc)
31 data World = World { infected :: Infection
33 , direction :: Direction
34 , infectionCount :: Int
40 text <- readFile "data/advent22.txt"
42 print $ infectionCount $ progress 10000 $ initialWorld grid
44 initialWorld :: [String] -> World
45 initialWorld grid = World
46 { infected = initialInfected grid
47 , position = initialPosition grid
52 initialInfected :: [String] -> Infection
53 initialInfected g = S.fromList [(r, c) | r <- [0..(length g - 1)]
54 , c <- [0..((length . head) g - 1)]
57 initialPosition :: [String] -> Point
58 initialPosition g = (length g `div` 2, (length . head) g `div` 2)
61 progress :: Int -> World -> World
62 progress n = (!! n) . iterate step
64 step :: World -> World
65 step world = World { infected = inf', position = pos', direction = dir'
66 , infectionCount = ic'}
67 where here = position world
68 infectedHere = here `S.member` infected world
69 dir' = if infectedHere then rightOf (direction world)
70 else leftOf (direction world)
71 inf' = if infectedHere then S.delete here $ infected world
72 else S.insert here $ infected world
73 ic' = if infectedHere then infectionCount world
74 else infectionCount world + 1
75 pos' = here +: delta dir'