@@ -2,19 +2,51 @@ import Aoc2024.Utils
2
2
import Aoc2024.Day10.Examples
3
3
import Aoc2024.Day10.Parser
4
4
import Aoc2024.Day10.Types
5
+ open Std (HashSet HashMap)
5
6
6
7
-- Part 1
7
8
8
- private def solvePart1 (input : List Int) : Int := sorry
9
+ private def Point.orthogonalNeighbours (p : Point): List Point :=
10
+ let ⟨x, y⟩ := p
11
+ [⟨x, y - 1 ⟩, ⟨x + 1 , y⟩, ⟨x, y + 1 ⟩, ⟨x - 1 , y⟩]
12
+
13
+ private def solvePart1 (input : PuzzleInput) : Int :=
14
+ let heights := input.heights
15
+ let trailheads := heights.invert.getD 0 []
16
+ let getNeighbours (p : Point) (height : Height): List Point :=
17
+ p.orthogonalNeighbours.filter (λ neighbour => heights.get? neighbour == some height)
18
+ let score (trailhead : Point): Int :=
19
+ let rec findReachablePeaks (p : Point) : Nat -> List Point
20
+ | 0 => [p]
21
+ | n + 1 =>
22
+ let targetHeight := 9 - n
23
+ let neighbours := getNeighbours p targetHeight
24
+ neighbours.flatMap (findReachablePeaks · n)
25
+ findReachablePeaks trailhead 9 |>.toSet.size
26
+ trailheads.sumBy score
27
+
28
+ def parseAndSolvePart1 (s : String): Int := parseHeightMap s |> solvePart1
29
+
30
+ #guard parseAndSolvePart1 exampleInput == 36
9
31
10
- def parseAndSolvePart1 (s : String): Except String Int := parseInput s |>.map solvePart1
32
+ -- Part 2
11
33
12
- -- #guard parseAndSolvePart1 exampleInput == Except.ok -1
34
+ private def getNeighbours (heights : HashMap Point Height) (p : Point) (height : Height): List Point :=
35
+ p.orthogonalNeighbours.filter (λ neighbour => heights.get? neighbour == some height)
13
36
14
- -- Part 2
37
+ private partial def countPaths (heights : HashMap Point Height) (p : Point) (currentHeight : Height): Int :=
38
+ match currentHeight with
39
+ | 9 => 1
40
+ | _ =>
41
+ let nextHeight := currentHeight + 1
42
+ getNeighbours heights p nextHeight |>.sumBy (countPaths heights · nextHeight)
15
43
16
- private def solvePart2 (input : List Int) : Int := sorry
44
+ private def solvePart2 (input : PuzzleInput) : Int :=
45
+ let heights := input.heights
46
+ let trailheads := heights.invert.getD 0 []
47
+ let score (trailhead : Point): Int := countPaths heights trailhead 0
48
+ trailheads.sumBy score
17
49
18
- def parseAndSolvePart2 (s : String): Except String Int := parseInput s |>.map solvePart2
50
+ def parseAndSolvePart2 (s : String): Int := parseHeightMap s |> solvePart2
19
51
20
- -- #guard parseAndSolvePart2 exampleInput == Except.ok -1
52
+ #guard parseAndSolvePart2 exampleInput == 81
0 commit comments