Skip to content

Commit 5075998

Browse files
committed
17
1 parent cdee618 commit 5075998

File tree

4 files changed

+170
-0
lines changed

4 files changed

+170
-0
lines changed

src/main/kotlin/17.kt

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
fun main() {
2+
println(solve17a(readInputLines("17")))
3+
println(solve17b())
4+
}
5+
6+
fun solve17a(lines: List<String>): String {
7+
var (state, instructions) = parseInput(lines)
8+
9+
while (state.i < instructions.size) {
10+
val instruction = Instruction(instructions[state.i], instructions[state.i + 1])
11+
state = update(state.copy(i = state.i + 2), instruction)
12+
}
13+
14+
return state.output.joinToString(separator = ",")
15+
}
16+
17+
fun solve17b(): Long {
18+
/*
19+
2,4,1,3,7,5,1,5,0,3,4,1,5,5,3,0
20+
while a != 0
21+
b = a % 8
22+
b = b ^ 3
23+
c = a >> b
24+
b = b ^ 5
25+
a = a >> 3
26+
b = b ^ c
27+
print(b % 8)
28+
*/
29+
30+
val program = listOf(2, 4, 1, 3, 7, 5, 1, 5, 0, 3, 4, 1, 5, 5, 3, 0)
31+
32+
fun runIteration(a: Long): Int {
33+
var b = a % 8L
34+
b = b.xor(3)
35+
val c = a.shr(b.toInt())
36+
b = b.xor(5)
37+
b = b.xor(c)
38+
return (b % 8).toInt()
39+
}
40+
41+
fun rec(a: Long, i: Int): Long? {
42+
if (i == -1) {
43+
return a
44+
}
45+
46+
for (n in 0..7) {
47+
val newA = a.shl(3) + n
48+
49+
if (runIteration(newA) == program[i]) {
50+
val result = rec(newA, i - 1)
51+
if (result != null) {
52+
return result
53+
}
54+
}
55+
}
56+
57+
return null
58+
}
59+
60+
for (a in 0L..1023L) {
61+
if (runIteration(a) == program.last()) {
62+
val result = rec(a, program.lastIndex - 1)
63+
if (result != null) {
64+
return result
65+
}
66+
}
67+
}
68+
69+
throw IllegalStateException("No solution found")
70+
}
71+
72+
private data class ComputerState(val a: Long, val b: Long, val c: Long, val i: Int, val output: List<Int>)
73+
private data class Input17(val state: ComputerState, val instructions: List<Int>)
74+
private data class Instruction(val opcode: Int, val operand: Int)
75+
76+
private fun update(state: ComputerState, instruction: Instruction): ComputerState = when (instruction.opcode) {
77+
// adv:
78+
0 -> state.copy(
79+
a = state.a.shr(getOperandValue(state, instruction.operand).toInt())
80+
)
81+
// bxl:
82+
1 -> state.copy(
83+
b = state.b.xor(instruction.operand.toLong())
84+
)
85+
// bst:
86+
2 -> state.copy(
87+
b = getOperandValue(state, instruction.operand) % 8
88+
)
89+
// jnz:
90+
3 -> if (state.a == 0L) state else state.copy(
91+
i = instruction.operand
92+
)
93+
// bxc:
94+
4 -> state.copy(
95+
b = state.b.xor(state.c)
96+
)
97+
// out:
98+
5 -> state.copy(
99+
output = state.output + (getOperandValue(state, instruction.operand) % 8).toInt()
100+
)
101+
// bdv:
102+
6 -> state.copy(
103+
b = state.a.shr(getOperandValue(state, instruction.operand).toInt())
104+
)
105+
// cdv:
106+
7 -> state.copy(
107+
c = state.a.shr(getOperandValue(state, instruction.operand).toInt())
108+
)
109+
110+
else -> throw IllegalStateException("Unknown instruction $instruction")
111+
}
112+
113+
private fun getOperandValue(state: ComputerState, operand: Int): Long = when (operand) {
114+
in 0..3 -> operand.toLong()
115+
4 -> state.a
116+
5 -> state.b
117+
6 -> state.c
118+
else -> throw IllegalStateException("Illegal operand code $operand")
119+
}
120+
121+
private val REGISTER_LINE_REGEX = Regex("""^Register [ABC]: (-?\d+)$""")
122+
private val INSTRUCTIONS_LINE_REGEX = Regex("""^Program: (.*)$""")
123+
private fun parseInput(lines: List<String>): Input17 {
124+
assert(lines.size == 5)
125+
val a = checkNotNull(REGISTER_LINE_REGEX.find(lines[0])).groupValues[1].toLong()
126+
val b = checkNotNull(REGISTER_LINE_REGEX.find(lines[1])).groupValues[1].toLong()
127+
val c = checkNotNull(REGISTER_LINE_REGEX.find(lines[2])).groupValues[1].toLong()
128+
val instructions = checkNotNull(INSTRUCTIONS_LINE_REGEX.find(lines[4])).groupValues[1].split(",").map { it.toInt() }
129+
130+
return Input17(
131+
ComputerState(a, b, c, 0, listOf()), instructions
132+
)
133+
}

src/main/kotlin/input/17.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Register A: 21539243
2+
Register B: 0
3+
Register C: 0
4+
5+
Program: 2,4,1,3,7,5,1,5,0,3,4,1,5,5,3,0

src/main/kotlin/input/17_example1.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Register A: 729
2+
Register B: 0
3+
Register C: 0
4+
5+
Program: 0,1,5,4,3,0

src/test/kotlin/Test17.kt

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import org.junit.Assert.assertEquals
2+
import org.junit.Test
3+
4+
class Test17 {
5+
@Test
6+
fun test_a() {
7+
val result = solve17a(readInputLines("17_example1"))
8+
9+
assertEquals("4,6,3,5,6,3,5,2,1,0", result)
10+
}
11+
12+
@Test
13+
fun test_b() {
14+
val resultA = solve17b()
15+
val output = solve17a(
16+
listOf(
17+
"Register A: $resultA",
18+
"Register B: 0",
19+
"Register C: 0",
20+
"",
21+
"Program: 2,4,1,3,7,5,1,5,0,3,4,1,5,5,3,0"
22+
)
23+
)
24+
25+
assertEquals("2,4,1,3,7,5,1,5,0,3,4,1,5,5,3,0", output)
26+
}
27+
}

0 commit comments

Comments
 (0)