diff --git a/22a.hs b/22a.hs index 40a8999..f3dedb3 100644 --- a/22a.hs +++ b/22a.hs @@ -6,9 +6,8 @@ type State = (Grid, (Int, Int), Direction, Int) (%) = mod changeDirection :: Char -> Direction -> Direction -changeDirection c = case c of - '#' -> toEnum . (%4) . (+1) . fromEnum - '.' -> toEnum . (%4) . (+3) . fromEnum +changeDirection c = + toEnum . (%4) . (+ if c == '#' then 1 else 3) . fromEnum incrementPosition :: Direction -> (Int, Int) -> (Int, Int) incrementPosition dir (x, y) = case dir of @@ -23,7 +22,7 @@ nextState (grid, pos, dir, count) = newDir = changeDirection currNode dir newGrid = insert pos (if currNode == '.' then '#' else '.') grid newPos = incrementPosition newDir pos - newCount = count + if currNode == '.' then 1 else 0 + newCount = count + fromEnum (currNode == '.') in (newGrid, newPos, newDir, newCount) parseRow :: (Int, [(Int, Char)]) -> Grid -> Grid @@ -31,7 +30,6 @@ parseRow (y, xs) grid = foldr (\(x, c) currGrid -> insert (x, y) c currGrid) gri main :: IO () main = do - input <- readFile "22.txt" - let grid = foldr parseRow empty $ zip [-12..12] . map (zip [-12..12]) . lines $ input - (_, _, _, count) = iterate nextState (grid, (0, 0), North, 0) !! 10000 + grid <- foldr parseRow empty . zip [-12..12] . map (zip [-12..12]) . lines <$> readFile "22.txt" + let (_, _, _, count) = iterate nextState (grid, (0, 0), North, 0) !! 10000 print $ count \ No newline at end of file diff --git a/22b.hs b/22b.hs index 989a036..b5722d7 100644 --- a/22b.hs +++ b/22b.hs @@ -1,24 +1,14 @@ -{-# LANGUAGE BangPatterns #-} +{-# LANGUAGE BangPatterns, ScopedTypeVariables #-} import Data.HashMap.Strict (HashMap, lookupDefault, insert, empty) -data Direction = North | East | South | West deriving Enum -type Grid = HashMap (Int, Int) Char +data Direction = North | East | South | West deriving (Bounded, Enum) +data Node = Weakened | Infected | Flagged | Clean deriving (Bounded, Enum, Eq) +type Grid = HashMap (Int, Int) Node type State = (Grid, (Int, Int), Direction, Int) -(%) = mod +(%) = mod; infixl 5 % -changeDirection :: Char -> Direction -> Direction -changeDirection c = case c of - '#' -> toEnum . (%4) . (+1) . fromEnum - 'F' -> toEnum . (%4) . (+2) . fromEnum - '.' -> toEnum . (%4) . (+3) . fromEnum - 'W' -> id - -changeNode :: Char -> Char -changeNode c = case c of - '.' -> 'W' - 'W' -> '#' - '#' -> 'F' - 'F' -> '.' +succn :: forall a. (Bounded a, Enum a) => Int -> a -> a +succn n = toEnum . (% 1 + fromEnum (maxBound :: a)) . (+ n) . fromEnum incrementPosition :: Direction -> (Int, Int) -> (Int, Int) incrementPosition dir (x, y) = case dir of @@ -29,11 +19,11 @@ incrementPosition dir (x, y) = case dir of nextState :: State -> State nextState (grid, pos, dir, count) = - let currNode = lookupDefault '.' pos grid - newDir = changeDirection currNode dir - newGrid = insert pos (changeNode currNode) grid + let currNode = lookupDefault Clean pos grid + newDir = succn (fromEnum currNode) dir + newGrid = insert pos (succn 1 currNode) grid newPos = incrementPosition newDir pos - !newCount = count + if currNode == 'W' then 1 else 0 + !newCount = count + fromEnum (currNode == Weakened) in (newGrid, newPos, newDir, newCount) stricterate :: Int -> State -> Int @@ -41,10 +31,12 @@ stricterate 0 (_, _, _, count) = count stricterate n state = let !next = nextState state in stricterate (n-1) next parseRow :: (Int, [(Int, Char)]) -> Grid -> Grid -parseRow (y, xs) grid = foldr (\(x, c) currGrid -> insert (x, y) c currGrid) grid xs +parseRow (y, xs) grid = foldr (\(x, c) currGrid -> insert (x, y) (charToEnum c) currGrid) grid xs + where charToEnum c = case c of + '.' -> Clean + '#' -> Infected main :: IO () main = do - input <- readFile "22.txt" - let grid = foldr parseRow empty $ zip [-12..12] . map (zip [-12..12]) . lines $ input + grid <- foldr parseRow empty . zip [-12..12] . map (zip [-12..12]) . lines <$> readFile "22.txt" print $ stricterate 10000000 (grid, (0, 0), North, 0) \ No newline at end of file