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.HashMap.Strict as M
11 type Point = (Int, Int)
13 data Flag = Clean | Weakened | Infected | Flagged deriving (Show, Eq)
15 type Infection = M.HashMap Point Flag
17 data Direction = Up | Right | Down | Left deriving (Show, Eq, Enum)
25 delta :: Direction -> Point
31 (+:) :: Point -> Point -> Point
32 (+:) (r, c) (dr, dc) = (r + dr, c + dc)
34 data World = World { infected :: Infection
36 , direction :: Direction
37 , infectionCount :: Int
43 text <- readFile "data/advent22.txt"
45 print $ infectionCount $ progress 10000000 $ initialWorld grid
47 initialWorld :: [String] -> World
48 initialWorld grid = World
49 { infected = initialInfected grid
50 , position = initialPosition grid
55 initialInfected :: [String] -> Infection
56 initialInfected g = M.fromList [ ((r, c), Infected)
57 | r <- [0..(length g - 1)]
58 , c <- [0..((length . head) g - 1)]
61 initialPosition :: [String] -> Point
62 initialPosition g = (length g `div` 2, (length . head) g `div` 2)
65 progress :: Int -> World -> World
66 -- progress n = (!! n) . iterate step
67 progress 0 world = world
68 progress n world = progress (n - 1) world'
69 where !world' = step world
72 step :: World -> World
73 step world = World { infected = inf', position = pos', direction = dir'
74 , infectionCount = ic'}
75 where !here = position world
76 !stateHere = M.lookupDefault Clean here (infected world)
77 !dir' = case stateHere of
78 Clean -> leftOf (direction world)
79 Weakened -> direction world
80 Infected -> rightOf (direction world)
81 Flagged -> rightOf (rightOf (direction world))
82 !stateHere' = case stateHere of
87 !inf' = M.insert here stateHere' (infected world)
88 !ic' = if stateHere' == Infected then infectionCount world + 1
89 else infectionCount world
90 !pos' = here +: delta dir'