[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