Aggiornamento maggiore
* Aggiunte docstrings * Correzioni PEP 8 * Aggiunta lista trinaria * Migliorata struttura e leggibilità del codice
This commit is contained in:
parent
c612dec925
commit
ffb836b975
@ -3,95 +3,147 @@ from .trinario import *
|
|||||||
class Macchina:
|
class Macchina:
|
||||||
|
|
||||||
def esegui(self, programma):
|
def esegui(self, programma):
|
||||||
|
"""Esegue il programma Malbolge fornito come stringa."""
|
||||||
|
|
||||||
#Accumulatore
|
#Accumulatore
|
||||||
self.a = trin(0)
|
self.a = trin(0)
|
||||||
|
|
||||||
#Registri
|
#Registri
|
||||||
self.d = [trin(0) for i in range(3**10)]
|
self.d = trinlist([0 for i in range(3**5)], True)
|
||||||
self.c = [trin(0) for i in range(3**10)]
|
self.c = trinlist([0 for i in range(3**5)], True)
|
||||||
|
|
||||||
#Puntatori
|
#Puntatori
|
||||||
self.puntatore_c = trin(0)
|
self.puntatore_c = trin(0)
|
||||||
self.puntatore_d = 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
|
#Controllo lunghezza massima
|
||||||
if len(programma) > 3**10:
|
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
|
#Copia il programma nel registro c
|
||||||
for indice, word in enumerate(programma):
|
for indice, word in enumerate(programma):
|
||||||
if trinord(word) not in range(33,127):
|
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"," "):
|
if word not in ("\n"," "):
|
||||||
self.c[indice] = trinord(word)
|
self.c[indice] = trinord(word)
|
||||||
|
|
||||||
#Esecuzione del programma
|
#Esecuzione del programma
|
||||||
while self.puntatore_c < len(programma):
|
while self.puntatore_c < len(programma):
|
||||||
istruzione = self.__calcola_istruzione(trinchr(self.c[self.puntatore_c.decimale]))
|
#Calcola ed esegue l'istruzione
|
||||||
if istruzione == "i":
|
istruzione = self.__calcola_istruzione(trinchr(self.c[self.puntatore_c]))
|
||||||
self.puntatore_c = self.d[self.puntatore_d.decimale]
|
istruzioni[istruzione]()
|
||||||
elif istruzione == "/":
|
|
||||||
self.__stampa()
|
#Operazioni per ogni istruzione
|
||||||
elif istruzione == "<":
|
self.c[self.puntatore_c] -= 33
|
||||||
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.__traduci()
|
||||||
self.puntatore_c += 1
|
self.puntatore_c += 1
|
||||||
self.puntatore_d += 1
|
self.puntatore_d += 1
|
||||||
|
|
||||||
#Determina l'istruzione da eseguire
|
|
||||||
def __calcola_istruzione(self, carattere):
|
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"
|
"""
|
||||||
|
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
|
istruzione = (trinord(carattere) - 33 + self.puntatore_c) % 94
|
||||||
return tabella[istruzione.decimale]
|
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
|
#Istruzioni
|
||||||
def __stampa(self):
|
|
||||||
print(trinchr(self.a), end="")
|
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):
|
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])
|
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):
|
def __pazza(self):
|
||||||
#Operazione pazza
|
"""
|
||||||
|
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]]
|
operazione = [[1,0,0],[1,0,2],[2,2,1]]
|
||||||
risultato = []
|
risultato = []
|
||||||
for i,j in zip(self.a, self.d[self.puntatore_d.decimale]):
|
for i,j in zip(self.a, self.d[self.puntatore_d]):
|
||||||
risultato += operazione[i][j],
|
risultato += operazione[i][j],
|
||||||
self.d[self.puntatore_d.decimale] = trin(risultato)
|
self.d[self.puntatore_d] = trin(risultato)
|
||||||
|
self.a = trin(risultato)
|
||||||
def __niente(self):
|
|
||||||
#Operazione nulla
|
def __leggi(self):
|
||||||
pass
|
"""
|
||||||
|
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.")
|
||||||
|
else:
|
||||||
|
self.a = trinord(carattere)
|
||||||
|
|
||||||
|
|
||||||
|
def __stampa(self):
|
||||||
|
"""
|
||||||
|
Istruzione Malbolge "/"
|
||||||
|
Stampa il carattere presente nell'accumulatore.
|
||||||
|
"""
|
||||||
|
print(trinchr(self.a), end="")
|
||||||
|
|
||||||
def __esci(self):
|
def __esci(self):
|
||||||
#Termina l'esecuzione
|
"""
|
||||||
|
Istruzione Malbolge "v"
|
||||||
|
Termina l'esecuzione del programma.
|
||||||
|
"""
|
||||||
exit()
|
exit()
|
||||||
|
|
||||||
def __traduci(self):
|
def __nulla(self):
|
||||||
#Traduce
|
"""
|
||||||
trascrizione = str.maketrans(
|
Istruzione Malbolge "o"
|
||||||
'!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~',
|
Esegue l'operazione nulla.
|
||||||
'5z]&gqtyfr$(we4{WP)H-Zn,[%\\3dL+Q;>U!pJS72FhOA1CB6v^=I_0/8|jsb9m<.TVac`uY*MK\'X~xDl}REokN:#?G"i@'
|
"""
|
||||||
)
|
pass
|
||||||
self.c[self.puntatore_c.decimale] = trinord(str.translate(trinchr(self.c[self.puntatore_c.decimale]), trascrizione))
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
class Trinario:
|
class Trinario:
|
||||||
|
"""Word trinaria"""
|
||||||
|
|
||||||
def __init__(self, valore, converti=False):
|
def __init__(self, valore, converti):
|
||||||
#Converte da base n a base 3 se necessario
|
#Converte da base n a base 3 se necessario
|
||||||
if converti:
|
if converti:
|
||||||
valore = self.__converti(valore)
|
valore = self.__converti(valore)
|
||||||
@ -8,17 +9,22 @@ class Trinario:
|
|||||||
|
|
||||||
#Controllo lunghezza massima
|
#Controllo lunghezza massima
|
||||||
if self.lunghezza > 10:
|
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):
|
def __converti(self, decimale):
|
||||||
|
"""Restituisce il valore decimale passato in trinario."""
|
||||||
trinario = []
|
trinario = []
|
||||||
|
if decimale == 0:
|
||||||
|
return [0]
|
||||||
while decimale > 0:
|
while decimale > 0:
|
||||||
trinario += decimale % 3,
|
trinario += decimale % 3,
|
||||||
decimale //= 3
|
decimale //= 3
|
||||||
return trinario[::-1]
|
return trinario[::-1]
|
||||||
|
|
||||||
#Vari override degli operatori
|
#Vari override degli operatori
|
||||||
|
|
||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
lista = [int(i) for i in self.valore]
|
lista = [int(i) for i in self.valore]
|
||||||
return iter(lista)
|
return iter(lista)
|
||||||
@ -29,8 +35,11 @@ class Trinario:
|
|||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return self.valore
|
return self.valore
|
||||||
|
|
||||||
#Assegna entrambi i valori(decimale e trinario) quando almeno uno cambia
|
|
||||||
def __setattr__(self, nome, valore):
|
def __setattr__(self, nome, valore):
|
||||||
|
"""
|
||||||
|
Assegna entrambi i valori (decimale e trinario) quando almeno uno
|
||||||
|
cambia.
|
||||||
|
"""
|
||||||
if nome == "valore":
|
if nome == "valore":
|
||||||
if type(valore) is list:
|
if type(valore) is list:
|
||||||
valore = "".join([str(i) for i in valore])
|
valore = "".join([str(i) for i in valore])
|
||||||
@ -51,39 +60,41 @@ class Trinario:
|
|||||||
self.__dict__["decimale"] = int(self.valore, base=3)
|
self.__dict__["decimale"] = int(self.valore, base=3)
|
||||||
self.__dict__["lunghezza"] = len(self.valore)
|
self.__dict__["lunghezza"] = len(self.valore)
|
||||||
|
|
||||||
def __getitem__(self, chiave):
|
def __getitem__(self, indice):
|
||||||
return self.valore[chiave]
|
return self.valore[indice]
|
||||||
|
|
||||||
|
#Override degli operatori matematici
|
||||||
|
|
||||||
def __add__(self, altro):
|
def __add__(self, altro):
|
||||||
try:
|
try:
|
||||||
return Trinario(self.decimale + altro.decimale, True)
|
return Trinario(self.decimale + altro.decimale, True)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
return Trinario(self.decimale + altro, True)
|
return Trinario(self.decimale + altro, True)
|
||||||
|
|
||||||
def __iadd__(self, altro):
|
def __iadd__(self, altro):
|
||||||
try:
|
try:
|
||||||
return self + altro
|
return self + altro
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
return self.decimale + altro
|
return self.decimale + altro
|
||||||
|
|
||||||
def __sub__(self, altro):
|
def __sub__(self, altro):
|
||||||
try:
|
try:
|
||||||
return Trinario(self.decimale - altro.decimale, True)
|
return Trinario(self.decimale - altro.decimale, True)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
return Trinario(self.decimale - altro, True)
|
return Trinario(self.decimale - altro, True)
|
||||||
|
|
||||||
def __isub__(self, altro):
|
def __isub__(self, altro):
|
||||||
return self - altro
|
return self - altro
|
||||||
|
|
||||||
def __mul__(self, altro):
|
def __mul__(self, altro):
|
||||||
try:
|
try:
|
||||||
return Trinario(self.decimale * altro.decimale, True)
|
return Trinario(self.decimale * altro.decimale, True)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
return Trinario(self.decimale * altro, True)
|
return Trinario(self.decimale * altro, True)
|
||||||
|
|
||||||
def __imul__(self, altro):
|
def __imul__(self, altro):
|
||||||
return self * altro
|
return self * altro
|
||||||
|
|
||||||
def __mod__(self, altro):
|
def __mod__(self, altro):
|
||||||
try:
|
try:
|
||||||
return Trinario(self.decimale % altro.decimale, True)
|
return Trinario(self.decimale % altro.decimale, True)
|
||||||
@ -92,69 +103,114 @@ class Trinario:
|
|||||||
|
|
||||||
def __imod__(self, altro):
|
def __imod__(self, altro):
|
||||||
return self % altro
|
return self % altro
|
||||||
|
|
||||||
def __truediv__(self, floor):
|
def __truediv__(self, floor):
|
||||||
try:
|
try:
|
||||||
return Trinario(self.decimale / altro.decimale, True)
|
return Trinario(self.decimale / altro.decimale, True)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
return Trinario(self.decimale / altro, True)
|
return Trinario(self.decimale / altro, True)
|
||||||
|
|
||||||
def __itruediv__(self, altro):
|
def __itruediv__(self, altro):
|
||||||
return self / altro
|
return self / altro
|
||||||
|
|
||||||
def __floordiv__(self, altro):
|
def __floordiv__(self, altro):
|
||||||
try:
|
try:
|
||||||
return Trinario(self.decimale // altro.decimale, True)
|
return Trinario(self.decimale // altro.decimale, True)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
return Trinario(self.decimale // altro, True)
|
return Trinario(self.decimale // altro, True)
|
||||||
|
|
||||||
def __ifloordiv__(self, altro):
|
def __ifloordiv__(self, altro):
|
||||||
return self // altro
|
return self // altro
|
||||||
|
|
||||||
def __lt__(self, altro):
|
def __lt__(self, altro):
|
||||||
try:
|
try:
|
||||||
return self.decimale < altro.decimale
|
return self.decimale < altro.decimale
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
return self.decimale < altro
|
return self.decimale < altro
|
||||||
|
|
||||||
def __le__(self, altro):
|
def __le__(self, altro):
|
||||||
try:
|
try:
|
||||||
return self.decimale <= altro.decimale
|
return self.decimale <= altro.decimale
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
return self.decimale <= altro
|
return self.decimale <= altro
|
||||||
|
|
||||||
def __eq__(self, altro):
|
def __eq__(self, altro):
|
||||||
try:
|
try:
|
||||||
return self.decimale == altro.decimale
|
return self.decimale == altro.decimale
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
return self.decimale == altro
|
return self.decimale == altro
|
||||||
|
|
||||||
def __ne__(self, altro):
|
def __ne__(self, altro):
|
||||||
try:
|
try:
|
||||||
return self.decimale != self.altro
|
return self.decimale != self.altro
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
return self.decimale != altro
|
return self.decimale != altro
|
||||||
|
|
||||||
def __gt__(self, altro):
|
def __gt__(self, altro):
|
||||||
try:
|
try:
|
||||||
return self.decimale > altro.decimale
|
return self.decimale > altro.decimale
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
return self.decimale > altro
|
return self.decimale > altro
|
||||||
|
|
||||||
def __ge__(self, altro):
|
def __ge__(self, altro):
|
||||||
try:
|
try:
|
||||||
return self.decimale >= altro.decimale
|
return self.decimale >= altro.decimale
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
return self.decimale >= altro
|
return self.decimale >= altro
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
#Ritorna una word trinaria
|
|
||||||
def trin(valore, converti=False):
|
def trin(valore, converti=False):
|
||||||
|
"""
|
||||||
|
Restituisce una word trinaria. Fornire converti=True come parametro se
|
||||||
|
il valore è decimale.
|
||||||
|
"""
|
||||||
return Trinario(valore, converti)
|
return Trinario(valore, converti)
|
||||||
|
|
||||||
#Ritorna l'ordinale di un carattere in una word trinaria
|
|
||||||
def trinord(carattere):
|
def trinord(carattere):
|
||||||
|
"""
|
||||||
|
Restituisce l'ordinale di un carattere in una word trinaria.
|
||||||
|
"""
|
||||||
return trin(ord(carattere), True)
|
return trin(ord(carattere), True)
|
||||||
|
|
||||||
#Ritorna il carattere ASCII data una word trinaria
|
|
||||||
def trinchr(trinario):
|
def trinchr(trinario):
|
||||||
|
"""
|
||||||
|
Restituisce il carattere ASCII data una wordtrinaria.
|
||||||
|
"""
|
||||||
return chr(trinario.decimale % 256)
|
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)
|
||||||
|
Loading…
Reference in New Issue
Block a user