From ffb836b97564801c56ca3861e201fc88240e7582 Mon Sep 17 00:00:00 2001 From: Rnhmjoj Date: Sun, 4 Aug 2013 02:27:11 +0200 Subject: [PATCH] Aggiornamento maggiore MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Aggiunte docstrings * Correzioni PEP 8 * Aggiunta lista trinaria * Migliorata struttura e leggibilità del codice --- malbolge/macchina.py | 166 ++++++++++++++++++++++++++++--------------- malbolge/trinario.py | 108 +++++++++++++++++++++------- 2 files changed, 191 insertions(+), 83 deletions(-) diff --git a/malbolge/macchina.py b/malbolge/macchina.py index f36c78c..392545d 100644 --- a/malbolge/macchina.py +++ b/malbolge/macchina.py @@ -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 == "<": - 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 + #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 - #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`_3iqxdRp0wkr \ + 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.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 - 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): - #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): - #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]] 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], - self.d[self.puntatore_d.decimale] = trin(risultato) - - def __niente(self): - #Operazione nulla - pass + 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.") + else: + self.a = trinord(carattere) + + + def __stampa(self): + """ + Istruzione Malbolge "/" + Stampa il carattere presente nell'accumulatore. + """ + print(trinchr(self.a), end="") 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 diff --git a/malbolge/trinario.py b/malbolge/trinario.py index d1dbe56..1e1a53a 100644 --- a/malbolge/trinario.py +++ b/malbolge/trinario.py @@ -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,39 +60,41 @@ 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: return Trinario(self.decimale + altro.decimale, True) except AttributeError: return Trinario(self.decimale + altro, True) - + def __iadd__(self, altro): try: return self + altro except AttributeError: return self.decimale + altro - + def __sub__(self, altro): try: return Trinario(self.decimale - altro.decimale, True) except AttributeError: return Trinario(self.decimale - altro, True) - + def __isub__(self, altro): return self - altro - + def __mul__(self, altro): try: return Trinario(self.decimale * altro.decimale, True) except AttributeError: return Trinario(self.decimale * altro, True) - + def __imul__(self, altro): return self * altro - + def __mod__(self, altro): try: return Trinario(self.decimale % altro.decimale, True) @@ -92,69 +103,114 @@ class Trinario: def __imod__(self, altro): return self % altro - + def __truediv__(self, floor): try: return Trinario(self.decimale / altro.decimale, True) except AttributeError: return Trinario(self.decimale / altro, True) - + def __itruediv__(self, altro): return self / altro - + def __floordiv__(self, altro): try: return Trinario(self.decimale // altro.decimale, True) except AttributeError: return Trinario(self.decimale // altro, True) - + def __ifloordiv__(self, altro): return self // altro - + def __lt__(self, altro): try: return self.decimale < altro.decimale except AttributeError: return self.decimale < altro - + def __le__(self, altro): try: return self.decimale <= altro.decimale except AttributeError: return self.decimale <= altro - + def __eq__(self, altro): try: return self.decimale == altro.decimale except AttributeError: return self.decimale == altro - + def __ne__(self, altro): try: return self.decimale != self.altro except AttributeError: return self.decimale != altro - + def __gt__(self, altro): try: - return self.decimale > altro.decimale + return self.decimale > altro.decimale except AttributeError: return self.decimale > altro - + def __ge__(self, altro): try: return self.decimale >= altro.decimale except AttributeError: 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): + """ + 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)