Aggiornamento maggiore

* Aggiunte docstrings
* Correzioni PEP 8
* Aggiunta lista trinaria
* Migliorata struttura e leggibilità del codice
This commit is contained in:
Rnhmjoj 2013-08-04 02:27:11 +02:00
parent c612dec925
commit ffb836b975
2 changed files with 191 additions and 83 deletions

View File

@ -3,95 +3,147 @@ from .trinario import *
class Macchina:
def esegui(self, programma):
"""Esegue il programma Malbolge fornito come stringa."""
#Accumulatore
self.a = trin(0)
#Registri
self.d = [trin(0) for i in range(3**10)]
self.c = [trin(0) for i in range(3**10)]
self.d = trinlist([0 for i in range(3**5)], True)
self.c = trinlist([0 for i in range(3**5)], True)
#Puntatori
self.puntatore_c = trin(0)
self.puntatore_d = trin(0)
istruzioni = {
"j": self.__scambia_d,
"i": self.__scambia_c,
"*": self.__ruota,
"p": self.__pazza,
"<": self.__leggi,
"/": self.__stampa,
"v": self.__esci,
"o": self.__nulla,
}
#Controllo lunghezza massima
if len(programma) > 3**10:
raise MemoryError("Memoria esaurita. Limite di 3**10 word superato.")
raise MemoryError("Memoria esaurita. Limite di 3^10 word superato.")
#Copia il programma nel registro c
for indice, word in enumerate(programma):
if trinord(word) not in range(33,127):
raise SyntaxError("Carattere non consentito nel programma: %c a %d." % (word, indice))
raise SyntaxError("Carattere non consentito nel programma: '%c' a %d." % (word, indice))
if word not in ("\n"," "):
self.c[indice] = trinord(word)
#Esecuzione del programma
while self.puntatore_c < len(programma):
istruzione = self.__calcola_istruzione(trinchr(self.c[self.puntatore_c.decimale]))
if istruzione == "i":
self.puntatore_c = self.d[self.puntatore_d.decimale]
elif istruzione == "/":
self.__stampa()
elif istruzione == "<":
#Calcola ed esegue l'istruzione
istruzione = self.__calcola_istruzione(trinchr(self.c[self.puntatore_c]))
istruzioni[istruzione]()
#Operazioni per ogni istruzione
self.c[self.puntatore_c] -= 33
self.__traduci()
self.puntatore_c += 1
self.puntatore_d += 1
def __calcola_istruzione(self, carattere):
"""
Calcola l'istruzione da eseguire
in base al carattere presente nel puntatore.
"""
tabella = "+b(29e*j1VMEKLyC})8&m#~W>qxdRp0wkr \
Uo[D7,XTcA\"lI.v%{gJh4G\-=O@5`_3i< \
?Z';FNQuY]szf$!BS/|t:Pn6^Ha"
istruzione = (trinord(carattere) - 33 + self.puntatore_c) % 94
return tabella[istruzione]
def __traduci(self):
"""
Trascive l'istruzione nel registro del
codice seguendo la tavola di conversione.
"""
trascrizione = str.maketrans(
'!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMN \
OPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~',
'5z]&gqtyfr$(we4{WP)H-Zn,[%\\3dL+Q;>U!pJS7 2FhOA \
1CB6v^=I_0/8|jsb9m<.TVac`uY*MK\'X~xDl}REokN:#?G"i@'
)
istruzione = str.translate(trinchr(self.c[self.puntatore_c]), trascrizione)
self.c[self.puntatore_c] = trinord(istruzione)
#Istruzioni
def __scambia_d(self):
"""
Istruzione Malbolge "j"
Assegna al data pointer il valore a cui punta.
"""
self.puntatore_d = self.d[self.puntatore_d]
def __scambia_c(self):
"""
Istruzione Malbolge "i"
Assegna al code pointer il valore puntato dal data pointer.
"""
self.puntatore_c = self.d[self.puntatore_d]
def __ruota(self):
"""
Istruzione Malbolge "*"
Ruota la word puntata dal data pointer di un trit verso destra.
"""
self.d[self.puntatore_d] = trin(self.a[-1] + self.a[0:-1])
def __pazza(self):
"""
Istruzione Malbolge "p"
Esegue l'operazione pazza con il valore nell'accumulatore e il valore
puntato dal data pointer. Poi salva il risultato nell'accumulatore
e nel registro dei dati.
"""
operazione = [[1,0,0],[1,0,2],[2,2,1]]
risultato = []
for i,j in zip(self.a, self.d[self.puntatore_d]):
risultato += operazione[i][j],
self.d[self.puntatore_d] = trin(risultato)
self.a = trin(risultato)
def __leggi(self):
"""
Istruzione Malbolge "<"
Legge un carattere dallo stdin e lo registra nell'accumulatore.
"""
carattere = input()
if len(carattere) > 1:
raise TypeError("Si attendeva un carattere: letta una stringa.")
elif len(carattere) == 0:
raise TypeError("Si attendeva un carattere: letta una stringa nulla.")
self.a = trinord(carattere)
elif istruzione == "*":
self.__ruota()
self.a = self.d[self.puntatore_d.decimale]
elif istruzione == "j":
self.puntatore_d = self.d[self.puntatore_d.decimale]
elif istruzione == "p":
self.__pazza()
self.a = self.d[self.puntatore_d.decimale]
elif istruzione == "o":
self.__niente()
elif istruzione == "v":
self.__esci()
else:
self.__niente()
self.c[self.puntatore_c.decimale] -= 33
self.__traduci()
self.puntatore_c += 1
self.puntatore_d += 1
self.a = trinord(carattere)
#Determina l'istruzione da eseguire
def __calcola_istruzione(self, carattere):
tabella = "+b(29e*j1VMEKLyC})8&m#~W>qxdRp0wkrUo[D7,XTcA\"lI.v%{gJh4G\-=O@5`_3i<?Z';FNQuY]szf$!BS/|t:Pn6^Ha"
istruzione = (trinord(carattere) - 33 + self.puntatore_c) % 94
return tabella[istruzione.decimale]
#Istruzioni
def __stampa(self):
"""
Istruzione Malbolge "/"
Stampa il carattere presente nell'accumulatore.
"""
print(trinchr(self.a), end="")
def __ruota(self):
#Ruota la word di un trit verso destra
self.d[self.puntatore_d.decimale] = trin(self.a[-1] + self.a[0:-1])
def __pazza(self):
#Operazione pazza
operazione = [[1,0,0],[1,0,2],[2,2,1]]
risultato = []
for i,j in zip(self.a, self.d[self.puntatore_d.decimale]):
risultato += operazione[i][j],
self.d[self.puntatore_d.decimale] = trin(risultato)
def __niente(self):
#Operazione nulla
pass
def __esci(self):
#Termina l'esecuzione
"""
Istruzione Malbolge "v"
Termina l'esecuzione del programma.
"""
exit()
def __traduci(self):
#Traduce
trascrizione = str.maketrans(
'!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~',
'5z]&gqtyfr$(we4{WP)H-Zn,[%\\3dL+Q;>U!pJS72FhOA1CB6v^=I_0/8|jsb9m<.TVac`uY*MK\'X~xDl}REokN:#?G"i@'
)
self.c[self.puntatore_c.decimale] = trinord(str.translate(trinchr(self.c[self.puntatore_c.decimale]), trascrizione))
def __nulla(self):
"""
Istruzione Malbolge "o"
Esegue l'operazione nulla.
"""
pass

View File

@ -1,6 +1,7 @@
class Trinario:
"""Word trinaria"""
def __init__(self, valore, converti=False):
def __init__(self, valore, converti):
#Converte da base n a base 3 se necessario
if converti:
valore = self.__converti(valore)
@ -8,17 +9,22 @@ class Trinario:
#Controllo lunghezza massima
if self.lunghezza > 10:
raise OverflowError("Limite di trit per word superato: massimo 10 (passati %d)" % self.lunghezza)
raise OverflowError(
"Limite di trit per word superato: massimo 10 (passati %d)" % self.lunghezza
)
#Conversione di base
def __converti(self, decimale):
"""Restituisce il valore decimale passato in trinario."""
trinario = []
if decimale == 0:
return [0]
while decimale > 0:
trinario += decimale % 3,
decimale //= 3
return trinario[::-1]
#Vari override degli operatori
def __iter__(self):
lista = [int(i) for i in self.valore]
return iter(lista)
@ -29,8 +35,11 @@ class Trinario:
def __repr__(self):
return self.valore
#Assegna entrambi i valori(decimale e trinario) quando almeno uno cambia
def __setattr__(self, nome, valore):
"""
Assegna entrambi i valori (decimale e trinario) quando almeno uno
cambia.
"""
if nome == "valore":
if type(valore) is list:
valore = "".join([str(i) for i in valore])
@ -51,8 +60,10 @@ class Trinario:
self.__dict__["decimale"] = int(self.valore, base=3)
self.__dict__["lunghezza"] = len(self.valore)
def __getitem__(self, chiave):
return self.valore[chiave]
def __getitem__(self, indice):
return self.valore[indice]
#Override degli operatori matematici
def __add__(self, altro):
try:
@ -147,14 +158,59 @@ class Trinario:
except AttributeError:
return self.decimale >= altro
#Ritorna una word trinaria
class Trilista:
"""Lista per word trinarie"""
def __init__(self, lista, converti):
"""Inizializzazione della lista trinaria."""
for i in lista:
self.valori = [trin(i, converti) for i in lista]
#Vari override degli operatori
def __setitem__(self, indice, valore):
try:
self.valori[indice.decimale]
except AttributeError:
self.valori[indice]
def __getitem__(self, indice):
try:
return self.valori[indice.decimale]
except AttributeError:
return self.valori[indice]
def __str__(self):
return self.valori.__str__()
def __repr__(self):
return self.valori
#Wrappers
def trin(valore, converti=False):
"""
Restituisce una word trinaria. Fornire converti=True come parametro se
il valore è decimale.
"""
return Trinario(valore, converti)
#Ritorna l'ordinale di un carattere in una word trinaria
def trinord(carattere):
"""
Restituisce l'ordinale di un carattere in una word trinaria.
"""
return trin(ord(carattere), True)
#Ritorna il carattere ASCII data una word trinaria
def trinchr(trinario):
"""
Restituisce il carattere ASCII data una wordtrinaria.
"""
return chr(trinario.decimale % 256)
def trinlist(lista, converti=False):
"""
Restituisce una lista accessibile da indici trinari data una lista.
Fornire converti=False come parametro solo se gli elementi della lista
sono trinari.Non usare liste con basi numeriche miste.
"""
return Trilista(lista, converti)