@@ -135,3 +135,9 @@ executable day17
|
||||
hs-source-dirs: src
|
||||
main-is: Day17.hs
|
||||
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