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")