Skip to content

Commit 3f5e869

Browse files
committed
Day 5
1 parent 3bcef59 commit 3f5e869

File tree

8 files changed

+1515
-13
lines changed

8 files changed

+1515
-13
lines changed

Aoc2024/Day05/Examples.lean

+28-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,29 @@
11
def exampleInput :=
2-
"..."
2+
"47|53
3+
97|13
4+
97|61
5+
97|47
6+
75|29
7+
61|13
8+
75|53
9+
29|13
10+
97|29
11+
53|29
12+
61|53
13+
97|53
14+
61|29
15+
47|13
16+
75|47
17+
97|75
18+
47|61
19+
75|61
20+
47|29
21+
75|13
22+
53|13
23+
24+
75,47,61,53,29
25+
97,61,53,29,13
26+
75,29,13
27+
75,97,47,61,53
28+
61,13,29
29+
97,13,75,29,47"

Aoc2024/Day05/Main.lean

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@ def main : IO Unit := do
1010
IO.println s!"Example: {<- parseAndSolvePart1 exampleInput}"
1111
let answerPart1 <- parseAndSolvePart1 puzzleInput
1212
IO.println s!"Puzzle: {answerPart1}"
13-
assert! (answerPart1 == -1)
13+
assert! (answerPart1 == 4569)
1414
IO.println ""
1515
IO.println "Part 2"
1616
IO.println s!"Example: {<- parseAndSolvePart2 exampleInput}"
1717
let answerPart2 <- parseAndSolvePart2 puzzleInput
1818
IO.println s!"Puzzle: {answerPart2}"
19-
assert! (answerPart2 == -1)
19+
assert! (answerPart2 == 6456)

Aoc2024/Day05/Parser.lean

+25-3
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,30 @@ import Std
55
open Std.Internal.Parsec.String
66
open Std.Internal.Parsec
77

8-
private def inputParser : Parser (List Int) := sorry
8+
private def number : Parser Int := do
9+
let nat <- digits
10+
pure nat
911

10-
def parseThings : String -> Except String (List Int) := inputParser.run
12+
private def orderingRuleParser : Parser OrderingRule := do
13+
let before ← number
14+
skipChar '|'
15+
let after ← number
16+
pure { before, after }
1117

12-
-- #guard parseReports exampleInput == Except.ok 42
18+
private def updateParser : Parser Update := do
19+
let pages <- sepBy number (skipChar ',')
20+
pure { pages }
21+
22+
private def inputParser : Parser PuzzleInput := do
23+
let rules ← many (orderingRuleParser <* skipChar '\n')
24+
skipChar '\n'
25+
let updates ← sepBy updateParser (skipChar '\n')
26+
pure { rules := rules.toList, updates }
27+
28+
def parseInput : String -> Except String PuzzleInput := inputParser.run
29+
30+
#guard parseInput "1|2\n\n1,2\n3,4" == Except.ok {
31+
rules := [{ before := 1, after := 2 }],
32+
updates := [{ pages := [1, 2] }, { pages := [3, 4] }]
33+
}
34+
#guard parseInput exampleInput |>.isOk

Aoc2024/Day05/Solve.lean

+29-6
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,38 @@
11
import Aoc2024.Utils
22
import Aoc2024.Day05.Examples
33
import Aoc2024.Day05.Parser
4+
open Std (HashSet)
45

5-
private def solvePart1 (things : List Int) : Int := sorry
6+
-- Part 1
67

7-
def parseAndSolvePart1 (s : String): Except String Int := parseThings s |>.map solvePart1
8+
private def middleElement {α} (l : List α) : Option α := l.get? (l.length / 2)
89

9-
-- #guard parseAndSolvePart1 exampleInput == Except.ok 2
10+
private def middlePageNumber (update : Update) : Int := middleElement update.pages |>.getD 0
1011

11-
private def solvePart2 (things : List Int) : Int := sorry
12+
private def isCorrectlyOrdered (rules : List OrderingRule) (update : Update) : Bool :=
13+
let allowedPairs := rules.map (·.toPair) |>.toSet
14+
update.pages.slidingPairs.toSet.isSubsetOf allowedPairs
1215

13-
def parseAndSolvePart2 (s : String): Except String Int := parseThings s |>.map solvePart2
16+
private def solvePart1 (input : PuzzleInput) : Int :=
17+
input.updates.filter (isCorrectlyOrdered input.rules)
18+
|>.sumBy middlePageNumber
1419

15-
-- #guard parseAndSolvePart2 exampleInput == Except.ok 4
20+
def parseAndSolvePart1 (s : String): Except String Int := parseInput s |>.map solvePart1
21+
22+
#guard parseAndSolvePart1 exampleInput == Except.ok 143
23+
24+
-- Part 2
25+
26+
private def orderCorrectly (rules : List OrderingRule) (update : Update) : Update :=
27+
let allowedPairs := rules.map (·.toPair) |>.toSet
28+
let reorderedPages := update.pages.mergeSort (λ p1 p2 => p1 == p2 || allowedPairs.contains (p1, p2))
29+
{ pages := reorderedPages }
30+
31+
private def solvePart2 (input : PuzzleInput) : Int :=
32+
input.updates.filterNot (isCorrectlyOrdered input.rules)
33+
|>.map (orderCorrectly input.rules)
34+
|>.sumBy middlePageNumber
35+
36+
def parseAndSolvePart2 (s : String): Except String Int := parseInput s |>.map solvePart2
37+
38+
#guard parseAndSolvePart2 exampleInput == Except.ok 123

Aoc2024/Day05/Types.lean

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
abbrev Page := Int
2+
3+
structure OrderingRule where
4+
before : Page
5+
after : Page
6+
deriving BEq, Hashable, Repr
7+
8+
def OrderingRule.toPair (r : OrderingRule) : Page × Page :=
9+
(r.before, r.after)
10+
11+
structure Update where
12+
pages : List Page
13+
deriving BEq, Hashable, Repr
14+
15+
structure PuzzleInput where
16+
rules : List OrderingRule
17+
updates : List Update
18+
deriving BEq, Hashable, Repr

Aoc2024/Day05/inputs/example.txt

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
47|53
2+
97|13
3+
97|61
4+
97|47
5+
75|29
6+
61|13
7+
75|53
8+
29|13
9+
97|29
10+
53|29
11+
61|53
12+
97|53
13+
61|29
14+
47|13
15+
75|47
16+
97|75
17+
47|61
18+
75|61
19+
47|29
20+
75|13
21+
53|13
22+
23+
75,47,61,53,29
24+
97,61,53,29,13
25+
75,29,13
26+
75,97,47,61,53
27+
61,13,29
28+
97,13,75,29,47

0 commit comments

Comments
 (0)