|
1 | 1 | package eu.sim642.adventofcode2024 |
2 | 2 |
|
3 | | -import eu.sim642.adventofcodelib.graph.{Dijkstra, GraphSearch, TargetNode} |
4 | | -import eu.sim642.adventofcodelib.pos.Pos |
5 | 3 | import eu.sim642.adventofcodelib.IntegralImplicits.* |
6 | | -import eu.sim642.adventofcodelib.NumberTheory |
| 4 | +import eu.sim642.adventofcodelib.pos.Pos |
7 | 5 |
|
8 | 6 | object Day13 { |
9 | 7 |
|
10 | | - case class LongPos(x: Long, y: Long) |
| 8 | + case class LongPos(x: Long, y: Long) // TODO: generalize library |
11 | 9 |
|
12 | 10 | case class ClawMachine(buttonA: Pos, buttonB: Pos, prize: LongPos) |
13 | 11 |
|
14 | 12 | trait Part { |
15 | | - def minWinTokens(clawMachine: ClawMachine): Long |
| 13 | + def minWinTokens(clawMachine: ClawMachine): Option[Long] |
16 | 14 |
|
17 | | - def sumMinWinTokens(clawMachines: Seq[ClawMachine]): Long = clawMachines.map(minWinTokens).sum |
| 15 | + def sumMinWinTokens(clawMachines: Seq[ClawMachine]): Long = clawMachines.flatMap(minWinTokens).sum |
18 | 16 | } |
19 | 17 |
|
20 | 18 | object Part1 extends Part { |
21 | | - override def minWinTokens(clawMachine: ClawMachine): Long = { |
| 19 | + override def minWinTokens(clawMachine: ClawMachine): Option[Long] = { |
22 | 20 | val ClawMachine(buttonA, buttonB, prize) = clawMachine |
23 | | - |
24 | | - /*val graphSearch = new GraphSearch[Pos] with TargetNode[Pos] { |
25 | | - override val startNode: Pos = Pos.zero |
26 | | -
|
27 | | - override def neighbors(pos: Pos): IterableOnce[(Pos, Int)] = { |
28 | | - for { |
29 | | - (button, tokens) <- Seq(clawMachine.buttonA -> 3, clawMachine.buttonB -> 1) |
30 | | - newPos = pos + button |
31 | | - if newPos <= targetNode |
32 | | - } yield newPos -> tokens |
33 | | - } |
34 | | -
|
35 | | - override val targetNode: Pos = clawMachine.prize |
36 | | - } |
37 | | -
|
38 | | - Dijkstra.search(graphSearch).target.map(_._2).getOrElse(0)*/ |
39 | | - |
40 | | - /*(for { |
41 | | - timesA <- 0 to 100 |
42 | | - prizeB = prize - timesA *: buttonA |
43 | | - timesB <- prizeB.x /! buttonB.x |
44 | | - if timesB * buttonB.y == prizeB.y |
45 | | - } yield 3 * timesA + timesB).minOption.getOrElse(0)*/ |
46 | | - |
47 | | - (for { |
| 21 | + // linear system of 2 equations |
| 22 | + for { |
48 | 23 | timesB <- (prize.x * buttonA.y - prize.y * buttonA.x) /! (buttonB.x * buttonA.y - buttonB.y * buttonA.x) |
49 | 24 | timesA <- (prize.x - timesB * buttonB.x) /! buttonA.x |
50 | | - } yield 3 * timesA + timesB).getOrElse(0) |
| 25 | + } yield 3 * timesA + timesB |
51 | 26 | } |
52 | 27 | } |
53 | 28 |
|
54 | 29 | object Part2 extends Part { |
55 | | - override def minWinTokens(clawMachine: ClawMachine): Long = { |
| 30 | + override def minWinTokens(clawMachine: ClawMachine): Option[Long] = { |
56 | 31 | val newClawMachine = clawMachine.copy(prize = LongPos(clawMachine.prize.x + 10000000000000L, clawMachine.prize.y + 10000000000000L)) |
57 | 32 | Part1.minWinTokens(newClawMachine) |
58 | 33 | } |
|
0 commit comments