| #include <bits/stdc++.h> |
| using namespace std; |
|
|
| struct Label { |
| int pos = -1; |
| }; |
|
|
| enum class InstrType { POP, HALT }; |
|
|
| struct Instr { |
| InstrType type; |
| int a = 1, b = 1; |
| Label *x = nullptr, *y = nullptr; |
| }; |
|
|
| struct Builder { |
| static constexpr int A_ALWAYS_MISMATCH = 1024; |
| static constexpr int TEMP_NOP = 1023; |
| static constexpr int TEMP_EXIT = 1022; |
|
|
| vector<Instr> prog; |
| vector<unique_ptr<Label>> labels; |
| int nextMarker = 1; |
|
|
| Label* newLabel() { |
| labels.emplace_back(make_unique<Label>()); |
| return labels.back().get(); |
| } |
|
|
| void bind(Label* l) { |
| if (!l) return; |
| if (l->pos != -1) { |
| |
| return; |
| } |
| l->pos = (int)prog.size() + 1; |
| } |
|
|
| void emitPopGoto(int a, Label* x, int b, Label* y) { |
| Instr in; |
| in.type = InstrType::POP; |
| in.a = a; |
| in.b = b; |
| in.x = x; |
| in.y = y; |
| prog.push_back(in); |
| } |
|
|
| void emitHalt(int b, Label* y) { |
| Instr in; |
| in.type = InstrType::HALT; |
| in.b = b; |
| in.y = y; |
| prog.push_back(in); |
| } |
|
|
| void emitPush(int v, Label* go) { |
| |
| emitPopGoto(A_ALWAYS_MISMATCH, go, v, go); |
| } |
|
|
| void emitPopExpected(int v, Label* go) { |
| emitPopGoto(v, go, TEMP_NOP, go); |
| } |
|
|
| void emitNOP(Label* cont) { |
| Label* afterPush = newLabel(); |
| emitPush(TEMP_NOP, afterPush); |
| bind(afterPush); |
| emitPopExpected(TEMP_NOP, cont); |
| } |
|
|
| Label* buildEven(uint64_t E, Label* cont, Label* start = nullptr) { |
| if (E == 0) { |
| if (start != nullptr) { |
| |
| |
| } |
| return cont; |
| } |
|
|
| if (!start) start = newLabel(); |
| bind(start); |
|
|
| if (E == 2) { |
| emitNOP(cont); |
| return start; |
| } |
| if (E == 4) { |
| Label* mid = newLabel(); |
| emitNOP(mid); |
| buildEven(2, cont, mid); |
| return start; |
| } |
|
|
| if (E % 4 == 2) { |
| Label* rest = newLabel(); |
| emitNOP(rest); |
| buildEven(E - 2, cont, rest); |
| return start; |
| } |
|
|
| |
| int marker = nextMarker++; |
| if (marker >= TEMP_EXIT) marker = 1; |
| Label* bodyStart = newLabel(); |
| Label* check = newLabel(); |
| Label* popExit = newLabel(); |
|
|
| emitPush(marker, bodyStart); |
|
|
| uint64_t L = E / 2 - 2; |
| buildEven(L, check, bodyStart); |
|
|
| bind(check); |
| |
| emitPopGoto(marker, bodyStart, TEMP_EXIT, popExit); |
|
|
| bind(popExit); |
| emitPopExpected(TEMP_EXIT, cont); |
|
|
| return start; |
| } |
| }; |
|
|
| int main() { |
| ios::sync_with_stdio(false); |
| cin.tie(nullptr); |
|
|
| long long k_in; |
| if (!(cin >> k_in)) return 0; |
| uint64_t k = (uint64_t)k_in; |
| uint64_t E = k - 1; |
|
|
| Builder b; |
| Label* halt = b.newLabel(); |
|
|
| if (E > 0) { |
| Label* entry = b.newLabel(); |
| b.buildEven(E, halt, entry); |
| } |
| |
|
|
| b.bind(halt); |
| b.emitHalt(1, halt); |
|
|
| int n = (int)b.prog.size(); |
| |
| for (auto &lp : b.labels) { |
| if (lp->pos == -1) { |
| |
| lp->pos = 1; |
| } |
| } |
| if (n < 1) n = 1; |
| if (n > 512) { |
| |
| cout << 1 << "\n"; |
| cout << "HALT PUSH 1 GOTO 1\n"; |
| return 0; |
| } |
|
|
| cout << n << "\n"; |
| for (int i = 0; i < n; i++) { |
| const auto &in = b.prog[i]; |
| if (in.type == InstrType::HALT) { |
| cout << "HALT PUSH " << in.b << " GOTO " << in.y->pos << "\n"; |
| } else { |
| cout << "POP " << in.a << " GOTO " << in.x->pos |
| << " PUSH " << in.b << " GOTO " << in.y->pos << "\n"; |
| } |
| } |
| return 0; |
| } |