X-Git-Url: https://git.njae.me.uk/?a=blobdiff_plain;f=src%2Fadvent22%2Fadvent22bh.hs;fp=src%2Fadvent22%2Fadvent22bh.hs;h=e52ee55e825adeb881bb2a8e398c692f44abc9e4;hb=ae3315403a3d303f4f1ea73147fc16f3568781f3;hp=0000000000000000000000000000000000000000;hpb=0c7f1b478186169e9ef06ceb669a0c5f489a4849;p=advent-of-code-17.git diff --git a/src/advent22/advent22bh.hs b/src/advent22/advent22bh.hs new file mode 100644 index 0000000..e52ee55 --- /dev/null +++ b/src/advent22/advent22bh.hs @@ -0,0 +1,90 @@ +{-# LANGUAGE NegativeLiterals #-} +{-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE TypeFamilies #-} +{-# LANGUAGE BangPatterns #-} + +import Prelude hiding (Left, Right) +import Data.List +import qualified Data.HashMap.Strict as M + +type Point = (Int, Int) + +data Flag = Clean | Weakened | Infected | Flagged deriving (Show, Eq) + +type Infection = M.HashMap Point Flag + +data Direction = Up | Right | Down | Left deriving (Show, Eq, Enum) + +leftOf Up = Left +leftOf x = pred x + +rightOf Left = Up +rightOf x = succ x + +delta :: Direction -> Point +delta Up = (-1, 0) +delta Right = (0, 1) +delta Down = (1, 0) +delta Left = (0, -1) + +(+:) :: Point -> Point -> Point +(+:) (r, c) (dr, dc) = (r + dr, c + dc) + +data World = World { infected :: Infection + , position :: Point + , direction :: Direction + , infectionCount :: Int + } deriving (Eq, Show) + + +main :: IO () +main = do + text <- readFile "data/advent22.txt" + let grid = lines text + print $ infectionCount $ progress 10000000 $ initialWorld grid + +initialWorld :: [String] -> World +initialWorld grid = World + { infected = initialInfected grid + , position = initialPosition grid + , direction = Up + , infectionCount = 0 + } + +initialInfected :: [String] -> Infection +initialInfected g = M.fromList [ ((r, c), Infected) + | r <- [0..(length g - 1)] + , c <- [0..((length . head) g - 1)] + , g!!r!!c == '#'] + +initialPosition :: [String] -> Point +initialPosition g = (length g `div` 2, (length . head) g `div` 2) + + +progress :: Int -> World -> World +-- progress n = (!! n) . iterate step +progress 0 world = world +progress n world = progress (n - 1) world' + where !world' = step world + + +step :: World -> World +step world = World { infected = inf', position = pos', direction = dir' + , infectionCount = ic'} + where !here = position world + !stateHere = M.lookupDefault Clean here (infected world) + !dir' = case stateHere of + Clean -> leftOf (direction world) + Weakened -> direction world + Infected -> rightOf (direction world) + Flagged -> rightOf (rightOf (direction world)) + !stateHere' = case stateHere of + Clean -> Weakened + Weakened -> Infected + Infected -> Flagged + Flagged -> Clean + !inf' = M.insert here stateHere' (infected world) + !ic' = if stateHere' == Infected then infectionCount world + 1 + else infectionCount world + !pos' = here +: delta dir' \ No newline at end of file