| Problem statement | Source code | Tags: VMManual inspectionPuzzle
This is a question type I enjoy a lot: there's more pen-and-paper (or, for me, iPad and typing in a text file) than coding.
I tried to formally work out the required input range, using Hoare logic to symbolically deduce the weakest precondition for each line of code, given that the postcondition is z = 0. This is actually feasible given that no loops exist. I even have a solution that I believe works; the problem is that the branching still leads to an exponential number of paths, and Node OOMs. So I was forced back to manual inspection.
The program has 14 chunks, each of the form:
Among the 14 chunks, only lines 5, 6, 16 may be different in their constant. In particular, <n0> can either be 1 or 26; <n1> can be between -15 and 15; <n2> can be between 1 and 14. Furthermore, n1 <= n0 iff n0 == 26.
If we convert this to TypeScript:
More compactly:
Note that while n1 can be negative, all other numbers are always positive, including z.
This is using z as a stack in base-26:
z.top() == w - n1 and n0 == 26, then z.pop().z.top() == w - n1 and n0 == 1, then do nothing.z.top() != w - n1 and n0 == 1, then z.push(w + n2).z.top() != w - n1 and n0 == 26, then z.replaceTop(w + n2).The goal at the end is to have z empty, and we have 7 n0 == 1 chunks and 7 n0 == 26 chunks, so we need to pop every time we can. We can pair up each push-chunk and pop-chunk, such that w_push + n2_push == w_pop - n1_pop. This creates 7 equations, each of the form w[i] - w[j] = n where i > j.
Because we want to maximize w, we can just greedily maximize each w[i], since these equations are independent of each other. If w[i] - w[j] = n, then when n is positive, set w[i] = 9 and w[j] = 9 - n; when n is negative, set w[j] = 9 and w[i] = 9 + n.
Exactly the same, except we minimize w instead of maximizing it. In this case we want w[i] and w[j] as close to 1 as possible.