@@ -135,3 +135,9 @@ executable day17
|
|||||||
hs-source-dirs: src
|
hs-source-dirs: src
|
||||||
main-is: Day17.hs
|
main-is: Day17.hs
|
||||||
build-depends: libaoc
|
build-depends: libaoc
|
||||||
|
|
||||||
|
executable day18
|
||||||
|
import: common
|
||||||
|
hs-source-dirs: src
|
||||||
|
main-is: Day18.hs
|
||||||
|
build-depends: libaoc, containers
|
||||||
|
71
src/Day18.hs
Normal file
71
src/Day18.hs
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
module Main where
|
||||||
|
|
||||||
|
import qualified AoC as A
|
||||||
|
import Data.Maybe (fromJust, isJust)
|
||||||
|
import qualified Data.Set as S
|
||||||
|
import Text.Parsec (char, digit, many1, newline, parse, sepEndBy1)
|
||||||
|
import Text.Parsec.String (Parser)
|
||||||
|
|
||||||
|
type Coord = (Int, Int)
|
||||||
|
|
||||||
|
type Queue = S.Set (Int, Coord)
|
||||||
|
|
||||||
|
parseBytes :: Parser [Coord]
|
||||||
|
parseBytes =
|
||||||
|
( (,)
|
||||||
|
<$> (read <$> many1 digit)
|
||||||
|
<*> (char ',' >> (read <$> many1 digit))
|
||||||
|
)
|
||||||
|
`sepEndBy1` newline
|
||||||
|
|
||||||
|
width :: Int
|
||||||
|
height :: Int
|
||||||
|
(width, height) = (71, 71)
|
||||||
|
|
||||||
|
oob :: Coord -> Bool
|
||||||
|
oob (x, y) = x < 0 || x >= width || y < 0 || y >= height
|
||||||
|
|
||||||
|
neighbours :: Coord -> [Coord]
|
||||||
|
neighbours (x, y) = [(x - 1, y), (x + 1, y), (x, y - 1), (x, y + 1)]
|
||||||
|
|
||||||
|
dijkstra :: Coord -> S.Set Coord -> Maybe Int
|
||||||
|
dijkstra c obs = travel (S.singleton (0, c)) S.empty
|
||||||
|
where
|
||||||
|
travel :: Queue -> S.Set Coord -> Maybe Int
|
||||||
|
travel q vis = do
|
||||||
|
((dis, c), q') <- S.minView q
|
||||||
|
|
||||||
|
let ns = neighbours c
|
||||||
|
q'' = foldr S.insert q' . map (dis + 1,) . filter (not . invalid) $ ns
|
||||||
|
vis' = S.insert c vis
|
||||||
|
|
||||||
|
if c == (width - 1, height - 1)
|
||||||
|
then Just dis
|
||||||
|
else travel q'' vis'
|
||||||
|
where
|
||||||
|
invalid :: Coord -> Bool
|
||||||
|
invalid c = c `S.member` vis || c `S.member` obs || oob c
|
||||||
|
|
||||||
|
part1 :: [Coord] -> Int
|
||||||
|
part1 obs = fromJust $ dijkstra (0, 0) (S.fromList . take 1024 $ obs)
|
||||||
|
|
||||||
|
part2 :: [Coord] -> Coord
|
||||||
|
part2 obs =
|
||||||
|
(!!) obs $
|
||||||
|
head
|
||||||
|
[ i
|
||||||
|
| i <- [n, n - 1 .. 1],
|
||||||
|
isJust $ dijkstra (0, 0) (S.fromList $ take i obs)
|
||||||
|
]
|
||||||
|
where
|
||||||
|
n = length obs
|
||||||
|
|
||||||
|
main :: IO ()
|
||||||
|
main =
|
||||||
|
do
|
||||||
|
raw <- readFile "./inputs/day18.in"
|
||||||
|
|
||||||
|
let bytes = A.extract $ parse parseBytes "" raw
|
||||||
|
|
||||||
|
putStr "Part 1: " >> print (part1 bytes)
|
||||||
|
putStr "Part 2: " >> print (part2 bytes)
|
Reference in New Issue
Block a user