◧◨/Interpreters
Jump to navigation
Jump to search
Implementations for ◧◨.
Python (by User:stkptr)
import math import sys LEFT = "◧" RIGHT = "◨" # This assumes that the source does not have arbitrary other symbols in it # Files with characters inside commands will not be parsed correctly # Invalid programs are also not explicitly tested for def parse(source): index = 0 parsed = [] def get(i): if i < len(source): return source[i] while index < len(source): if source[index] == LEFT: index += 2 n = 0 while get(index) == RIGHT: index += 1 n += 1 # overstep if get(index) == LEFT and get(index + 1) == RIGHT: index -= 1 n -= 1 parsed.append((-1)**n * math.ceil(n / 2)) elif source[index] == RIGHT: index += 3 parsed.append(None) else: index += 1 return parsed class BoundedTape: def __init__(self, default=0): self.cells = [] self.default = default def __getitem__(self, index): if index >= len(self.cells): return self.default return self.cells[index] def __setitem__(self, index, value): extra = index + 1 - len(self.cells) if extra > 0: self.cells += [self.default] * extra self.cells[index] = value class Tape: def __init__(self, default=0): self.left = BoundedTape(default) self.right = BoundedTape(default) def __getitem__(self, index): if index < 0: return self.left[abs(index) - 1] return self.right[index] def __setitem__(self, index, value): if index < 0: self.left[abs(index) - 1] = value else: self.right[index] = value class Machine: def __init__(self, program): self.tape = Tape(False) self.pointer = 0 self.ip = 0 self.program = program def step(self): if self.ip >= len(self.program): return False if self.program[self.ip] is None: self.tape[self.pointer] = not self.tape[self.pointer] self.pointer += 1 self.ip += 1 else: jump = self.program[self.ip] if self.tape[self.pointer] else 1 self.pointer -= 1 self.ip += jump return True def run(self): running = True while running: running = self.step() def run_source(source): program = parse(source) machine = Machine(program) machine.run() return machine def main(): if len(sys.argv) != 2: print("You must pass a single source filename") return with open(sys.argv[1]) as f: source = f.read() machine = run_source(source) touched = len(machine.tape.left.cells) + len(machine.tape.right.cells) print(f"Program ended with machine altering at most {touched} cell(s)") print(f"Final tape pointer was {machine.pointer}") if __name__ == "__main__": main()