7 | directions : LazyList (Integer, Integer)
18 | grid : Grid rows cols Nat
22 | show (MkInput rows cols grid) =
23 | unlines . toList . map (joinBy "" . toList . map show) $
grid
25 | parseInput : String -> Maybe Input
27 | (
rows ** cols ** grid)
<- stringTo2D str
28 | grid <- traverse id . map (traverse parsePositive . map singleton) $
grid
29 | pure $
MkInput rows cols grid
31 | trailheads : (input : Input) -> LazyList (Coord input.rows input.cols)
33 | map fst . filter ((== (the Nat 0)) . snd) . flat $
input.grid
35 | accessibleEnds : (input : Input) -> (start : Coord input.rows input.cols)
36 | -> LazyList (Coord input.rows input.cols)
37 | accessibleEnds input start = do
38 | let canidates = mapMaybe (step start) directions
39 | let current = start `index` input.grid
40 | next_pos <- canidates
41 | let next = next_pos `index` input.grid
42 | if next == current + 1
45 | else accessibleEnds input next_pos
48 | trailheadScore : (input : Input) -> Coord input.rows input.cols -> Nat
49 | trailheadScore input start = length . nub . toList . accessibleEnds input $
start
51 | accessibleTrails : (input : Input) -> (start : Coord input.rows input.cols)
52 | -> LazyList (List (Coord input.rows input.cols))
53 | accessibleTrails input start = do
54 | let canidates = mapMaybe (step start) directions
55 | let current = start `index` input.grid
56 | next_pos <- canidates
57 | let next = next_pos `index` input.grid
58 | if next == current + 1
60 | then [[start, next_pos]]
62 | rest <- accessibleTrails input next_pos
66 | trailheadRating : (input : Input) -> Coord input.rows input.cols -> Nat
67 | trailheadRating input start =
68 | length . nub . toList . accessibleTrails input $
start
71 | part1 : String -> IO (String, Input)
73 | Just input <- pure $
parseInput str
75 | let trailhead_scores = map (trailheadScore input) $
trailheads input
76 | pure $
(show . sum $
trailhead_scores, input)
79 | part2 : Input -> String -> IO String
80 | part2 input str = do
81 | let accessible_trails = map (trailheadRating input) $
trailheads input
82 | pure . show . sum $
accessible_trails