@@ -116,3 +116,9 @@ executable day14
|
|||||||
build-depends:
|
build-depends:
|
||||||
, containers
|
, containers
|
||||||
, libaoc
|
, libaoc
|
||||||
|
|
||||||
|
executable day15
|
||||||
|
import: common
|
||||||
|
hs-source-dirs: src
|
||||||
|
main-is: Day15.hs
|
||||||
|
build-depends: containers
|
||||||
|
75
src/Day15.hs
Normal file
75
src/Day15.hs
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
module Main where
|
||||||
|
|
||||||
|
import qualified Data.Map as M
|
||||||
|
|
||||||
|
type Coord = (Int, Int)
|
||||||
|
|
||||||
|
type Grid = M.Map Coord Char
|
||||||
|
|
||||||
|
data Dir = East | West | North | South deriving (Eq)
|
||||||
|
|
||||||
|
next :: Coord -> Dir -> Coord
|
||||||
|
next (x, y) East = (x + 1, y)
|
||||||
|
next (x, y) West = (x - 1, y)
|
||||||
|
next (x, y) North = (x, y - 1)
|
||||||
|
next (x, y) South = (x, y + 1)
|
||||||
|
|
||||||
|
dir :: Char -> Dir
|
||||||
|
dir '>' = East
|
||||||
|
dir '<' = West
|
||||||
|
dir '^' = North
|
||||||
|
dir 'v' = South
|
||||||
|
|
||||||
|
widen :: Char -> [Char]
|
||||||
|
widen '#' = "##"
|
||||||
|
widen 'O' = "[]"
|
||||||
|
widen '.' = ".."
|
||||||
|
widen '@' = "@."
|
||||||
|
|
||||||
|
parse :: [[Char]] -> (Coord, Grid)
|
||||||
|
parse raw =
|
||||||
|
let [bot] = [(x, y) | (y, row) <- zip [0 ..] raw, (x, ch) <- zip [0 ..] row, ch == '@']
|
||||||
|
raw' = [((x, y), ch) | (y, row) <- zip [0 ..] raw, (x, ch) <- zip [0 ..] row]
|
||||||
|
grid = M.insert bot '.' $ M.fromList raw'
|
||||||
|
in (bot, grid)
|
||||||
|
|
||||||
|
move :: [Dir] -> Coord -> Grid -> Grid
|
||||||
|
move [] _ grid = grid
|
||||||
|
move (d : ds) c grid = case move' c d grid of
|
||||||
|
Nothing -> move ds c grid
|
||||||
|
Just grid' -> move ds (next c d) grid'
|
||||||
|
where
|
||||||
|
move' :: Coord -> Dir -> Grid -> Maybe Grid
|
||||||
|
move' c d grid = case M.lookup n grid of
|
||||||
|
Just '.' -> Just grid
|
||||||
|
Just '#' -> Nothing
|
||||||
|
Just 'O' -> push n d <$> move' n d grid
|
||||||
|
Just '[' | d `elem` [East, West] -> push n d <$> move' n d grid
|
||||||
|
Just '[' -> push n d . push r d <$> (move' n d grid >>= move' r d)
|
||||||
|
Just ']' | d `elem` [East, West] -> push n d <$> move' n d grid
|
||||||
|
Just ']' -> push n d . push l d <$> (move' n d grid >>= move' l d)
|
||||||
|
_ -> error "what?"
|
||||||
|
where
|
||||||
|
n :: Coord
|
||||||
|
n@(x, y) = next c d
|
||||||
|
r = (x + 1, y)
|
||||||
|
l = (x - 1, y)
|
||||||
|
|
||||||
|
push :: Coord -> Dir -> Grid -> Grid
|
||||||
|
push c d grid = case M.lookup c grid of
|
||||||
|
Just ch -> M.insert (next c d) ch $ M.insert c '.' grid
|
||||||
|
Nothing -> error "what?"
|
||||||
|
|
||||||
|
gps :: Grid -> Char -> Int
|
||||||
|
gps grid char = sum [y * 100 + x | ((x, y), ch) <- M.assocs grid, ch == char]
|
||||||
|
|
||||||
|
main :: IO ()
|
||||||
|
main =
|
||||||
|
do
|
||||||
|
(raw, map dir . concat -> moves) <- break null . lines <$> readFile "./inputs/day15.in"
|
||||||
|
|
||||||
|
let (bot1, grid1) = parse raw
|
||||||
|
(bot2, grid2) = parse . map (concatMap widen) $ raw
|
||||||
|
|
||||||
|
putStr "Part 1: " >> print (gps (move moves bot1 grid1) 'O')
|
||||||
|
putStr "Part 2: " >> print (gps (move moves bot2 grid2) '[')
|
Reference in New Issue
Block a user