Solving (and Animating) Advent of Code with 아희 by mcyc
The original Korean version of this post can be found here.
The 2021 Advent of Code challenge has just ended. Typically, I do the problems in Python or Julia (or, this year, some in Dart), but this time I also solved the first day’s problem using 아희 (Aheui), a Korean esoteric programming language. On top of this, I hooked up my 아희 interpreter to the Manim animation library to generate animations that show the internal state of the 아희 program as it executes!
아희 Crash Course
To understand the rest of this post, one should first be familiar with 아희. There is a complete English specification, but here I will introduce the main themes of the language.
아희 is written as a 2-dimensional grid of Korean characters. Each Korean character encodes an instruction (add
, subtract
, push
, swap
, etc), a direction, and possibly some parameters for the function.
For example, here is a program that outputs Hello, world!
:
밤밣따빠밣밟따뿌
빠맣파빨받밤뚜뭏
돋밬탕빠맣붏두붇
볻뫃박발뚷투뭏붖
뫃도뫃희멓뭏뭏붘
뫃봌토범더벌뿌뚜
뽑뽀멓멓더벓뻐뚠
뽀덩벐멓뻐덕더벅
Korean characters are made up of three parts, the initial consonant, a vowel, and an (optional) final consonant. For example, 한
is ㅎ/ㅏ/ㄴ
and 가
is ㄱ/ㅏ
(with no final consonant). When reading a character, the top or top-left section is the initial consonant. The middle/middle-right/right is the vowel, and the bottom is the final consonant. A visual introduction can be found here.
In 아희, the initial consonant determines the instruction. A full list of these can be found in the specification, but later on I will provide a list of the relevant ones for this post.
The directional information is provided by the vowel. As you execute an 아희 program, you traverse the grid with some momentum. When you execute a command, the vowel tells you how to update your momentum, and then you can determine the next cell. Conveniently, the vowel/direction mappings are determined by the shape of the vowel. For example, ㅏ
means “your new momentum is right with magnitude 1”. Likewise, ㅜ
would give a downwards momentum with magnitude 1. Vowels like ㅑ/ㅕ/ㅛ/ㅠ
are the same but with magnitude 2. Other vowels reflect the momentum, and some have no effect. One other key feature is that, if an instruction fails (for example, if the instruction is add
, but an invalid parameter is passed), the momentum information is reflected (so that ㅏ
would act as ㅓ
).
The final consonant acts as a parameter to some instructions and has no effect on others. Depending on the instruction, the final consonant can act as a pointer to select certain things (mainly data structures), or it can act as some numerical consonant. In the chart of instructions below, the effect of the final consonant is given.
An 아희 program has access to several data structures: 26 stacks, 1 queue, and 1 undefined extension protocol. Each data structure is mapped to one final consonant so that they can be easily indexed. At any time during the execution of a program, there is one “active” data structure, upon which instructions can act. The ㅅ
command allows one to select a new active data structure.
아희 programs begin at the top left of the 2-d code grid, and execute continuously until a cell with the instruction ㅎ
is reached, which immediately terminates the program.
A Slight Modification to the 아희 Specification
아희 allows for reading from user input (via the ㅂ
-push instruction with a ㅇ
or ㅎ
final-consonant parameter). However, this does not necessarily cover reading from a piped in file (which is required here, as Advent of Code inputs are given as text files). I slightly deviated from the specification in my interpreter to make the ㅂ
-push instruction read from an input file, with the condition that, if a read is performed after the end-of-file had been reached, it would count as a failed instruction (and so the direction information would be reversed, as explained above).
Advent of Code Day 1 Solution
This year, the first day’s problem was roughly: “in a list of numbers, how many times is a number immediately followed by a larger number?” For example, if the list was 1, 4, 2, 5, 7
, then the pairs 1->4, 2->5, 5->7
means the correct answer must be 3
.
In Python, a possible solution is:
if __name__ == '__main__':
f = open('input.txt', 'r')
x = int(f.readline())
count = 0
for line in f:
y = int(line)
if y > x: count += 1
x = y
print(count)
In 아희, I solved it in the following way:
삼바샇뱡숨방파빠파주
마르코하멍솧더섬썸퍼
There are several instructions used in this program (listed here in Korean alphabetical order):
-
ㄷ
-> add-
From the active data structure, pop the
-