summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteven Le Rouzic <steven.lerouzic@gmail.com>2024-12-17 22:01:36 +0100
committerSteven Le Rouzic <steven.lerouzic@gmail.com>2024-12-20 15:33:16 +0100
commit431ee3626a823f68a0e7824676f82d9c40f8211e (patch)
tree1854137d0271b01ccb2d8b0b1c2046996ac9b7dd
parent68f5cce6fb9f69c666471ee64d0c9d004f24e483 (diff)
Day 17
-rw-r--r--day17/go.mod3
-rw-r--r--day17/main.go115
-rw-r--r--go.work1
3 files changed, 119 insertions, 0 deletions
diff --git a/day17/go.mod b/day17/go.mod
new file mode 100644
index 0000000..cc9fe5f
--- /dev/null
+++ b/day17/go.mod
@@ -0,0 +1,3 @@
+module stevenlr.com/aoc2024/day17
+
+go 1.23.3
diff --git a/day17/main.go b/day17/main.go
new file mode 100644
index 0000000..7e45e94
--- /dev/null
+++ b/day17/main.go
@@ -0,0 +1,115 @@
+package main
+
+import (
+ "fmt"
+)
+
+func main() {
+ fmt.Println("4,6,3,5,6,3,5,2,1,0,")
+ execute(729, 0, 0, []byte{0, 1, 5, 4, 3, 0})
+
+ fmt.Println("7,1,3,4,1,2,6,7,1,")
+ execute(46187030, 0, 0, []byte{2, 4, 1, 5, 7, 5, 0, 3, 4, 0, 1, 6, 5, 5, 3, 0})
+
+ // Example
+ // while (a != 0) {
+ // a = a >> 3
+ // print(a%8)
+ // }
+
+ // Data
+ // while (a != 0) {
+ // b = a % 8
+ // b = b ^ 5
+ // c = a >> b
+ // a = a >> 3
+ // b = b ^ c
+ // b = b ^ 6
+ // print(b % 8)
+ // }
+ part2([]byte{2, 4, 1, 5, 7, 5, 0, 3, 4, 0, 1, 6, 5, 5, 3, 0})
+}
+
+func solve(ops []byte, forOp int, startingA int64) bool {
+ if forOp < 0 {
+ fmt.Println(startingA)
+ return true
+ }
+
+ // For the last iteration, only the last 3 can be non 0.
+ // So we only have 8 values to test.
+ // For the other operands to invert, the higher bits are fixed
+ // so we only check the last 3 bits.
+ for n := range 8 {
+ a := (startingA << 3) | int64(n)
+ b := a % 8
+ b = b ^ 5
+ c := a >> b
+ b = b ^ c
+ b = b ^ 6
+ if byte(b%8) == ops[forOp] && solve(ops, forOp-1, a) {
+ return true
+ }
+ }
+
+ return false
+}
+
+func part2(ops []byte) (a int64) {
+ solve(ops, len(ops)-1, 0)
+ return
+}
+
+func execute(a, b, c int64, ops []byte) {
+ pc := 0
+
+ readOp := func() (op byte) {
+ op = ops[pc]
+ pc++
+ return
+ }
+
+ getCombo := func(op byte) int64 {
+ if op <= 3 {
+ return int64(op)
+ }
+
+ switch op {
+ case 4:
+ return a
+ case 5:
+ return b
+ case 6:
+ return c
+ }
+
+ panic("")
+ }
+
+ for pc < len(ops)-1 {
+ switch readOp() {
+ case 0:
+ a = a >> getCombo(readOp())
+ case 1:
+ b = b ^ int64(readOp())
+ case 2:
+ b = getCombo(readOp()) % 8
+ case 3:
+ if a != 0 {
+ pc = int(readOp())
+ }
+ case 4:
+ b = b ^ c
+ pc++
+ case 5:
+ fmt.Print(getCombo(readOp()) % 8)
+ fmt.Print(",")
+ case 6:
+ b = a >> getCombo(readOp())
+ case 7:
+ c = a >> getCombo(readOp())
+ }
+ }
+
+ fmt.Println("")
+}
diff --git a/go.work b/go.work
index 60d840c..ad53500 100644
--- a/go.work
+++ b/go.work
@@ -9,6 +9,7 @@ use (
./day14
./day15
./day16
+ ./day17
./day2
./day3
./day4