[Corso Python3] programma numeri romani
alessandro medici
alexxandro.medici a gmail.com
Mar 31 Maggio 2016 16:57:15 CEST
''' traduce numeri romani ,in decimali e viceversa '''
#from copy import copy
import unittest
num_romani = 'MDCLXVI'
# ammessi è un dizio con:
# chiave = lettera, valore una tupla con:
# ( valore decimale,
# num_romani ammessi nel precedente,
# num_romani ammessi successivi
# ordine importanza scala valori
ammessi = { 'alfa' :1001,
'M' :1000,
'D' : 500,
'C' : 100,
'L' : 50,
'X' : 10,
'V' : 5,
'I' : 1}
def controllaLegalita(numax):
''' torna None se condizioni di errore
il valore decimale se corretto
'''
if numax == "": return # caso della stringa vuota
global stoppa
global num
num = numax.upper()
# contiene la stringa in caratteri romani
# il metodo di stringa .upper() ritorna laicita
# la medesima stringa in numeri maiuscoli
# scoP = 'alfa'
# indica il valore massimo nello sconto
# ricorda che quando un valore è usato come sconto
# non può più essere usato come valore in aggiunta:
# es: se MCM -> non ammesso MCMC
# altrimenti sarebbe ammesso anche MCCM
# quindi un valore usato come aggiunta non può più
# essere usato come sconto.
# adjP = 'alfa'
# indica il valore massimo in aggiunta
# sia con bloP che con adjP impostati così non si
# sbaglia altrimenti nel primo passaggio
# si esclude tutto e bisognerebbe riscrivere
# il codice per gestire tutte le eccezioni relative
# adjPP = 'alfa' è il backup per gli sconti
# diFila = 0
# mantiene un contatore (counter abbeviato ctr in
# gergo) al numero di caratteri inseriti di
# fila -> max 3
# valorD = 0
# mantiene il conto del valore decimale complessivo
# da tornare per la stampa ed il test_parto_da_qui
# qui si sistema scoP:
if len(num) > 1 and ammessi[num[0]] < ammessi[num[1]]:
scoP = num[1]
if stoppa == num:
zz = stoppa
else:
scoP = 'alfa'
scoP = 'alfa'
adjPP = adjP = 'alfa'
diFila = valorD = 0
for pos, car in enumerate(num):
''' fa la scansione di tutta la stringe in num per sottoporla
ad esame di correttezza
'''
# for pos, car in enumerate(num):
# abbiamo avuto sia posizione che carattere,
# -> enumerate un iterabile torna
# la posizione e l'elemento
# in quella posizione
if car not in num_romani:
# non esiste in romano:
if stoppa == num:
zz = stoppa
return
if ammessi[adjP] >= ammessi[car]:
# adjP => car. Ok. Caso semplice:
# sono ammessi IN AGGIUNTA solo valori minori/eguali dell'ultimo
# qui si gestisce il caso del minore
# valore inserito IN AGGIUNTA: ok MMCC e MMCM no MMCCM
# Per ovviare al primo inserimento nel primo giro è
# adjP = 'alfa', valore fittizio massimo
'''
a0 = ammessi[car]
a1 = ammessi[scoP]
a2 = ammessi[adjPP]
a3 = ammessi[adjP]
a4 = ammessi[car]
if stoppa == num:
zz = stoppa
a0 = scoP
a1 = ammessi[scoP]
a2 = ammessi[scoP]
a3 = ammessi[scoP]
a4 = ammessi[car]
'''
if ammessi[scoP] <= ammessi[car]:
# ma sono ammessi IN AGGIUNTA solo valori minori dell'ultimo
# valore inserito COME SCONTO: ok MCML e CXCV no CXCX
# Per ovviare al primo inserimento nel primo giro è
# adjP = 'alfa', valore fittizio massimo
if stoppa == num:
zz = stoppa
return
# ok, tutto bene, aggiorno i valori di adjP a quello inserito:
# if ammessi[adjP] == ammessi[car]:
if adjP == car:
# caso inserimento eguale all'ultimo
# controllo la fila:
if car in 'DLV':
# fanculo perché non si possono duplicare DLV:
if stoppa == num:
zz = stoppa
return
if diFila == 2:
# non vi possono essere più di tre num_romani eguali di fila
# ricorda che il conteggio parte da 0
if stoppa == num:
zz = stoppa
return
# ed incremento il contatore
diFila +=1
else:
# spezzo la fila per ricominciare da zero:
diFila = 0
adjPP = adjP # se dopo avrò uno sconto dovrò riaggiornare adjP!
adjP = car
if stoppa == num:
zz = stoppa
valorD += ammessi[car]
continue
# resta adjP < car e l'if sotto non è necessario:
# if ammessi[adjP][1] > ammessi[car][1]:
# ovvio che siamo di fronte ad una richiesta di sconto.
# che fa riferimento al valore precedente
'''
ATTENZIONE QUI SOTTO ALLA DIFFERENZA TRA adjP e adjPP
sostanzialmente:
adjP -> aggiunto precedente
adjPP -> aggiunto prima del precedente
'''
if stoppa == num:
zz = stoppa
if ammessi[adjPP] < ammessi[car]:
# sono ammessi SCONTABILI solo valori minori o eguali
# dell'ultimo valore inserito IN AGGIUNTA, in questo caso:
# ammessi[adjPP][1]
# quindi: ok MCM e CXC no CXCM
# Per ovviare al primo inserimento nel primo giro è
# adjPP = 'alfa', valore fittizio massimo
if stoppa == num:
zz = stoppa
return
if not(ammessi[car]//10 <= ammessi[adjP] < ammessi[car]//2):
# sono ammessi sconti solo eguali o superiori
# ad un decimo del valore da scontare
# e minori della metà dello stesso
if stoppa == num:
zz = stoppa
return
# sono ammessi IN SCONTO solo valori minori dell'ultimo
# valore inserito IN AGGIUNTA, in questo caso: ammessi[adjPP][1]
# quindi: ok MCM e CXC no CXCM
# Per ovviare al primo inserimento nel primo giro è
# adjPP = 'alfa', valore fittizio massimo
if ammessi[adjPP] < ammessi[adjP]:
# sono ammessi SCONTI solo valori minori
# dell'ultimo valore inserito IN AGGIUNTA, in questo caso:
# ammessi[adjPP]
# quindi: ok MCM e CXC no CXCM
# Per ovviare al primo inserimento nel primo giro è
# adjPP = 'alfa', valore fittizio massimo
if stoppa == num:
zz = stoppa
return
# aggiorno i valori:
valorD += ammessi[car] -2 * ammessi[adjP]
# adjP due volte perché una era stata caricata prima di sapere che
# era da scontare.
scoP = adjP
adjP = car
# ignoriamo adjPP: qui non interessati al valore dello sconto
diFila = 2 # non si può inserire un MCM
continue
return valorD
def parto_da_qui(nome):
global stoppa
a = ''
#while True:
#a = input("un numero romano or 'fine' ?")
#if a == 'fine':
# break
a = controllaLegalita(nome)
print(a)
return a
def parto_da_qui(nome):
global stoppa
a = ''
#while True:
#a = input("un numero romano or 'fine' ?")
#if a == 'fine':
# break
a = controllaLegalita(nome)
print(a)
return a
def int_to_roman(input):
""" Convert an integer to a Roman numeral. """
# questa funzione l'ho trovata in rete qui l'ho solo adattata:
#
https://www.safaribooksonline.com/library/view/python-cookbook/0596001673/ch03s24.html
ints = (1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1)
nums = ('M', 'CM', 'D', 'CD','C', 'XC','L','XL','X','IX','V','IV','I')
result = []
for i in range(len(ints)):
count = int(input / ints[i])
result.append(nums[i] * count)
input -= ints[i] * count
return ''.join(result)
class perTest(unittest.TestCase):
global stoppa
stoppa = 'i'
stoppa = stoppa.upper()
def test_parto_da_qui(self):
for j in range(1, 4000):
rom = (int_to_roman(j))
print(j, rom)
self.assertEqual(j, parto_da_qui(rom))
if __name__ == '__main__':
unittest.main()
-------------- parte successiva --------------
Un allegato HTML è stato rimosso...
URL: <http://lists.fsugpadova.org/pipermail/fsug-corso-python3/attachments/20160531/0799cfd9/attachment.html>
Maggiori informazioni sulla lista
fsug-corso-python3