| #include <iostream> |
| #include <vector> |
| #include <string> |
| #include <algorithm> |
|
|
| using namespace std; |
|
|
| struct Instruction { |
| string type; |
| int a; |
| int x; |
| int b; |
| int y; |
| }; |
|
|
| vector<Instruction> program; |
| int add_instruction(string type, int a, int x, int b, int y) { |
| program.push_back({type, a, x, b, y}); |
| return program.size(); |
| } |
|
|
| const int UNKNOWN = -1; |
|
|
| struct Layer { |
| string type; |
| int val_in; |
| int val_aux; |
| int val_garbage; |
| int entry_instr; |
| int return_target; |
| }; |
|
|
| int main() { |
| ios_base::sync_with_stdio(false); |
| cin.tie(NULL); |
| long long k; |
| if (!(cin >> k)) return 0; |
|
|
| if (k == 1) { |
| cout << "1\nHALT PUSH 1 GOTO 1\n"; |
| return 0; |
| } |
|
|
| |
| |
| |
| long long t = k - 2; |
| |
| |
| vector<string> layer_types; |
| |
| |
| while (t >= 9) { |
| |
| |
| if (t % 4 == 1) { |
| layer_types.push_back("Double7"); |
| t = (t - 7) / 2; |
| } else { |
| layer_types.push_back("Double9"); |
| t = (t - 9) / 2; |
| } |
| } |
| |
| |
| |
| while (t > 1) { |
| layer_types.push_back("Linear"); |
| t -= 2; |
| } |
| layer_types.push_back("Base"); |
| |
| |
| reverse(layer_types.begin(), layer_types.end()); |
| |
| |
| int current_val = 1; |
| vector<Layer> layers(layer_types.size()); |
| |
| |
| for (int i = layer_types.size() - 1; i >= 0; --i) { |
| layers[i].type = layer_types[i]; |
| layers[i].val_in = current_val++; |
| if (layers[i].type == "Double7" || layers[i].type == "Double9") { |
| layers[i].val_aux = current_val++; |
| layers[i].val_garbage = current_val++; |
| } |
| } |
| |
| int next_instr = 1; |
| |
| |
| int preamble_idx = next_instr++; |
| add_instruction("HALT", 0, 0, 0, 0); |
| |
| |
| int final_halt_idx = next_instr++; |
| add_instruction("HALT", 0, 0, 1, 1); |
| |
| |
| for (int i = 0; i < layers.size(); ++i) { |
| int child_entry = (i > 0) ? layers[i-1].entry_instr : -1; |
| |
| if (layers[i].type == "Base") { |
| layers[i].entry_instr = next_instr++; |
| add_instruction("POP", layers[i].val_in, UNKNOWN, layers[i].val_in, UNKNOWN); |
| } |
| else if (layers[i].type == "Linear") { |
| int start_idx = next_instr++; |
| layers[i].entry_instr = start_idx; |
| |
| add_instruction("POP", layers[i].val_in, UNKNOWN, layers[i-1].val_in, child_entry); |
| |
| int check_idx = next_instr++; |
| add_instruction("POP", layers[i].val_in, UNKNOWN, 1, 1); |
| |
| program[start_idx-1].x = check_idx; |
| layers[i-1].return_target = check_idx; |
| } |
| else { |
| int X = layers[i].val_in; |
| int Y = layers[i].val_aux; |
| int G = layers[i].val_garbage; |
| int child_val = layers[i-1].val_in; |
| |
| int start_idx = next_instr++; |
| layers[i].entry_instr = start_idx; |
| |
| int check_idx = next_instr++; |
| int swap_idx = next_instr++; |
| int pass2_idx = next_instr++; |
| int cleanup_idx = next_instr++; |
| int finish_idx = next_instr++; |
| |
| int delay_idx = -1, restore_idx = -1; |
| if (layers[i].type == "Double9") { |
| delay_idx = next_instr++; |
| restore_idx = next_instr++; |
| } |
| |
| int else_target = (layers[i].type == "Double9") ? delay_idx : cleanup_idx; |
| |
| add_instruction("POP", Y, check_idx, child_val, child_entry); |
| add_instruction("POP", X, swap_idx, G, else_target); |
| add_instruction("HALT", 0, 0, Y, pass2_idx); |
| add_instruction("POP", X, 0, child_val, child_entry); |
| add_instruction("POP", G, finish_idx, 0, 0); |
| add_instruction("POP", Y, UNKNOWN, 0, 0); |
| |
| if (layers[i].type == "Double9") { |
| add_instruction("POP", G, restore_idx, 0, 0); |
| add_instruction("HALT", 0, 0, G, cleanup_idx); |
| } |
| |
| layers[i-1].return_target = check_idx; |
| } |
| } |
| |
| |
| int outer_layer_idx = layers.size() - 1; |
| program[preamble_idx-1].b = layers[outer_layer_idx].val_in; |
| program[preamble_idx-1].y = layers[outer_layer_idx].entry_instr; |
| |
| |
| for (int i = 0; i < layers.size(); ++i) { |
| int target = (i == layers.size() - 1) ? final_halt_idx : layers[i+1].return_target; |
| int instr_to_fix = -1; |
| if (layers[i].type == "Base") { |
| instr_to_fix = layers[i].entry_instr; |
| program[instr_to_fix-1].x = target; |
| } else if (layers[i].type == "Linear") { |
| instr_to_fix = layers[i].entry_instr + 1; |
| program[instr_to_fix-1].x = target; |
| } else { |
| instr_to_fix = layers[i].entry_instr + 5; |
| program[instr_to_fix-1].x = target; |
| } |
| } |
|
|
| cout << program.size() << "\n"; |
| for (const auto& instr : program) { |
| if (instr.type == "HALT") { |
| cout << "HALT PUSH " << instr.b << " GOTO " << instr.y << "\n"; |
| } else { |
| cout << "POP " << instr.a << " GOTO " << instr.x << " PUSH " << instr.b << " GOTO " << instr.y << "\n"; |
| } |
| } |
|
|
| return 0; |
| } |