Skip to content

Instantly share code, notes, and snippets.

@harrynull
Created October 30, 2021 13:24
Show Gist options
  • Save harrynull/24a7ab92ae48b318c158539daac5e148 to your computer and use it in GitHub Desktop.
Save harrynull/24a7ab92ae48b318c158539daac5e148 to your computer and use it in GitHub Desktop.
compiler written for hackergame 2021
import sys
i = 0
j = 0
ret = ""
ops = {
'read': '~',
'output': '.',
'pop': '$',
'nop': '?',
'dup': ':',
'not': '!',
'mod': '%',
}
defined = {}
markers = {}
def cur_cmd():
return defined.get((i, j))
def add_command(cmd, nl):
global ret, defined
ret += f"({i}, {j}, 0) -> {ord(cmd)} "
if (i, j) in defined and defined[(i, j)] != cmd:
print(i, j, "redefined!", defined[(i, j)], '->', cmd, "@", nl + 1, file=sys.stderr)
defined[(i, j)] = cmd
TEST = 1
USE_TEST_PROG = 0
TEST_PROG = """
v*
#1
nop*
#2
nop*
#3
nop
@test
>
nop
nop
goto 4 test
nop
nop
nop
goto 6 test
goto 1 test
nop
@test2
>
nop
"""
with open('prog.txt') as prog:
prog_to_parse = prog.readlines() if not USE_TEST_PROG else TEST_PROG.splitlines()
for nl, line in enumerate(prog_to_parse):
line = line.strip()
if len(line) == 0: continue
in_place = False
if line[-1] == '*' and len(line) > 1:
in_place = True
line = line[:-1]
if line[0] == '!':
if line[1] == 'w': j -= 1
if line[1] == 's': j += 1
if line[1] == 'a': i -= 1
if line[1] == 'd': i += 1
continue
if line[0] == '#':
if line[1:].isdigit():
j = int(line[1:])
continue
if line[0] == '@':
markers[line[1:]] = (i, j)
continue
if line[0] == '$':
i, j = markers[line[1:]]
continue
if line == "debug":
print(i, j, file=sys.stderr)
continue
if line == 'wrap up':
j -= 1
add_command('>', nl)
i += 1
add_command('v', nl)
j += 1
add_command('>', nl)
i += 1
continue
if line == 'wrap down':
j += 1
add_command('>', nl)
i += 1
add_command('^', nl)
j -= 1
add_command('>', nl)
i += 1
continue
if line.split()[0] == 'nop' and len(line) > 4:
for cmd in range(int(line.split()[1])):
add_command('?', nl)
i += 1
continue
if line.split()[0] == 'fetch':
tar = line.split()[1]
for cmd in ['1', tar, '\\', ':', '2', str(int(tar) + 1), '\\']:
add_command(cmd, nl)
i += 1
continue
if line.split()[0] == 'goto':
_, channel, marker_id = line.split()
oldi, oldj = i, j
channel = int(channel)
went_down = j < channel
if j != channel:
add_command('^' if j > channel else 'v', nl)
j += 1 if j < channel else -1
while j != channel:
add_command('?', nl)
j += 1 if j < channel else -1
add_command('<', nl)
i -= 1
while i > markers[marker_id][0]:
if (i, j) not in defined:
add_command('?', nl)
elif defined[(i, j)] != '?' and defined[(i, j)] != '<':
print(i, j, "redefined!", defined[(i, j)], '-x> nop', "@", nl + 1, file=sys.stderr)
i -= 1
target_j = markers[marker_id][1]
add_command('^' if j > target_j else 'v', nl)
if j != target_j:
j += 1 if j < target_j else -1
while j != target_j:
if cur_cmd() != '?' and cur_cmd() != '^' if j > target_j else 'v':
add_command('?', nl)
j += 1 if j < target_j else -1
i, j = oldi, oldj
i += 1
continue
if line in ops:
line = ops[line]
add_command(line, nl)
if not in_place:
i += 1
ret += " END"
print(ret)
if TEST:
board = [[' ' for _ in range(512)] for _ in range(11)]
for c, d in defined.items():
board[c[1]][c[0]] = d
for i, line in enumerate(board):
print(str(i).zfill(2), ''.join(line), file=sys.stderr)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment