view interps/dimensifuck/dimensifuck.py @ 12500:e48c08805365 draft default tip

<b_jonas> ` learn \'The password of the month is Cthulhuquagdonic Mothraquagdonic Narwhalicorn.\' # https://logs.esolangs.org/libera-esolangs/2024-04.html#lKE Infinite craft
author HackEso <hackeso@esolangs.org>
date Wed, 01 May 2024 06:39:10 +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)