1
+ /*
2
+ * Copyright (c) 2024 James Carman
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ package adventofcode.day17
18
+
19
+ import adventofcode.util.splitByEmptyLines
20
+ import adventofcode.util.splitsAs
21
+ import kotlin.math.pow
22
+
23
+ fun Long.pow (exponent : Long ) = this .toDouble().pow(exponent.toDouble()).toInt()
24
+
25
+ fun String.parseComputer (): Computer {
26
+ val parts = splitByEmptyLines()
27
+ val (a, b, c) = parts[0 ].lines().map { it.substringAfter(' :' ).trim().toLong() }
28
+ val program = parts[1 ].substringAfter(' :' ).trim().replace(' ,' , ' ' ).splitsAs { it.toLong() }
29
+ return Computer (a, b, c, program)
30
+ }
31
+
32
+ fun String.determineProgramOutput (): String {
33
+ val computer = parseComputer()
34
+ val output = computer.runProgram()
35
+ return output.joinToString(separator = " ," )
36
+ }
37
+
38
+ fun String.findLeastSelfReplicatingValueForA () = generatorsOf(this , parseComputer().program).first()
39
+
40
+ private fun generatorsOf (input : String , output : List <Long >): List <Long > {
41
+ if (output.size == 1 ) {
42
+ return (0L .. 7L ).filter { input.parseComputer().initializeARegister(it).runProgram() == output }
43
+ }
44
+ val tailGenerators = generatorsOf(input, output.drop(1 ))
45
+ return tailGenerators.flatMap { generator ->
46
+ (0 .. 7 ).map { generator * 8 + it }
47
+ .filter { input.parseComputer().initializeARegister(it).runProgram() == output }
48
+ }
49
+ }
50
+
51
+ class Computer (
52
+ private var a : Long = 0 ,
53
+ private var b : Long = 0 ,
54
+ private var c : Long = 0 ,
55
+ val program : List <Long >
56
+ ) {
57
+ private var instructionPoInter: Int = 0
58
+
59
+ fun initializeARegister (value : Long ): Computer {
60
+ a = value
61
+ return this
62
+ }
63
+
64
+ private fun operand () = program[instructionPoInter + 1 ]
65
+
66
+ private fun literal (): Long = operand()
67
+
68
+ private fun combo (): Long = when (operand()) {
69
+ 4L -> a
70
+ 5L -> b
71
+ 6L -> c
72
+ else -> literal()
73
+ }
74
+
75
+ fun runProgram (): List <Long > {
76
+ val output = mutableListOf<Long >()
77
+ while (instructionPoInter < program.size) {
78
+ val currentInstructionPoInter = instructionPoInter
79
+ when (program[instructionPoInter]) {
80
+ 0L -> a = a / 2L .pow(combo())
81
+ 1L -> b = b xor literal()
82
+ 2L -> b = combo() % 8
83
+ 3L -> if (a != 0L ) instructionPoInter = literal().toInt()
84
+ 4L -> b = b xor c
85
+ 5L -> output + = combo() % 8
86
+ 6L -> b = a / 2L .pow(combo())
87
+ 7L -> c = a / 2L .pow(combo())
88
+ else -> throw IllegalArgumentException (" Unknown opcode: $program [$instructionPoInter ]" )
89
+ }
90
+ if (currentInstructionPoInter == instructionPoInter) {
91
+ instructionPoInter + = 2
92
+ }
93
+ }
94
+ return output
95
+ }
96
+
97
+ }
0 commit comments