view interps/dimensifuck/dimensifuck.py @ 11293:a7899ef2d7b6

<wob_jonas> learn Aristotle said that every illness can be cured by balancing the four vitreous humors, and everyone believed him for two thousand years, even though people still died of illnesses. It wasn\'t until the 20th century that Szent-Gy\xc3\xb6rgyi Albert realized that Aristotle didn\'t find fifth kind of vitreous humor, vitamin C, because the Greek alphabet
author HackBot
date Mon, 01 Jan 2018 17:57:43 +0000
parents 859f9b4339e6
children
line wrap: on
line source

#!/usr/bin/env python
from numarray import *
import sys

def dimensionSubstr(line):
    a = enumerate(line)
    try:
        b = a.next()
    except:
        return ["", line]
    try:
        while 1:
            if b[1] not in "0123456789": return [line[0:b[0]], line[b[0]:]]
            b = a.next()
            while b[1] != ".":
                if b[1] not in "0123456789": return [line[0:b[0]], line[b[0]:]]
                b = a.next()
            b = a.next()
            if b[1] == ".":
                return None #syntax error
    except:
        return [line[0:b[0]], ""]

class Dimensifuck:
    def __init__(self):
        self.dimensions = 0
        self.dimensionSizes = []
        self.matrix = array(type=Int8)
        self.tape = [0]
        self.pointer = 0
    def run(self, verbose=False):
        location = [0] * self.dimensions
        dimension = 0
        nextDimension = 0
        direction = 1
        while 1:
            op = self._getMatrixAt(location)
            if verbose:
                print "Location: ", location
                print "Opcode:", "+-.,<>=_^vX "[op]
            if op == 0:
                self.tape[self.pointer] = (self.tape[self.pointer] + 1) & 255
            elif op == 1:
                self.tape[self.pointer] = (self.tape[self.pointer] - 1) & 255
            elif op == 2:
                print chr(self.tape[self.pointer]),
            elif op == 3:
                self.tape[self.pointer] = ord(sys.stdin.read(1))
            elif op == 4:
                self.pointer -= 1
                if self.pointer < 0:
                    self.tape = [0] + self.tape
                    self.pointer = 0
            elif op == 5:
                self.pointer += 1
                if self.pointer == len(self.tape):
                    self.tape.append(0)
            elif op == 6:
                nextDimension += 1
            elif op == 7:
                nextDimension -= 1
            elif op == 8:
                if self.tape[self.pointer]:
                    dimension = nextDimension
                    direction = 1
            elif op == 9:
                if self.tape[self.pointer]:
                    dimension = nextDimension
                    direction = -1
            elif op == 10:
                return self.tape[self.pointer]
            location[dimension] += direction
    def loadMatrix(self, code):
        self.dimensions = 0
        code = [dimensionSubstr(i) for i in code.split('\n')]
        lines = []
        for i, j in enumerate(code):
            if j is None:
                print "Syntax error on line ", i
                return False
            if j[0]:
                lines.append(j)
                self.dimensions = max(self.dimensions, j[0].count(".") + 2)
            else:
                lines[-1][1] += j[1]
        self.dimensionSizes = [0] * self.dimensions
        for i in xrange(len(lines)):
            lines[i][0] = [len(lines[i][1])] + [int(j) for j in lines[i][0].split(".")]
            lines[i][0] += [0] * (len(lines[i][0]) - self.dimensions)
        for i in xrange(self.dimensions):
            self.dimensionSizes[i] = max([a[0][i] + 1 for a in lines])
        for i in xrange(self.dimensions):
            self.matrix = array([-1], type=Int8)
            self.matrix.resize(self.dimensionSizes)
        for i in lines:
            location = list(i[0])
            location[0] = 0
            for j in i[1]:
                self._setMatrixAt(location, self._getValue(j))
                location[0] += 1
        
    def loadFile(self, filename):
        self.loadMatrix(file(filename, "r").read())

    def _getMatrixAt(self, location):
        for i in location:
            if i < 0:
                return 10
        try:
            return reduce(lambda x, y: x[y], location, self.matrix)
        except:
            return 10
    def _setMatrixAt(self, location, value):
        array = self.matrix
        while len(location) > 1:
            array = array[location[0]]
            location = location[1:]
        array[location[0]] = value
    def _getValue(self, char):
        return "+-.,<>=_^vX".find(char)