Expand description
§Arithmetic Logic Unit
There are two ways to solve this problem. We can brute force emulate the ALU, but even with memoization this takes a long time to solve. Instead analyzing and reverse engineering the code shows an insight that reduces the problem to a much simpler constraint satisfaction problem.
§Analysis Summary
The code consists of 14 blocks of 18 instructions, each block starting with inp w.
There are 7 “push” blocks and 7 “pop” blocks.
- Push blocks use
zas a stack, multiplying by 26 and addingwplus some constantk₁. Push blocks always add to the stack. - Pop blocks compare the top element of
zplus some constantk₂tow. If the values are equal thenzis “popped” by dividing by 26. Otherwisezis pushed again withwplus some constant.
Since the push/pop blocks are equally numbered and we want z to be zero (empty stack) at the
end of the program, the condition:
w₁ + k₁ + k₂ = w₂
must be true for each matching pair of push/pop blocks. Since we also know that each w is
between 1 and 9 inclusive, that is enough information to determine maximum and minimum values
for each of the fourteen w values.
For example:
- If
k₁ + k₂ = 7thenw₁ + 7 = w₂. - Maximum value of
w₁is 2 whenw₂is 9. - Minimum value of
w₁is 1 whenw₂is 8.
§Detailed Push block analysis
inp w // w = 1 to 9 inclusive
mul x 0 // x = 0
add x z // x = z
mod x 26 // x = z % 26
div z 1 // nop
add x 13 // x = z % 26 + 13
eql x w // if (z % 26 + 13) == w { x = 1 } else { x = 0 }
// However since w is restricted to 1 to 9 this condition is always false
// so x is always 0. Other blocks have different constants but always > 9.
eql x 0 // x = 1 (as 0 == 0)
mul y 0 // y = 0
add y 25 // y = 25
mul y x // y = 25 * 1 = 25
add y 1 // y = 25 + 1 = 26
mul z y // z = 26 * z
mul y 0 // y = 0
add y w // y = w
add y 14 // y = w + 14 (k₁ = 14)
mul y x // y = (w + 14) * 1 = (w + 14)
add z y // z = (26 * z) + (w + 14)§Detailed Push block analysis
inp w // w = 1 to 9 inclusive
mul x 0 // x = 0
add x z // x = z
mod x 26 // x = z % 26
div z 26 // z /= 26 (pop)
add x -13 // x = z % 26 - 13 (k₂ = -13)
eql x w // if (z % 26 - 13) == w { x = 1 } else { x = 0 }
eql x 0 // if (z % 26 - 13) == w { x = 0 } else { x = 1 }
// Inverts the previous conditional.
// Unlike the push blocks, this may true or false
// We'll split into 2 paths, depending on equals (x = 0) or
// not equal (x = 1).
| Equals (x = 0) | Not Equals (x = 1) |
mul y 0 | y = 0 | y = 0 |
add y 25 | y = 25 | y = 25 |
mul y x | y = 25 * 0 = 0 | y = 25 * 1 = 25 |
add y 1 | y = 0 + 1 = 1 | y = 25 + 1 = 26 |
mul z y | z = z (nop) | z = 26 * z |
mul y 0 | y = 0 | y = 0 |
add y w | y = w | y = w |
add y 4 | y = w + 4 | y = w + 4 |
mul y x | y = (w + 4) * 0 | y = (w + 4) * 1 |
add z y | z = z | z = (26 * z) * (w + 4) |Structs§
- Constraint
- Convert matching pairs of blocks into constraints.
For the first digit
valueis-(k₁ + k₂)and second digit value isk₁ + k₂.
Enums§
- Block 🔒
- Blocks are either “push” or “pop”.