Skip to content

Instantly share code, notes, and snippets.

@ngoctnq
Created November 2, 2021 10:15
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ngoctnq/99589e821f99be27b8c05bc8ae714e98 to your computer and use it in GitHub Desktop.
Save ngoctnq/99589e821f99be27b8c05bc8ae714e98 to your computer and use it in GitHub Desktop.
Hanoi Love interpreter.
'''
I couldn't find a modern interpreter for Hanoi Love so here goes.
@author Ngoc N. Tran (@ngoctnq)
@created November 2nd, 2021
'''
from typing import Union
def run_hl(instructions: str, stdin: Union[list, bytes] = []):
'''
Run the Hanoi Love program.
Parameters:
:param instructions : the program instructions
:param stdin (optional): the stdin to pipe into the program
may be a list or anything that can be converted into a list
'''
stacks = [[], [], [], []]
stack_idx = 0
register = 0
skipping = False
iomode = False
insptr = 0
output = []
if type(stdin) is not list:
stdin = list(stdin)
while True:
if insptr == len(instructions):
return bytes(output)
c = instructions[insptr]
insptr += 1
if skipping:
if c == '!':
skipping = False
continue
if c == '.':
stack_idx = (stack_idx + 1) % 4
elif c == "'":
if iomode:
output.append(register)
iomode = False
elif stack_idx == 3:
stacks[3].append(insptr - 2)
else:
stacks[stack_idx].append(register)
elif c == ',':
if iomode:
register = stdin.pop(0)
iomode = False
elif len(stacks[stack_idx]) == 0:
if stack_idx == 0:
register = 1
continue
if stack_idx < 3:
register = 0
continue
raise
elif stack_idx == 3:
insptr = stacks[3].pop()
else:
register = stacks[stack_idx].pop()
elif c == ';':
if iomode:
register += stdin.pop(0)
iomode = False
elif len(stacks[stack_idx]) == 0:
if stack_idx == 0:
register += 1
continue
if stack_idx < 3:
continue
raise
elif stack_idx == 3:
stacks[stack_idx].pop()
else:
register += stacks[stack_idx].pop()
elif c == '`':
if iomode:
register -= stdin.pop(0)
iomode = False
elif len(stacks[stack_idx]) == 0:
if stack_idx == 0:
register -= 1
continue
if stack_idx < 3:
continue
raise
elif stack_idx == 3:
stacks[stack_idx].pop()
else:
register -= stacks[stack_idx].pop()
elif c == '"':
iomode = True
elif c == ':':
if register == 0:
skipping = True
elif c == '!':
return bytes(output)
if __name__ == '__main__':
assert run_hl('''.'...,;';';;';';';'.,...;"'.'...,;;';;';';;'.,...;"';;;;;;;"'"';;;"'.'.,...'...,;';';';';'.,...;"'..'...,'...,;;';';';'.,...`"'.'...,;;';';';'.,...;"';;;"'``````"'````````"'.'.,..;"'.'.,..;;;;;;;;;;"\'''') == b'Hello World!\n'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment