Skip to content

Commit 0df8f3c

Browse files
committed
Solve 2024 day 13 part 2
1 parent 43af2c9 commit 0df8f3c

File tree

2 files changed

+56
-26
lines changed

2 files changed

+56
-26
lines changed

src/main/scala/eu/sim642/adventofcode2024/Day13.scala

Lines changed: 46 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,51 +2,73 @@ package eu.sim642.adventofcode2024
22

33
import eu.sim642.adventofcodelib.graph.{Dijkstra, GraphSearch, TargetNode}
44
import eu.sim642.adventofcodelib.pos.Pos
5-
import eu.sim642.adventofcodelib.IntegralImplicits._
5+
import eu.sim642.adventofcodelib.IntegralImplicits.*
6+
import eu.sim642.adventofcodelib.NumberTheory
67

78
object Day13 {
89

9-
case class ClawMachine(buttonA: Pos, buttonB: Pos, prize: Pos)
10+
case class LongPos(x: Long, y: Long)
1011

11-
def minWinTokens(clawMachine: ClawMachine): Int = {
12-
val ClawMachine(buttonA, buttonB, prize) = clawMachine
12+
case class ClawMachine(buttonA: Pos, buttonB: Pos, prize: LongPos)
1313

14-
/*val graphSearch = new GraphSearch[Pos] with TargetNode[Pos] {
15-
override val startNode: Pos = Pos.zero
14+
trait Part {
15+
def minWinTokens(clawMachine: ClawMachine): Long
1616

17-
override def neighbors(pos: Pos): IterableOnce[(Pos, Int)] = {
18-
for {
19-
(button, tokens) <- Seq(clawMachine.buttonA -> 3, clawMachine.buttonB -> 1)
20-
newPos = pos + button
21-
if newPos <= targetNode
22-
} yield newPos -> tokens
17+
def sumMinWinTokens(clawMachines: Seq[ClawMachine]): Long = clawMachines.map(minWinTokens).sum
18+
}
19+
20+
object Part1 extends Part {
21+
override def minWinTokens(clawMachine: ClawMachine): Long = {
22+
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
2336
}
2437
25-
override val targetNode: Pos = clawMachine.prize
26-
}
38+
Dijkstra.search(graphSearch).target.map(_._2).getOrElse(0)*/
2739

28-
Dijkstra.search(graphSearch).target.map(_._2).getOrElse(0)*/
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)*/
2946

30-
(for {
31-
timesA <- 0 to 100
32-
prizeB = prize - timesA *: buttonA
33-
timesB <- prizeB.x /! buttonB.x
34-
if timesB * buttonB.y == prizeB.y
35-
} yield 3 * timesA + timesB).minOption.getOrElse(0)
47+
(for {
48+
timesB <- (prize.x * buttonA.y - prize.y * buttonA.x) /! (buttonB.x * buttonA.y - buttonB.y * buttonA.x)
49+
timesA <- (prize.x - timesB * buttonB.x) /! buttonA.x
50+
} yield 3 * timesA + timesB).getOrElse(0)
51+
}
3652
}
3753

38-
def sumMinWinTokens(clawMachines: Seq[ClawMachine]): Int = clawMachines.map(minWinTokens).sum
54+
object Part2 extends Part {
55+
override def minWinTokens(clawMachine: ClawMachine): Long = {
56+
val newClawMachine = clawMachine.copy(prize = LongPos(clawMachine.prize.x + 10000000000000L, clawMachine.prize.y + 10000000000000L))
57+
Part1.minWinTokens(newClawMachine)
58+
}
59+
}
3960

4061
def parseClawMachine(s: String): ClawMachine = s match {
4162
case s"Button A: X+$aX, Y+$aY\nButton B: X+$bX, Y+$bY\nPrize: X=$pX, Y=$pY" =>
42-
ClawMachine(Pos(aX.toInt, aY.toInt), Pos(bX.toInt, bY.toInt), Pos(pX.toInt, pY.toInt))
63+
ClawMachine(Pos(aX.toInt, aY.toInt), Pos(bX.toInt, bY.toInt), LongPos(pX.toLong, pY.toLong))
4364
}
4465

4566
def parseClawMachines(input: String): Seq[ClawMachine] = input.split("\n\n").map(parseClawMachine).toSeq
4667

4768
lazy val input: String = scala.io.Source.fromInputStream(getClass.getResourceAsStream("day13.txt")).mkString.trim
4869

4970
def main(args: Array[String]): Unit = {
50-
println(sumMinWinTokens(parseClawMachines(input)))
71+
println(Part1.sumMinWinTokens(parseClawMachines(input)))
72+
println(Part2.sumMinWinTokens(parseClawMachines(input)))
5173
}
5274
}

src/test/scala/eu/sim642/adventofcode2024/Day13Test.scala

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,18 @@ class Day13Test extends AnyFunSuite {
2323
|Prize: X=18641, Y=10279""".stripMargin
2424

2525
test("Part 1 examples") {
26-
assert(sumMinWinTokens(parseClawMachines(exampleInput)) == 480)
26+
assert(Part1.sumMinWinTokens(parseClawMachines(exampleInput)) == 480)
2727
}
2828

2929
test("Part 1 input answer") {
30-
assert(sumMinWinTokens(parseClawMachines(input)) == 31623)
30+
assert(Part1.sumMinWinTokens(parseClawMachines(input)) == 31623)
31+
}
32+
33+
test("Part 2 examples") {
34+
assert(Part2.sumMinWinTokens(parseClawMachines(exampleInput)) == 875318608908L) // from IRC
35+
}
36+
37+
test("Part 2 input answer") {
38+
assert(Part2.sumMinWinTokens(parseClawMachines(input)) == 93209116744825L)
3139
}
3240
}

0 commit comments

Comments
 (0)