|
| 1 | +---toml |
| 2 | +[fuzz] |
| 3 | +exec = ["cargo", "run", "--release", "--", "generate"] |
| 4 | +env = {} |
| 5 | + |
| 6 | +[judge] |
| 7 | +exec = ["cargo", "run", "--release", "--quiet", "--", "validate"] |
| 8 | + |
| 9 | +[problem] |
| 10 | +points = 10 |
| 11 | +difficulty = 1 |
| 12 | +--- |
| 13 | + |
| 14 | +# 📜 Bytecode Interpreter |
| 15 | + |
| 16 | +Congratulations! You've been hired as part of a top-secret division that |
| 17 | +specialises in decoding badly-coded machines. |
| 18 | +As your initiation, your manager has decided it's best for you to dive right into |
| 19 | +a typical day-to-day task that you'll have to carry out. |
| 20 | + |
| 21 | +Next thing you know, your manager has put a massive sequence of archaic bytecode instructions |
| 22 | +on your desk, together with some sort of key that translates what each of the instructions do. |
| 23 | + |
| 24 | +Initially, your manager (not knowing any better) asked you to run the code until termination |
| 25 | +and report to him what the output is. |
| 26 | +Thankfully, you remembered that the |
| 27 | +[Halting Problem](https://en.wikipedia.org/wiki/Halting_problem) |
| 28 | +is undecidable, and thus you managed to avoid an impossible task. |
| 29 | + |
| 30 | +Your manager is quick on their feet though. |
| 31 | +You're now given the following task. |
| 32 | +**Given a series of bytecode instructions, if you run it for 10,000,000 steps, |
| 33 | +what will the sum of all the variables be, and what value will the output register have?** |
| 34 | + |
| 35 | +Firstly, here's a brief layout of the machine. |
| 36 | +It has three components used for storing values: |
| 37 | +* A **namespace**, where variables named by a single lowercase character (a-z) |
| 38 | + can store one signed 64-bit integer and are always initialised to `0` |
| 39 | + at the start of the program, |
| 40 | +* A **stack**, where values (always signed 64-bit integers) |
| 41 | + are stored and retrieved in a first-in-last-out fashion, and |
| 42 | +* An **output register**, which functions just like a regular variable in the namespace, |
| 43 | + but is referred to in instructions by a `!` symbol, and is initialised to `1`. |
| 44 | + |
| 45 | +Next, here is a list of all types of bytecode instructions it supports. |
| 46 | +* `LOAD <value>`: Puts a copy of `<value>` on the top of the **stack**. |
| 47 | +* `STORE <value>`: Stores the value at the top of the **stack** |
| 48 | + in the place indicated by `<value>`. If the **stack** is currently empty, |
| 49 | + a `0` value is placed. |
| 50 | + `<value>` in this case will *never* be an integer. |
| 51 | +* `LABEL <name>`: Does nothing, but counts as an instruction. |
| 52 | + Acts as a point in the bytecode that other instructions can jump to. |
| 53 | +* `JUMP <name>`: Jump to the line that contains a `LABEL` instruction |
| 54 | + associated with the same `<name>`. |
| 55 | + Such a `LABEL` line is guaranteed to exist such that any `JUMP` is valid, |
| 56 | + and that exactly *one* line will match, making this instruction always unambiguous. |
| 57 | +* `ADD <value> <value>`: Add the two `<value>`s and push the result on the top of the **stack**. |
| 58 | +* `SUB <value> <value>`: Subtract the second `<value>` from the first `<value>` |
| 59 | + and push the result on the top of the **stack**. |
| 60 | +* `MUL <value> <value>`: Multiply the two `<value>`s together |
| 61 | + and push the result on the top of the **stack**. |
| 62 | +* `DIVMOD <value> <value>`: Conduct a division of the first `<value>` by the second `<value>`. |
| 63 | + First push the quotient of the division onto the **stack**, |
| 64 | + then push the remainder (modulo) of the division onto the **stack**. |
| 65 | + If, however, the second `<value>` is zero, then instead of the quotient and remainder, |
| 66 | + push the original `<value>`s onto the **stack** instead. |
| 67 | + (i.e., push the first `<value>` first, then the second `<value>` next.) |
| 68 | +* `CMP <value> <value>`: Compares the first `<value>` against the second `<value>`. |
| 69 | + If the two are equal, push `0` onto the **stack**. |
| 70 | + If the first is greater than the second, push `1` onto the **stack**. |
| 71 | + If the first is less than the second, push `-1` onto the **stack**. |
| 72 | +* `BRANCHZERO <name>`: Pops off the top value of the **stack** |
| 73 | + (if empty, the value is taken as `0`). If this value is equal to `0`, |
| 74 | + jumps to the line that reads `LABEL <name>`. |
| 75 | +* `BRANCHCMP <value> <value> <ordering> <name>`: |
| 76 | + Compares the first `<value>` against the second `<value>`. |
| 77 | + If their relation is the same as given by `<ordering>`, |
| 78 | + then jump to the line that reads `LABEL <name>`. |
| 79 | + `<ordering>` is one of three values: |
| 80 | + * `EQ` matches when the first value is equal to the second value, |
| 81 | + * `GT` matches when the first value is greater than the second value, |
| 82 | + * `LS` matches when the first value is less than the second value. |
| 83 | + |
| 84 | +In the above, `<value>` can be one of three different formats: |
| 85 | +* A single integer from the range `-50` to `50` inclusive, |
| 86 | +* A single character denoting the value of a variable in the **namespace**, |
| 87 | +* A `!` symbol, denoting the value of the **output register**. |
| 88 | + |
| 89 | +Additionally, every `<name>` consists of three lowercase letters exactly. |
| 90 | + |
| 91 | +## Example |
| 92 | + |
| 93 | +Consider the following sequence of instructions. |
| 94 | +``` |
| 95 | +JUMP str |
| 96 | +LABEL pqr |
| 97 | +JUMP end |
| 98 | +LABEL str |
| 99 | +LOAD 6 |
| 100 | +STORE a |
| 101 | +LOAD 2 |
| 102 | +STORE ! |
| 103 | +ADD a ! |
| 104 | +STORE b |
| 105 | +BRANCHCMP b 8 EQ pqr |
| 106 | +LABEL end |
| 107 | +``` |
| 108 | +The following instructions will be executed: |
| 109 | +1. `JUMP str`: Jumps forward to the line 3 lines down. |
| 110 | +2. `LABEL str`: Does nothing. Moves to the next instruction. |
| 111 | +3. `LOAD 6`: Loads the value `6` onto the stack. |
| 112 | +4. `STORE a`: Pops `6` from the stack, stores it in the variable `a`. |
| 113 | +5. `LOAD 2`: Loads the value `2` onto the stack. |
| 114 | +6. `STORE !`: Pops `2` from the stack, stores it in the output register. |
| 115 | +7. `ADD a !`: Adds the values of the variable `a` and the output register, |
| 116 | + which is `6 + 2 = 8`. Hence, `8` is loaded onto the stack. |
| 117 | +8. `STORE b`: Pops `8` from the stack, stores it in the variable `b`. |
| 118 | +9. `BRANCHCMP b 8 EQ pqr`: Compares the variable `b` with the value `8`. |
| 119 | + Since they are equal in value, jump to the line that reads `LABEL pqr` (second from top). |
| 120 | +10. `LABEL pqr`: Does nothing. Moves to the next instruction. |
| 121 | +11. `JUMP end`: Jumps all the way to the last line (which reads `LABEL end`). |
| 122 | +12. `LABEL end`: Does nothing. Moves to the next (non-existent) instruction, thus halting. |
| 123 | + |
| 124 | +At the end, the **namespace** contains the variables `a` with value `6` and `b` with value `8`. |
| 125 | +The **output register** contains the value `2`. |
| 126 | +Hence, the output in this case should be |
| 127 | +``` |
| 128 | +14 2 |
| 129 | +``` |
| 130 | +since the sum of all variables in the namespace is 14. |
| 131 | + |
| 132 | +Also note that in the above, **12** steps were executed. |
| 133 | + |
| 134 | +## Input |
| 135 | + |
| 136 | +Your input is the list of bytecode instructions to be executed. |
| 137 | +Each instruction will be on a new line, |
| 138 | +and the operands to each instruction are space separated. |
| 139 | + |
| 140 | +## Output |
| 141 | + |
| 142 | +Your output should be two space-separated integers. |
| 143 | +The first integer is the sum of all variables in the namespace, |
| 144 | +and the second integer is the value of the output register |
| 145 | +after the 10,000,000 steps have concluded (or after the program halts, whichever is earlier). |
0 commit comments