# Emoji Stack In the world of esolangs, you might have heard of all kinds of odd programming languages. This time, PatriotCTF introduced us to **Emoji Stack**, a stack-based programming language that uses emojis as its instructions. ## Understanding the language The challenge provided us with an example program to better understand how the language works. Here, we only look at the first four cells on the stack. I'll use `^` to indicate the current cell. ``` [0] [0] [0] [0] ^ 👍🔁47 [0x48] [0] [0] [0] ^ ``` As you can see, `👍` makes the value go up by `1`. `🔁47` repeats the execution `0x47` more times. That makes for a total of `0x48` (`72` in decimal). Onto the next instruction: ``` [0x48] [0] [0] [0] ^ 💬 Output: 'H' ``` ASCII is a way for us to represent a character as a number. `0x48` maps to the letter `H` in ASCII. Later we'll use python's `chr()` to do this conversion. Next, we take a look at the instruction to move the stack pointer to the right: ``` [0x48] [0] [0] [0] ^ 👉 [0x48] [0] [0] [0] ^ ``` The pointer now points to the next cell on the stack. Subsequent `👍`s, `👎`s or `💬`s now refer to this cell. ``` [0x48] [0] [0] [0] ^ 👍🔁68 [0x48] [0x69] [0] [0] ^ 💬 Output: 'i' ``` By now, we have printed out `Hi` on the screen. ## Implementing the language, for real I use python as my language of choice, since it has built-in support for emojis. You can choose any other programming language if you prefer. ### Extracting instructions from input.txt Here, we write the first lines to read the source code from the input file. ```python= with open('input.txt', 'rb') as input_file: source = input_file.read().decode() print(source) # delete later ``` To ensure that we handle emojis properly, we read `input.txt` in `read bytes` mode (`rb` for short) and call `.decode()` to turn the file content into a string. Let's take a look at the value of `source` to make sure everything is working as intended. It should look something like this: ``` Output: 👉👉👉👉👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👉🔁08👍🔁34👈👈👈👈👈👈👈👈👈👈👍🔁48👉🔁15👍🔁5e👈🔁07👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👉🔁02👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👈👈👈👈👈👈👈👈👈👈👈👈👈👈👈👈👈👈👍🔁42👉🔁02👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👉🔁17👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👈🔁14👍🔁20👉🔁06👍🔁51👉🔁0c👍🔁34👉👉👍🔁46👈🔁14👍🔁4d👈🔁01👍🔁51👉🔁04👍🔁20👉🔁03👍🔁2f👉👉👉👉👉👉👉👉👍🔁4d👈🔁17👍🔁42👉👉👉👉👉👉👉👉👉👉👉👉👉👉👉👉👉👉👉👉👉👉👉👉👉👉👉👉👉👉👉👉👉👉👉👍🔁7c👈👈👈👈👈👈👈👈👈👈👈👈👈👈👈👈👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👉🔁0c👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👉👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👈👈👈👈👈👈👈👈👈👈👈👈👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👉🔁0c👍🔁32👈👈👈👈👈👈👈👈👈👈👈👈👈👈👈👈👈👈👈👈👈👈👈👈👈👈👈👈👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👉🔁04👍🔁5e👉👉👉👉👉👉👉👉👉👉👉👉👉👉👉👍🔁47👈🔁0f👍🔁46👉👉👉👉👉👉👉👉👉👉👉👉👉👉👉👉👉👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👈🔁03👍🔁20👈🔁08👍🔁5e👉🔁10👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👈🔁1d👍🔁40👉🔁10👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👉👉👉👉👍🔁5e👈👈👈👈👈👈👈👈👈👈👈👈👈👈👈👈👈👈👈👈👈👈💬👉💬👉💬👉💬👉💬👉💬👉💬👉💬👉💬👉💬👉💬👉💬👉💬👉💬👉💬👉💬👉💬👉💬👉💬👉💬👉💬👉💬👉💬👉💬👉💬👉💬👉💬👉💬👉💬👉💬👉💬👉💬👉💬👉💬👉💬👉💬 ``` After confirming all is working properly, we can now delete `print(source)`. ### Executing instructions This is what our code will do: - Read each instruction from `source`. - If the instruction is `👉`, `👈`, `👍`, `👎` or `💬`: + Excute. + Move on to the next instruction. - If the instruction is `🔁`: + Get the number of repeats from the two hex digits that follow. + For the number of repeats: + Excute the instruction that came before. + Skip the next two hex digits and move on to the next instruction. But before any of that, we first define the stack we're going to work with: ```python=6 stack = [0] * 256 pointer = 0 ``` Here, we initialize `stack` as a list with 256 cells of `0`s and set `pointer` to the beginning of it. Now we get to our main program loop: ```python=10 i = 0 while i < len(source): if source[i] == '🔁': hexdigits = source[i + 1] + source[i + 2] repeats = int(hexdigits, 16) for _ in range(repeats): execute(source[i - 1]) i += 3 ``` We use `i` to keep track of our current position in `source`. New instructions are read until we get to the end of `source`. When we hit a `🔁`, we get the number of `repeats` by converting the hex digits to decimal. The instruction at `i - 1` is then executed for a `repeats` number of times. Finally, we skip the next two hex digits by advancing `i` by `3`. For other emojis, we execute them once and move on to the next one: ```python=23 else: execute(source[i]) i += 1 ``` Now that we've mapped out the general logic of our solution, we define `execute` after the snippet where we initialize `stack` and `pointer`: ```python=5 stack = [0] * 256 pointer = 0 def execute(emoji): global pointer if emoji == '👉': pointer += 1 elif emoji == '👈': pointer -= 1 elif emoji == '👍': stack[pointer] += 1 elif emoji == '👎': stack[pointer] -= 1 elif emoji == '💬': print(chr(stack[pointer]), end='') i = 0 ``` `execute` takes an `emoji` as its argument and execute the corresponding instruction. `👉` and `👈` manipulate the position of the stack pointer by increasing and decreasing `pointer` by `1`. `pointer` serves as a reference to where we are on the stack. To refer to the current cell, we use `stack[pointer]`. As you can see, `👍` and `👎` increases and decreases the value of the current cell by `1`. Lastly, `💬` uses `chr()` to retrieve the character with the ASCII value of the current cell and prints it out. ### Full script After assembling all the parts of our solution, here's the full script: ```python= with open('input.txt', 'rb') as input_file: source = input_file.read().decode() stack = [0] * 256 pointer = 0 def execute(emoji): global pointer if emoji == '👉': pointer += 1 elif emoji == '👈': pointer -= 1 elif emoji == '👍': stack[pointer] += 1 elif emoji == '👎': stack[pointer] -= 1 elif emoji == '💬': print(chr(stack[pointer]), end='') i = 0 while i < len(source): if source[i] == '🔁': hexdigits = source[i + 1] + source[i + 2] repeats = int(hexdigits, 16) for _ in range(repeats): execute(source[i - 1]) i += 3 else: execute(source[i]) i += 1 ``` After running the script, this is the flag: ``` Output: CACI{TUR!NG_!5_R011!NG_!N_H!5_GR@V3} ```