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("") }