@@ -9,16 +9,61 @@ import java.math.BigInteger
9
9
*/
10
10
object Day17 : DayOf2024(17 ) {
11
11
private val numberPattern = " (-?\\ d+)" .toRegex()
12
+ private val EIGHT = 8 .toBigInteger()
13
+
12
14
override fun first (): Any? {
13
15
val (rawRegisters, rawProgram) = data.split(" \n\n " )
16
+ val (a, b, c) = rawRegisters.lines().mapNotNull { line ->
17
+ numberPattern.find(line)?.value?.toBigInteger()
18
+ }
19
+ val program = numberPattern.findAll(rawProgram).map { it.value.toInt() }.toList()
14
20
15
- var (a, b, c) = rawRegisters.lines()
16
- .mapNotNull { line ->
17
- numberPattern.find(line)?.value?.toBigInteger()
18
- }
21
+ return calculate(program, a, b, c).joinToString(separator = " ," )
22
+ }
19
23
24
+ override fun second (): Any? {
25
+ val rawProgram = data.substringAfter(" \n\n " )
20
26
val program = numberPattern.findAll(rawProgram).map { it.value.toInt() }.toList()
21
27
28
+ val mapping = (0 until 4096 ).associate { startA ->
29
+ (0 .. 3 ).map { (startA shr (3 * it)) and 7 } to calculate(program, startA.toBigInteger()).first()
30
+ }
31
+
32
+ val startConfig = mapping.filter { it.value == program.first() }
33
+ .keys
34
+ .groupingBy { it.drop(1 ) }
35
+ .fold(Int .MAX_VALUE ) { min, list -> minOf(min, list.first()) }
36
+ .mapValues { it.value.toBigInteger() }
37
+
38
+ val result = program.drop(1 ).foldIndexed(startConfig) { index, acc, op ->
39
+ val fit = mapping.filter { it.value == op }.filter { it.key.dropLast(1 ) in acc }
40
+
41
+ fit.keys
42
+ .groupingBy { it.drop(1 ) }
43
+ .fold(Int .MAX_VALUE ) { min, list -> minOf(min, list.first()) }
44
+ .mapValues { it.value.toBigInteger().shl((index + 1 ) * 3 ) + acc[listOf (it.value) + it.key.dropLast(1 )]!! }
45
+ }
46
+
47
+ val best = result.minOf { (rawHead, tail) ->
48
+ val head = rawHead.reduceRight { value, acc -> acc * 8 + value }.toBigInteger()
49
+ head.shl(3 * program.size) + tail
50
+ }
51
+
52
+ check(calculate(program, best) == program)
53
+
54
+ return best
55
+ }
56
+
57
+ private fun calculate (
58
+ program : List <Int >,
59
+ startA : BigInteger ,
60
+ startB : BigInteger = BigInteger .ZERO ,
61
+ startC : BigInteger = BigInteger .ZERO ,
62
+ ): List <Int > = buildList {
63
+ var a = startA
64
+ var b = startB
65
+ var c = startC
66
+
22
67
fun combo (input : Int ): BigInteger = when (input) {
23
68
in 0 .. 3 -> input.toBigInteger()
24
69
4 -> a
@@ -27,8 +72,6 @@ object Day17 : DayOf2024(17) {
27
72
else -> error(" Unexpected value" )
28
73
}
29
74
30
- val output = mutableListOf<BigInteger >()
31
-
32
75
var position = 0
33
76
while (position in program.indices) {
34
77
val instruction = program[position++ ]
@@ -37,16 +80,14 @@ object Day17 : DayOf2024(17) {
37
80
when (instruction) {
38
81
0 -> a = a.div(BigInteger .TWO .pow(combo(operand).toInt()))
39
82
1 -> b = b xor operand.toBigInteger()
40
- 2 -> b = combo(operand).mod(8 .toBigInteger() )
83
+ 2 -> b = combo(operand).mod(EIGHT )
41
84
3 -> position = if (a != BigInteger .ZERO ) operand else position
42
85
4 -> b = b xor c
43
- 5 -> output + = combo(operand).mod(8 .toBigInteger ())
86
+ 5 -> add( combo(operand).mod(EIGHT ).toInt ())
44
87
6 -> b = a.div(BigInteger .TWO .pow(combo(operand).toInt()))
45
88
7 -> c = a.div(BigInteger .TWO .pow(combo(operand).toInt()))
46
89
}
47
90
}
48
-
49
- return output.joinToString(separator = " ," )
50
91
}
51
92
}
52
93
0 commit comments