This commit is contained in:
Chris Hodges 2024-12-17 09:32:46 +01:00
parent 76c01e01e5
commit b0e4461a7d

123
src/aoc2024/Day17.kt Normal file
View File

@ -0,0 +1,123 @@
package aoc2024
import println
import readInput
import splitInts
/*
--- Day 17: Chronospatial Computer ---
https://adventofcode.com/2024/day/17
*/
fun main() {
val inlineTestInput = """
Register A: 117440
Register B: 0
Register C: 0
Program: 0,3,5,4,3,0
"""
val regs = LongArray(3)
fun getComboOperand(op: Int): Long =
when (op) {
0, 1, 2, 3 -> op.toLong()
4, 5, 6 -> regs[op - 4]
else -> throw IllegalStateException()
}
fun part1(input: List<String>): String {
regs[0] = input[0].split(" ")[2].toLong()
regs[1] = input[1].split(" ")[2].toLong()
regs[2] = input[2].split(" ")[2].toLong()
val ops = input[4].split(" ")[1].splitInts(",")
val outs = ArrayList<Int>()
var pc = 0
while (pc < ops.size) {
when (ops[pc++]) {
// adv
0 -> regs[0] = regs[0] shr getComboOperand(ops[pc++]).toInt()
// bdv
6 -> regs[1] = regs[0] shr getComboOperand(ops[pc++]).toInt()
// cdv
7 -> regs[2] = regs[0] shr getComboOperand(ops[pc++]).toInt()
// bxl
1 -> regs[1] = regs[1] xor ops[pc++].toLong()
// bst
2 -> regs[1] = getComboOperand(ops[pc++]) and 7
// jnz
3 -> if (regs[0] == 0L) pc++ else pc = ops[pc]
// bxc
4 -> {
regs[1] = regs[1] xor regs[2]
pc++
}
// out
5 -> outs.add((getComboOperand(ops[pc++]) and 7).toInt())
}
}
return outs.joinToString(",")
}
fun verify(rega: Long, ops: List<Int>, outs: List<Int>): Boolean {
regs[0] = rega
var pc = 0
var outpos = 0
while (pc < ops.size) {
when (ops[pc++]) {
// adv
0 -> regs[0] = regs[0] shr getComboOperand(ops[pc++]).toInt()
// bdv
6 -> regs[1] = regs[0] shr getComboOperand(ops[pc++]).toInt()
// cdv
7 -> regs[2] = regs[0] shr getComboOperand(ops[pc++]).toInt()
// bxl
1 -> regs[1] = regs[1] xor ops[pc++].toLong()
// bst
2 -> regs[1] = getComboOperand(ops[pc++]) and 7
// jnz
3 -> if (regs[0] == 0L) pc++ else pc = ops[pc]
// bxc
4 -> {
regs[1] = regs[1] xor regs[2]
pc++
}
// out
5 -> {
val o = (getComboOperand(ops[pc++]) and 7).toInt()
if (outs[outpos++] != o) return false
}
}
}
return true
}
fun rec(a: Long, p: Int, ops: List<Int>, outs: List<Int>): Long {
val partOutput = outs.take(p).reversed()
// assuming that all programs use 3 bit shifts in the last operation
for (i in 0L..7L) {
if (verify((a shl 3) or i, ops, partOutput)) {
if (p == outs.size) return (a shl 3) or i
val res = rec((a shl 3) or i, p + 1, ops, outs)
if (res != 0L) return res
}
}
return 0
}
fun part2(input: List<String>): Long {
val ops = input[4].split(" ")[1].splitInts(",")
val outs = ops.reversed()
return rec(0L, 1, ops, outs)
}
// test if implementation meets criteria from the description, like:
val testInput = inlineTestInput.trim().reader().readLines()
//val testInput = readInput("aoc2024/Day17_test")
val testInputPart1Result = part1(testInput)
println("Part 1 Test: $testInputPart1Result")
val input = readInput("aoc2024/Day17")
part1(input).println()
part2(input).println()
}