Day 17
This commit is contained in:
@@ -18,7 +18,8 @@ val solvers = Map[Int, Solver](
|
|||||||
13 -> Day13,
|
13 -> Day13,
|
||||||
14 -> Day14,
|
14 -> Day14,
|
||||||
15 -> Day15,
|
15 -> Day15,
|
||||||
16 -> Day16
|
16 -> Day16,
|
||||||
|
17 -> Day17
|
||||||
)
|
)
|
||||||
|
|
||||||
def runSolver(solver: Solver, input: os.Path): Unit =
|
def runSolver(solver: Solver, input: os.Path): Unit =
|
||||||
|
|||||||
78
aoc/src/dev/ctsk/aoc/days/Day17.scala
Normal file
78
aoc/src/dev/ctsk/aoc/days/Day17.scala
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
package dev.ctsk.aoc.days
|
||||||
|
|
||||||
|
import dev.ctsk.aoc.*
|
||||||
|
|
||||||
|
import scala.util.boundary
|
||||||
|
import scala.util.boundary.break
|
||||||
|
|
||||||
|
object Day17 extends Solver(17):
|
||||||
|
case class Machine(var code: IndexedSeq[Long]):
|
||||||
|
def execute(
|
||||||
|
registers: Map[Char, Long],
|
||||||
|
output: Option[Int] = None
|
||||||
|
): Vector[Long] =
|
||||||
|
val reg = Array.from(registers).sorted.map(_._2)
|
||||||
|
var pc = 0
|
||||||
|
|
||||||
|
def combo(i: Long): Long =
|
||||||
|
i match
|
||||||
|
case i if i <= 3 => i
|
||||||
|
case i if i > 3 && i <= 6 => reg(i.toInt - 4)
|
||||||
|
|
||||||
|
var out = Vector.empty[Long]
|
||||||
|
boundary:
|
||||||
|
while pc < code.length do
|
||||||
|
code(pc) match
|
||||||
|
case 0 => reg(0) >>= combo(code(pc + 1)); pc += 2
|
||||||
|
case 1 => reg(1) ^= code(pc + 1); pc += 2
|
||||||
|
case 2 => reg(1) = combo(code(pc + 1)) % 8; pc += 2
|
||||||
|
case 3 => if reg(0) != 0 then pc = code(pc + 1).toInt else pc += 2
|
||||||
|
case 4 => reg(1) = reg(1) ^ reg(2); pc += 2
|
||||||
|
case 5 =>
|
||||||
|
out :+= combo(code(pc + 1)) % 8;
|
||||||
|
if output.exists(_ >= out.length) then break()
|
||||||
|
pc += 2
|
||||||
|
case 6 => reg(1) = reg(0) >> combo(code(pc + 1)); pc += 2
|
||||||
|
case 7 => reg(2) = reg(0) >> combo(code(pc + 1)); pc += 2
|
||||||
|
|
||||||
|
out
|
||||||
|
|
||||||
|
def part1(machine: Machine, initialRegs: Map[Char, Long]): String =
|
||||||
|
machine.execute(initialRegs).mkString(",")
|
||||||
|
|
||||||
|
def part2(machine: Machine, initialRegs: Map[Char, Long]): Long =
|
||||||
|
val target = machine.code.reverse
|
||||||
|
|
||||||
|
def rec(pos: Int = 0, acc: Long = 0): Option[Long] =
|
||||||
|
if pos >= target.length then return Some(acc)
|
||||||
|
def check(aVal: Long): Boolean =
|
||||||
|
machine.execute(initialRegs.updated('A', aVal), Some(1)).head == target(
|
||||||
|
pos
|
||||||
|
)
|
||||||
|
|
||||||
|
(0 until 8)
|
||||||
|
.map((acc << 3) + _)
|
||||||
|
.filter(check)
|
||||||
|
.flatMap(rec(pos + 1, _))
|
||||||
|
.headOption
|
||||||
|
|
||||||
|
rec().get
|
||||||
|
|
||||||
|
override def run(input: os.ReadablePath): (Timings, Solution) =
|
||||||
|
val Array(initial_, code_) = os.read(input).split("\n\n")
|
||||||
|
val initialRegs = initial_.linesIterator
|
||||||
|
.map(line => {
|
||||||
|
val spl = line.split(" ");
|
||||||
|
(spl(1)(0) -> spl(2).toLong)
|
||||||
|
})
|
||||||
|
.toMap
|
||||||
|
val code = longs(code_)
|
||||||
|
val machine = Machine(code)
|
||||||
|
|
||||||
|
val (p1_time, p1_solution) = timed { part1(machine, initialRegs) }
|
||||||
|
val (p2_time, p2_solution) = timed { part2(machine, initialRegs) }
|
||||||
|
|
||||||
|
(
|
||||||
|
Timings(0, p1_time, p2_time),
|
||||||
|
Solution(p1_solution, Long.box(p2_solution))
|
||||||
|
)
|
||||||
2
data/17.ans
Normal file
2
data/17.ans
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
2,0,7,3,0,3,1,3,7
|
||||||
|
247839539763386
|
||||||
5
data/17.in
Normal file
5
data/17.in
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
Register A: 18427963
|
||||||
|
Register B: 0
|
||||||
|
Register C: 0
|
||||||
|
|
||||||
|
Program: 2,4,1,1,7,5,0,3,4,3,1,6,5,5,3,0
|
||||||
Reference in New Issue
Block a user