@@ -15,30 +15,30 @@ parse s = Grid { items = M.fromList xs, lastNode = fst (last xs) }
15
15
enum :: [a ] -> [(Int , a )]
16
16
enum = zip [0 .. ]
17
17
18
- data Direction = L | R | U | D deriving (Eq , Ord )
18
+ data Direction = H | V deriving (Eq , Ord )
19
19
data Cell = Cell { node :: Node , direction :: Direction } deriving (Eq , Ord )
20
20
data Neighbour = Neighbour { cell :: Cell , distance :: Int }
21
21
22
22
neighbours :: Grid Int -> [Int ] -> Cell -> [Neighbour ]
23
23
neighbours Grid { items } range = concat . adjacent
24
24
where
25
- adjacent Cell { node = (x, y), direction = d }
26
- | d `elem` [L , R ] = [cells (\ m -> Cell (x, y - m) U ),
27
- cells (\ m -> Cell (x, y + m) D )]
28
- | otherwise = [cells (\ m -> Cell (x - m, y) R ),
29
- cells (\ m -> Cell (x + m, y) L )]
25
+ adjacent Cell { node = (x, y), direction } = case direction of
26
+ H -> [cells (\ m -> Cell (x, y - m) V ), cells (\ m -> Cell (x, y + m) V )]
27
+ V -> [cells (\ m -> Cell (x - m, y) H ), cells (\ m -> Cell (x + m, y) H )]
30
28
cells mkCell = snd $ foldl (mkNeighbour mkCell) (0 , [] ) [1 .. maximum range]
31
- mkNeighbour mkCell (d, xs) m = let cell = mkCell m in case M. lookup (node cell) items of
32
- Just d2 -> (d + d2, if m `elem` range then Neighbour cell (d + d2) : xs else xs)
33
- _ -> (d, xs)
29
+ mkNeighbour mkCell (d, xs) m =
30
+ let c = mkCell m in case M. lookup (node c) items of
31
+ Just d2 -> let dc = d + d2
32
+ in (dc, if m `elem` range then Neighbour c dc : xs else xs)
33
+ _ -> (d, xs)
34
34
35
35
shortestPath :: [Int ] -> Grid Int -> Int
36
36
shortestPath moveRange grid@ Grid { lastNode } = go startDist S. empty startQ
37
37
where
38
- -- Start in both directions so that we never have to go straight and can
39
- -- just always turn. This way, we don't even need to track moves.
40
- startCells = [Cell { node = (0 , 0 ), direction = L },
41
- Cell { node = (0 , 0 ), direction = D }]
38
+ -- Start on both axes so that we never have to go straight and can just
39
+ -- always turn. This way, we don't even need to track moves.
40
+ startCells = [Cell { node = (0 , 0 ), direction = H },
41
+ Cell { node = (0 , 0 ), direction = V }]
42
42
startDist = M. fromList $ zip startCells [0 , 0 ]
43
43
startQ = S. fromList $ zip [0 , 0 ] startCells
44
44
isEnd Cell { node } = node == lastNode
0 commit comments