Skip to content

Commit 662f3c0

Browse files
committed
Day 24, part two: Simulate the wired gates for different input
Compare the outputs to see which digits of the resulting number differ from the sum of the input numbers.
1 parent a0a6988 commit 662f3c0

File tree

1 file changed

+88
-6
lines changed

1 file changed

+88
-6
lines changed

src/main/kotlin/de/ronny_h/aoc/year24/day24/CrossedWires.kt

Lines changed: 88 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,28 @@
11
package de.ronny_h.aoc.year24.day24
22

33
import de.ronny_h.aoc.AdventOfCode
4+
import de.ronny_h.aoc.extensions.toBoolean
45
import de.ronny_h.aoc.extensions.toDigit
56

67
fun main() = CrossedWires().run(66055249060558, 0)
78

8-
class CrossedWires: AdventOfCode<Long>(2024, 24) {
9+
class CrossedWires : AdventOfCode<Long>(2024, 24) {
910

10-
class And: (Boolean, Boolean) -> Boolean {
11+
class And : (Boolean, Boolean) -> Boolean {
1112
override fun invoke(a: Boolean, b: Boolean) = a && b
1213
override fun toString() = "AND"
1314
override fun equals(other: Any?) = other is And
1415
override fun hashCode(): Int = javaClass.hashCode()
1516
}
16-
class Or: (Boolean, Boolean) -> Boolean {
17+
18+
class Or : (Boolean, Boolean) -> Boolean {
1719
override fun invoke(a: Boolean, b: Boolean) = a || b
1820
override fun toString() = "OR"
1921
override fun equals(other: Any?) = other is Or
2022
override fun hashCode(): Int = javaClass.hashCode()
2123
}
22-
class Xor: (Boolean, Boolean) -> Boolean {
24+
25+
class Xor : (Boolean, Boolean) -> Boolean {
2326
override fun invoke(a: Boolean, b: Boolean) = a xor b
2427
override fun toString() = "XOR"
2528
override fun equals(other: Any?) = other is Xor
@@ -39,7 +42,7 @@ class CrossedWires: AdventOfCode<Long>(2024, 24) {
3942
.map {
4043
val (term, result) = it.split(" -> ")
4144
val (in1, op, in2) = term.split(" ")
42-
val operation = when(op) {
45+
val operation = when (op) {
4346
"AND" -> And()
4447
"OR" -> Or()
4548
"XOR" -> Xor()
@@ -81,7 +84,86 @@ class CrossedWires: AdventOfCode<Long>(2024, 24) {
8184
}
8285

8386
override fun part2(input: List<String>): Long {
84-
TODO("Not yet implemented")
87+
// inputs: x00..x44, y00..y44
88+
// outputs: z00..z45
89+
val gates = parseGates(input)
90+
val wires = parseWires(input).associateBy(Wire::name)
91+
92+
simulateGates(wires, gates)
93+
add(0, 0, wires, gates)
94+
add("1".repeat(45).toLong(2), 0, wires, gates)
95+
add(0, "1".repeat(45).toLong(2), wires, gates)
96+
add("1".repeat(45).toLong(2), "1".repeat(45).toLong(2), wires, gates)
97+
98+
return 0
99+
}
100+
101+
private fun add(
102+
x: Long,
103+
y: Long,
104+
wires: Map<String, Wire>,
105+
gates: List<Gate>
106+
) {
107+
val modifiedWires = wires.toMutableMap()
108+
modifiedWires.putAll(x.toWires("x"))
109+
modifiedWires.putAll(y.toWires("y"))
110+
simulateGates(modifiedWires, gates)
111+
}
112+
113+
private fun Long.toWires(prefix: String): Map<String, Wire> = toString(2)
114+
.reversed()
115+
.padEnd(45, '0')
116+
.mapIndexed { i, digit ->
117+
Wire(prefix + i.toString().padStart(2, '0'), digit.toBoolean())
118+
}
119+
.associateBy(Wire::name)
120+
121+
private fun simulateGates(
122+
wires: Map<String, Wire>,
123+
gates: List<Gate>
124+
) {
125+
println("--- simulating gates ---")
126+
val x0 = wires.withPrefixAsDecimal("x")
127+
val y0 = wires.withPrefixAsDecimal("y")
128+
129+
val simulatedWires = wires.simulateGates(gates)
130+
131+
val x1 = simulatedWires.withPrefixAsDecimal("x")
132+
val y1 = simulatedWires.withPrefixAsDecimal("y")
133+
134+
val sumSimulatedBinary = simulatedWires.withPrefixAsBinary("z")
135+
val zWires = simulatedWires.withPrefixSortedByLSBFirst("z")
136+
val sumSimulated = sumSimulatedBinary.toLong(2)
137+
val sumExpectedBinary = (x1 + y1).toString(2).padStart(46, '0')
138+
139+
// check that the input wires aren't modified
140+
check(x0 == x1)
141+
check(y0 == y1)
142+
143+
println("inputs:")
144+
println("x=$x0")
145+
println("y=$y0")
146+
println()
147+
println("expected : x+y=${x1 + y1}")
148+
println("simulated: z =$sumSimulated")
149+
println()
150+
println("as binary:")
151+
println("expected : x+y=$sumExpectedBinary")
152+
println("simulated: z =$sumSimulatedBinary")
153+
154+
val differentIndices = mutableListOf<Int>()
155+
for (i in sumSimulatedBinary.indices) {
156+
if (sumSimulatedBinary[i] != sumExpectedBinary[i]) {
157+
differentIndices.add(i)
158+
}
159+
}
160+
println("different indices: $differentIndices (${differentIndices.size})")
161+
162+
val wrongWires = differentIndices.map { zWires[it].name }
163+
println("zWires at these indices: $wrongWires")
164+
165+
val gatesToChange = gates.filter { it.out in wrongWires }
166+
println("gates to change: $gatesToChange")
85167
}
86168
}
87169

0 commit comments

Comments
 (0)