Day 22 - minor refactoring
This commit is contained in:
parent
22aad7dd66
commit
b7e9013d09
12
22a.hs
12
22a.hs
|
@ -6,9 +6,8 @@ type State = (Grid, (Int, Int), Direction, Int)
|
||||||
(%) = mod
|
(%) = mod
|
||||||
|
|
||||||
changeDirection :: Char -> Direction -> Direction
|
changeDirection :: Char -> Direction -> Direction
|
||||||
changeDirection c = case c of
|
changeDirection c =
|
||||||
'#' -> toEnum . (%4) . (+1) . fromEnum
|
toEnum . (%4) . (+ if c == '#' then 1 else 3) . fromEnum
|
||||||
'.' -> toEnum . (%4) . (+3) . fromEnum
|
|
||||||
|
|
||||||
incrementPosition :: Direction -> (Int, Int) -> (Int, Int)
|
incrementPosition :: Direction -> (Int, Int) -> (Int, Int)
|
||||||
incrementPosition dir (x, y) = case dir of
|
incrementPosition dir (x, y) = case dir of
|
||||||
|
@ -23,7 +22,7 @@ nextState (grid, pos, dir, count) =
|
||||||
newDir = changeDirection currNode dir
|
newDir = changeDirection currNode dir
|
||||||
newGrid = insert pos (if currNode == '.' then '#' else '.') grid
|
newGrid = insert pos (if currNode == '.' then '#' else '.') grid
|
||||||
newPos = incrementPosition newDir pos
|
newPos = incrementPosition newDir pos
|
||||||
newCount = count + if currNode == '.' then 1 else 0
|
newCount = count + fromEnum (currNode == '.')
|
||||||
in (newGrid, newPos, newDir, newCount)
|
in (newGrid, newPos, newDir, newCount)
|
||||||
|
|
||||||
parseRow :: (Int, [(Int, Char)]) -> Grid -> Grid
|
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 :: IO ()
|
||||||
main = do
|
main = do
|
||||||
input <- readFile "22.txt"
|
grid <- foldr parseRow empty . zip [-12..12] . map (zip [-12..12]) . lines <$> readFile "22.txt"
|
||||||
let grid = foldr parseRow empty $ zip [-12..12] . map (zip [-12..12]) . lines $ input
|
let (_, _, _, count) = iterate nextState (grid, (0, 0), North, 0) !! 10000
|
||||||
(_, _, _, count) = iterate nextState (grid, (0, 0), North, 0) !! 10000
|
|
||||||
print $ count
|
print $ count
|
40
22b.hs
40
22b.hs
|
@ -1,24 +1,14 @@
|
||||||
{-# LANGUAGE BangPatterns #-}
|
{-# LANGUAGE BangPatterns, ScopedTypeVariables #-}
|
||||||
import Data.HashMap.Strict (HashMap, lookupDefault, insert, empty)
|
import Data.HashMap.Strict (HashMap, lookupDefault, insert, empty)
|
||||||
|
|
||||||
data Direction = North | East | South | West deriving Enum
|
data Direction = North | East | South | West deriving (Bounded, Enum)
|
||||||
type Grid = HashMap (Int, Int) Char
|
data Node = Weakened | Infected | Flagged | Clean deriving (Bounded, Enum, Eq)
|
||||||
|
type Grid = HashMap (Int, Int) Node
|
||||||
type State = (Grid, (Int, Int), Direction, Int)
|
type State = (Grid, (Int, Int), Direction, Int)
|
||||||
(%) = mod
|
(%) = mod; infixl 5 %
|
||||||
|
|
||||||
changeDirection :: Char -> Direction -> Direction
|
succn :: forall a. (Bounded a, Enum a) => Int -> a -> a
|
||||||
changeDirection c = case c of
|
succn n = toEnum . (% 1 + fromEnum (maxBound :: a)) . (+ n) . fromEnum
|
||||||
'#' -> 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' -> '.'
|
|
||||||
|
|
||||||
incrementPosition :: Direction -> (Int, Int) -> (Int, Int)
|
incrementPosition :: Direction -> (Int, Int) -> (Int, Int)
|
||||||
incrementPosition dir (x, y) = case dir of
|
incrementPosition dir (x, y) = case dir of
|
||||||
|
@ -29,11 +19,11 @@ incrementPosition dir (x, y) = case dir of
|
||||||
|
|
||||||
nextState :: State -> State
|
nextState :: State -> State
|
||||||
nextState (grid, pos, dir, count) =
|
nextState (grid, pos, dir, count) =
|
||||||
let currNode = lookupDefault '.' pos grid
|
let currNode = lookupDefault Clean pos grid
|
||||||
newDir = changeDirection currNode dir
|
newDir = succn (fromEnum currNode) dir
|
||||||
newGrid = insert pos (changeNode currNode) grid
|
newGrid = insert pos (succn 1 currNode) grid
|
||||||
newPos = incrementPosition newDir pos
|
newPos = incrementPosition newDir pos
|
||||||
!newCount = count + if currNode == 'W' then 1 else 0
|
!newCount = count + fromEnum (currNode == Weakened)
|
||||||
in (newGrid, newPos, newDir, newCount)
|
in (newGrid, newPos, newDir, newCount)
|
||||||
|
|
||||||
stricterate :: Int -> State -> Int
|
stricterate :: Int -> State -> Int
|
||||||
|
@ -41,10 +31,12 @@ stricterate 0 (_, _, _, count) = count
|
||||||
stricterate n state = let !next = nextState state in stricterate (n-1) next
|
stricterate n state = let !next = nextState state in stricterate (n-1) next
|
||||||
|
|
||||||
parseRow :: (Int, [(Int, Char)]) -> Grid -> Grid
|
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 :: IO ()
|
||||||
main = do
|
main = do
|
||||||
input <- readFile "22.txt"
|
grid <- foldr parseRow empty . zip [-12..12] . map (zip [-12..12]) . lines <$> readFile "22.txt"
|
||||||
let grid = foldr parseRow empty $ zip [-12..12] . map (zip [-12..12]) . lines $ input
|
|
||||||
print $ stricterate 10000000 (grid, (0, 0), North, 0)
|
print $ stricterate 10000000 (grid, (0, 0), North, 0)
|
Loading…
Reference in New Issue