From b0e4461a7d5359003ce488fcbd46506491f658e3 Mon Sep 17 00:00:00 2001 From: chrisly42 Date: Tue, 17 Dec 2024 09:32:46 +0100 Subject: [PATCH] Day 17. --- src/aoc2024/Day17.kt | 123 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 src/aoc2024/Day17.kt diff --git a/src/aoc2024/Day17.kt b/src/aoc2024/Day17.kt new file mode 100644 index 0000000..ad66e10 --- /dev/null +++ b/src/aoc2024/Day17.kt @@ -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 { + 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() + 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, outs: List): 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, outs: List): 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): 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() +}