57 lines
1.4 KiB
Haskell
57 lines
1.4 KiB
Haskell
module Main where
|
|
|
|
import qualified Data.IntMap as IM
|
|
import qualified Data.Map as M
|
|
|
|
type Coord = (Int, Int)
|
|
|
|
type Grid = M.Map Coord Char
|
|
|
|
type Path = IM.IntMap Coord
|
|
|
|
manhattan :: Coord -> Coord -> Int
|
|
manhattan (x1, y1) (x2, y2) = abs (x2 - x1) + abs (y2 - y1)
|
|
|
|
neighbours :: Coord -> [Coord]
|
|
neighbours (x, y) = [(x - 1, y), (x + 1, y), (x, y - 1), (x, y + 1)]
|
|
|
|
race :: Grid -> Coord -> Path
|
|
race grid = IM.fromList . zip [0 ..] . path (-1, -1)
|
|
where
|
|
path :: Coord -> Coord -> [Coord]
|
|
path prev c = case ch of
|
|
'E' -> [c, next]
|
|
'.' -> c : path c next
|
|
where
|
|
[(next, ch)] =
|
|
[ (n, ch)
|
|
| n <- neighbours c,
|
|
n /= prev,
|
|
let Just ch = n `M.lookup` grid,
|
|
ch /= '#'
|
|
]
|
|
|
|
nCheats :: Path -> Int -> Int
|
|
nCheats path n =
|
|
let l = IM.size path
|
|
in length
|
|
[ ()
|
|
| i <- [0 .. l - 1],
|
|
j <- [i + 100 .. l - 1],
|
|
let d = manhattan (path IM.! i) (path IM.! j),
|
|
d <= n,
|
|
100 <= j - i - d
|
|
]
|
|
|
|
main :: IO ()
|
|
main =
|
|
do
|
|
raw <- lines <$> readFile "./inputs/day20.in"
|
|
|
|
let [start] = [(x, y) | (y, row) <- zip [0 ..] raw, (x, ch) <- zip [0 ..] row, ch == 'S']
|
|
grid = M.fromList [((x, y), ch) | (y, row) <- zip [0 ..] raw, (x, ch) <- zip [0 ..] row]
|
|
path = race grid start
|
|
|
|
putStr "Part 1: " >> print (nCheats path 2)
|
|
putStr "Part 2: " >> print (nCheats path 20)
|