Seite 1 von 1

Verbesserungsvorschläge

Verfasst: Mittwoch 5. Juni 2013, 20:41
von darktrym
Hallo,
ich schreibe gerade an einem Malbolge Interpreter. Dort gibts eine Funktion crz die als Argument 2 Zahlen bekommt die über ein zweidimensionales Codebuch ziffernweise verarbeitet werden. Malbolge rechnet intern mit Zahlen der Basis 3, MAX_DIGITS ist dabei 10.

Mein bisheriger Ansatz sieht nicht besonders toll aus, deshalb bitte ich um Verbesserungsvorschläge.

Code: Alles auswählen

def crz(self, first_number, second_number):
        crypt_table = (("1", "0", "0"),
                            ("1", "0", "2"),
                            ("2", "2", "1"))
        crypted_value = []
        values1 = map(int, list(self.int_to_base3_str(first_number)))
        values2 = map(int, list(self.int_to_base3_str(second_number)))
        for index in xrange(Malbolge.MAX_DIGITS):
            crypted_value.append(crypt_table[values1[index]][values2[index]])
        return int("".join(crypted_value), Malbolge.BASE)
       

Re: Verbesserungsvorschläge

Verfasst: Mittwoch 5. Juni 2013, 22:00
von Sirius3
Hallo darktrym,
- die »list« sind überflüssig
- über »values1« und »values2« solltest Du mittels »zip« iterieren
- »int_to_base3_str« gibt hoffentlich immer Strings der Länge MAX_DIGITS zurück??
- warum ist »crz« eine Klassenmethode, da »self« genauso wie in »int_to_base3_str« gar nicht benutzt wird.

Code: Alles auswählen

CRYPT_TABLE = ((1,0,0), (1,0,2), (2,2,1))
def crz(first, second):
    B = Malbolge.BASE
    return reduce(lambda a,b: a*B+b, (
        CRYPT_TABLE[first/(B**n)%B][second/(B**n)%B]
            for n in range(Malbolge.MAX_DIGITS-1,-1,-1)))

Re: Verbesserungsvorschläge

Verfasst: Donnerstag 6. Juni 2013, 17:55
von darktrym
Vielen Dank.
Den Reduce Kram hab' ich noch nicht verstanden, dass braucht noch etwas Zeit.
Und da irgendwo noch ein anderer Fehler ist, der mein Interpreter nach den ersten Buchstaben vom Hello World crashen lässt bleibe ich vorerst bei meiner verbesserten Variante, die deutlich lesbarer ist.

Code: Alles auswählen

def crz(first, second):
        CRYPT_TABLE = ((1, 0, 0),
                            (1, 0, 2),
                            (2, 2, 1))
        crypted_value = [] 
        digits = []
        for number in (first, second):
            digits.append(map(int, list(Malbolge.int_to_base3_str(number))))
        number = 0
        for index, pair in enumerate(zip(digits[0], digits[1])):
            number += Malbolge.BASE**(Malbolge.MAX_DIGITS - 1 - index) * CRYPT_TABLE[pair[0]][pair[1]]
        return number

Re: Verbesserungsvorschläge

Verfasst: Freitag 7. Juni 2013, 20:13
von darktrym
Hier ist nun der komplette Code, wenigstens das Hello World Beispiel scheint zu funktionieren.
Irgendwie gibt da einen math. Kniff, wie das Rotieren direkt mathematisch beschrieben werden kann.

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys

__author__ = "Daniel Ölschlegel"
__license__ = "bsdl"
__version__ = "0.01" 


BASE = 3
MAX_DIGITS = 10
MAX_NUMBER = BASE**MAX_DIGITS
OPCODES = {"jmp":4, "out":5, "in":23, "mov":40, "rotr":39, "crz":62, "nop":68, "end":81}


def int_to_base3_str(number):
    '''convert a positive integer number to a string which represents a number with the base of 3
      the number is limited to MAX_NUMBER and a string is returned with a length of 10      
    '''
    if number >= MAX_NUMBER:
        raise ValueError
    digits = ''
    div, mod = divmod(number, BASE)
    while div:
        digits = str(mod) + digits
        div, mod = divmod(div, BASE)
    return  "%s%d%s" % ((MAX_DIGITS - len(digits) - 1) * '0', mod, digits)
  
def encrypt(number):
    '''uses a ecb mode for encryption'''
    CRYPT_TABLE = '9m<.TVac`uY*MK\'X~xDl}REokN:#?G"i@5z]&gqtyfr$(we4{WP)H-Zn,[%\\3dL+Q;>U!pJS72FhOA1CB6v^=I_0/8|jsb'
    #print CRYPT_TABLE, len(CRYPT_TABLE)
    return ord(CRYPT_TABLE[number  % 94])
 
def crz(first, second):
    CRYPT_TABLE =   ((1, 0, 0),
                            (1, 0, 2),
                            (2, 2, 1))
    crypted_value = [] 
    digits = []
    for number in (first, second):
        digits.append(map(int, list(int_to_base3_str(number))))
    number = 0
    for index, pair in enumerate(zip(digits[0], digits[1])):
        number += BASE**(MAX_DIGITS - 1 - index) * CRYPT_TABLE[pair[0]][pair[1]]
    return number

def rotr(number):
    '''rotate value of the given memory address
    the last digits is the first, the rest is shifted to right'''
    number = int_to_base3_str(number)
    return int(number[-1] + number[:-1], BASE)
   
def run(source):
    #reset all registers
    a = c = d = 0
    memory = [] 
    #strip whitespaces and other invalid characer
    for filter in (" ", "\n"):
        source = source.replace(filter, "")
   
    #copy the code into memory as numbers
    memory = map(ord, source)
    #encrypt the free space, by the way code should at least 2 bytes long
    for index in xrange(len(source), MAX_NUMBER):
        memory.append(crz(memory[index - 2], memory[index - 1]))
    while True:
        opcode = (memory[c] + c) % 94
        if opcode in OPCODES.values():
            if opcode == OPCODES["jmp"]:
                c = memory[d]
            elif opcode == OPCODES["out"]:
                sys.stdout.write(chr(a % 256))
            elif opcode == OPCODES["in"]:
                try:
                    chars = raw_input("")
                    a = ord("\n") if not chars else ord(chars[0])
                except EOFError:
                    a = MAX_NUMBER - 1
            elif opcode == OPCODES["rotr"]:
                a = memory[d] = rotr(memory[d])
            elif opcode == OPCODES["mov"]:
                d = memory[d] 
            elif opcode == OPCODES["crz"]:
                a = memory[d] = crz(memory[d], a) 
            elif opcode == OPCODES["end"]:
                break
            elif opcode == OPCODES["nop"]:
                pass
        
        #encrypt current instruction
        memory[c] = encrypt(memory[c])
        c = (c + 1) % MAX_NUMBER
        d = (d + 1) % MAX_NUMBER

if __name__ == '__main__':
    run("(\'&%:9]!~}|z2Vxwv-,POqponl$Hjig%eB@@>a=<M:9[p6tsl1TS/QlOj)L(I&%$\"\"Z~AA@UZ=RvttT`R5P3m0LEDh,T*?(b&`$#87[}{W")