Esercizi di lettura

Da aptiva.

Indice

Esercizio 1

Esercizio 10 del PAS 2013/14. Vi propongo il mio commento. Elena (discussioni)

def sdiv(n):
        return {x for x in range(2,n) if n % x == 0}

#alternativa:
#def sdiv(n):
#       d=set()
#       for x in range(2,n):
#               if n % x == 0: d.add(x)
#       return d

def pr(n):
        return not sdiv(n)

def pdiv(n):
        return {x for x in sdiv(n) if pr(x)}

#alternativa:
#def pdiv(n):
#       d=set()
#       for x in sdiv(n):
#               if pr(x): d.add(x)
#       return d

def gcd(a,b):
        csdiv=pdiv(a) & pdiv(b)
        r=1
        for x in csdiv:
                while a % (r*x) == 0 and b % (r*x) == 0:
                        r *= x
        return r

def lcm(a,b):
        return a * b // gcd(a,b)

if __name__=="__main__":
        a,b=input("Inserisci due numeri (es: 48 36): ").split()
        a,b=int(a),int(b)
        print("pdiv({})={}".format(a,pdiv(a)))
        print("pdiv({})={}".format(b,pdiv(b)))
        print("gcd({},{})={}".format(a,b,gcd(a,b)))
        print("lcm({},{})={}".format(a,b,lcm(a,b)))

Questo programma prende in input due numeri(a,b) e stampa:

- la lista dei divisori primi del primo numero(a)

- la lista dei divisori primi del secondo numero(b)

- il massimo comun divisore dei due numeri

- il minimo comune multiplo dei due numeri

Ad esempio:

        Inserisci due numeri (es: 48 36): 60 72
        pdiv(60)={2, 3, 5}
        pdiv(72)={2, 3}
        gcd(60,72)=12
        lcm(60,72)=360

Descriviamo inizialmente le funzioni richiamate all'interno del programma.

	def sdiv(n):
        return {x for x in range(2,n) if n % x == 0}

La funzione sdiv prende in input un parametro intero n e restituisce una lista contenente i divisori propri non banali di n (ossia i divisori di n diversi da 1 e da n stesso). Dato il numero intero n, viene eseguito un ciclo for per x da 2 a n-1 che controlla se il resto della divisione di n per ognuno di questi valori di x è uguale a zero, in caso affermativo tale x viene inserito nella lista.

	def pr(n):
        return not sdiv(n)

La funzione pr prende in input un parametro intero n e determina se n è un numero primo. Dato il numero intero n la funzione restituisce il valore booleano True se la lista data dalla funzione sdiv(n) è vuota, altrimenti restituisce False. Se la lista restituita dalla funzione sdiv(n) è vuota significa che il numero n non ha divisori propri non banali e quindi è primo.

	def pdiv(n):
        return {x for x in sdiv(n) if pr(x)}

La funzione pdiv prende in input un parametro intero n e restituisce una lista contenente i divisori primi di n. Dato il numero intero n, viene eseguito un ciclo for per x appartenente alla lista restituita dalla funzione sdiv(n) (lista dei divisori propri non banali di n) e per ogni x viene richiamata la funzione pr(x) che determina se tale valore è primo, in caso affermativo x viene inserito nella lista finale.

	def gcd(a,b):
        csdiv=pdiv(a) & pdiv(b)
        r=1
        for x in csdiv:
                while a % (r*x) == 0 and b % (r*x) == 0:
                        r *= x
        return r

La funzione gcd prende in input due parametri interi a e b e restituisce il loro massimo comun divisore (GCD=Greatest Common Divisor). Dati i numeri interi a e b, la lista csdiv contiene i divisori primi comuni tra a e b, tale lista si ottiene come intersezione (&) delle liste pdiv(a) e pdiv(b). Si inizializza la variabile r a 1 e si esegue un ciclo for per x appartenente alla lista csdiv. All'interno di esso viene eseguito un ciclo while mentre a e b sono entrambi divisibili per r*x, ponendo in tal caso r=r*x ad ogni step. Alla fine del ciclo for otteniamo il massimo comun divisore tra a e b salvato in r. In questo modo, il massimo comun divisore r è calcolato moltiplicando i divisori primi comuni di a e b, considerati una sola volta con esponente minimo.

	def lcm(a,b):
        return a * b // gcd(a,b)

La funzione lcm prende in input due parametri interi a e b e restituisce il minimo comune multiplo (LCM=Least Common Multiple). Dati i numeri interi a e b la funzione restituisce il loro minimo comune multiplo, calcolato come quoziente (// divisione tra interi) tra il prodotto a*b e il massimo comun divisore di a e b fornito dalla funzione gcd(a,b).

Analizziamo ora le istruzioni principali quando viene eseguito il modulo:

	if __name__=="__main__":
		a,b=input("Inserisci due numeri (es: 48 36): ").split()
		a,b=int(a),int(b)
		print("pdiv({})={}".format(a,pdiv(a)))
		print("pdiv({})={}".format(b,pdiv(b)))
		print("gcd({},{})={}".format(a,b,gcd(a,b)))
		print("lcm({},{})={}".format(a,b,lcm(a,b)))

In questa sezione viene inizialmente presa in input una stringa e, mediante il metodo split, essa viene suddivisa (in corrispondenza di almeno uno spazio) in due sottostringhe a e b. Non sono presenti controlli formali sull'input: si presuppone che l'utente inserisca due numeri interi positivi separati da almeno uno spazio. Successivamente le due sottostringhe vengono convertite in numeri interi (casting esplicito). Inoltre:

        print("pdiv({})={}".format(a,pdiv(a)))
        print("pdiv({})={}".format(b,pdiv(b)))

vengono stampate le liste dei divisori primi di a e di b, dopo averle formattate con il metodo format. I parametri passati al metodo format vengono sostituiti nella stringa in corrispondenza delle parentesi graffe nell'ordine in cui sono scritti. Nel caso in cui a = 60 e b = 72 l'output è:

        pdiv(60)={2, 3, 5}
	pdiv(72)={2, 3}

Infine:

	print("gcd({},{})={}".format(a,b,gcd(a,b)))
	print("lcm({},{})={}".format(a,b,lcm(a,b)))

vengono stampati il massimo comun divisore e il minimo comune multiplo di a e b, utilizzando sempre il metodo format come sopra. L'output è il seguente:

	gcd(60,72)=12
	lcm(60,72)=360

Esercizio 2

Mi sono cimentato con l'esercizio [7] del PAS 2013/14. Ecco il mio commento.

f="f={0}{1}{0};print(f.format(chr(34),f))";print(f.format(chr(34),f))

Il programma stampa a video una stringa contenente il codice del programma stesso. Il programma "banalmente" dichiara una stringa f che poi stampa. Sulla stringa f viene richiamato il metodo .format, dal funzionamento abbastanza semplice ma piuttosto macchinoso da descrivere: il metodo serve a formattare la stringa cui viene applicato sostituendo i propri parametri a dei marcatori di posizione presenti nella stringa stessa. Il generico marcatore è composto dall'indice del parametro con cui verrà sostituito racchiuso da parentesi graffe. Nell'esempio in oggetto il metodo format prende in ingresso due parametri: il primo è il carattere " (convertito dall'ascii tramite la funzione chr), il secondo è la stringa stessa. Nella stringa f sono presenti due marcatori {0} che verranno appunto sostituiti dal carattere " e un marcatore {1} che verrà rimpiazzato con la stringa f stessa. Il programma stamperà quindi nell'ordine:

f=
{0} => "
{1} => f={0}{1}{0};print(f.format(chr(34),f))
{0} => "
;print(f.format(chr(34),f))

Cioè, "riassemblando" i pezzi

f="f={0}{1}{0};print(f.format(chr(34),f))";print(f.format(chr(34),f))

che è appunto il codice del programma stesso. --Salvatore Parlato (discussioni) 10:07, 5 mar 2015 (CET)

Esercizio 3

Per prendere confidenza con python ho elaborato un esercizio di lettura simpatico. Dato in input un numero intero stampare la sua rappresentazione in parole.

primiVenti = ["zero","uno","due","tre","quattro",
              "cinque","sei","sette","otto","nove",
              "dieci","undici","dodici","tredici","quattordici",
              "quindici","sedici","diciassette","diciotto","diciannove"]
multipliDieci = ["","","venti","trenta","quaranta","cinquanta",
                 "sessanta","settanta","ottanta","novanta"]
prefissoPotenzeSingolare = ["","", "un", "un","un","un","un","un","un","un"]
potenzeSingolare = ["","mille","milione","miliardo","bilione","biliardo","trilione","triliardo","quadrilione","quadriliardo"]
potenzePlurale = ["","mila","milioni","miliardi","bilioni","biliardi","trilioni","triliardi","quadrilioni","quadriliardi"]


def traslitteraMinoreCento(x):
    lettere = "";
    if (x<20):
        lettere = primiVenti[x]
    else:
        resto = x % 10
        decine = x // 10
        if (resto == 1 or resto == 8):
            lettere = multipliDieci[decine][:-1]
        else:
            lettere = multipliDieci[decine]        
        if (resto > 0):
            lettere += primiVenti[resto]
    return lettere

def traslitteraMinoreMille(x):
    lettere = ""
    if (x < 100):
        lettere = traslitteraMinoreCento(x)
    else:
        resto = x % 100
        risultato = x // 100
        if (risultato == 1):
            lettere = "cento"
        else:
            lettere = primiVenti[risultato]+"cento"
        if(resto > 0):
                lettere += traslitteraMinoreCento(resto)
    return lettere

def traslittera(num):
    lettere = ""
    indiceMigliaia = 0

    while(num > 0):
        resto = num % 1000
        num = num // 1000
        if(resto==1):
            lettere = prefissoPotenzeSingolare[indiceMigliaia] + potenzeSingolare[indiceMigliaia] + lettere
        elif(resto>0):
            lettere = traslitteraMinoreMille(resto) + potenzePlurale[indiceMigliaia] + lettere
            
        indiceMigliaia += 1
    
    return lettere

if __name__ == "__main__":
    print("Digita un numero per convertirlo in lettere. Quando vuoi uscire digita 0")
    n=int(input("Dammi il numero: "))
    while(n>0):
        print ("Numero in lettere:",traslittera(n))
        n=int(input("Dammi il numero: "))
    print("Arrivederci a presto !!!")

Il programma contiene due piccoli errori. Chi si vuole cimentare nel trovarli? --Simone.riccucci (discussioni) 18:57, 7 mar 2015 (CET)

Una versione ricorsiva dell'algoritmo sopra. Più elegante da vedere e che non contiene i due errori

primiVenti = ["zero","uno","due","tre","quattro",
              "cinque","sei","sette","otto","nove",
              "dieci","undici","dodici","tredici","quattordici",
              "quindici","sedici","diciassette","diciotto","diciannove"]
multipliDieci = ["","","venti","trenta","quaranta","cinquanta",
                 "sessanta","settanta","ottanta","novanta"]
potenzeSingolare = ["","mille","unmilione","unmiliardo","unbilione","unbiliardo","untrilione","untriliardo","unquadrilione","unquadriliardo"]
potenzePlurale = ["","mila","milioni","miliardi","bilioni","biliardi","trilioni","triliardi","quadrilioni","quadriliardi"]

def traslittera(x):
    lettere = ""
    if(x > 0):
        if (x < 20):
            lettere = primiVenti[x]
        elif (x < 100):
            resto = x % 10
            decine = x // 10
            if (resto == 1 or resto == 8):
                lettere = multipliDieci[decine][:-1]
            else:
                lettere = multipliDieci[decine]        
            lettere += traslittera(resto)
        elif (x < 200):
            lettere = "cento" + traslittera(x % 100)
        elif (x < 1000):
            lettere = primiVenti[x // 100] + "cento" + traslittera(x % 100)
        else:
            indiceMigliaia, potenza = 1, 1000
            while(indiceMigliaia < len(potenzeSingolare)):
                if(x < potenza * 2):
                    lettere = potenzeSingolare[indiceMigliaia] + traslittera(x % potenza)
                    break
                elif(x < potenza * 1000):
                    lettere = traslittera(x // potenza) + potenzePlurale[indiceMigliaia] + traslittera(x % potenza)
                    break
                potenza = potenza * 1000
                indiceMigliaia += 1
            else:
                lettere = "NON SO CONTARE FINO A " + str(x)
    return lettere

if __name__ == "__main__":
    print("Digita un numero per convertirlo in lettere. Quando vuoi uscire digita 0")
    n=int(input("Dammi il numero: "))
    while(n>0):
        print ("Numero in lettere:",traslittera(n))
        n=int(input("Dammi il numero: "))
    print("Arrivederci a presto !!!")

--Simone.riccucci (discussioni) 22:19, 10 mar 2015 (CET)

Esercizio 4

Propongo un esercizio nello stile dei primi esercizi di lettura preparati per i PAS:

import decimal

def dd(c):
  d = {}
  v = ["2", "1", "0.5", "0.2", "0.1", "0.05", "0.02", "0.01"]
  
  try: 
    c = decimal.Decimal(c)
  except:
    return d
  
  for i in v:
    i = decimal.Decimal(i)
    while (c-i)>= decimal.Decimal("0.00"):
      c = c -i
      if i in d:
        d[i] += 1
      else:
        d[i]=1
  return d
 
if __name__=="__main__":
  data=(input("Dammi una cifra espressa in € (es. 2.14) "))
  d = dd(data)
  print("La funzione misteriosa restituisce:")
  for k,v in d.items():
    print(v, "da ", k, "€")

Una considerazione: ponendosi di fronte agli esercizi di lettura risulta chiaro che un codice in cui le variabili abbiano nomi come a, b o c non sia particolarmente semplice da leggere. Chiunque ha un'esperienza di sviluppo sa quanto sia importante e delicato scrivere con un certo "stile". Mi chiedo da profano dell'insegnamento dell'informatica alle scuole superiori: a lezione si pone l'attenzione sugli aspetti di stile del codice (nomi di variabili e funzioni, ma anche formattazione)? Potrebbe essere utile farlo? Questo non tanto per insegnare ai ragazzi ad essere bravi programmatori (non che questo sarebbe male, anzi) ma per accrescere la sensibilità nei confronti del coding, ovvero per renderli capaci, come si diceva a lezione, di saper riconoscere un software scritto bene, da uno scritto male. --Matteo.montani (discussioni) 19:51, 12 mar 2015 (CET)

Esercizio 5

Nel tentativo di prendere "confidenza" con Python ho aggiunto questo algoritmo, parte di un più complesso algoritmo di selezione.

#SCOPO: progettare un algoritmo che determini il mediano di 5 elementi, sui quali sia definito un ordine totale,
#       utilizzando al più 6 confronti
#
#DESCRIZIONE: viene utilizzato l'algoritmo del torneo sui primi quattro elementi di una lista. Il vincitore viene scartato
#in quanto è il maggiore di tre elementi e quindi non può esserne il mediano. Si ripete il torneo
#sui quattro rimanenti elementi. Si esegue un ultimo torneo sui tre elementi rimanenti il vincitore
#di quest'ultimo torneo è il mediano. Il numero di confronti è dovuto al numero di chiamate della
#funzione posVin. Sono però necessarie un numero di variabili ausiliarie per tenere traccia dei vincitori
#degli scontri che degli elementi che rimangono invariati tra un torneo e l'altro.

#Indici delle posizioni della lista come costanti
POS_ELEM_1 = 0
POS_ELEM_2 = 1
POS_ELEM_3 = 2
POS_ELEM_4 = 3
POS_ELEM_5 = 4

#Numero massimo di elementi della lista
N_MAX_ELEM = 5

#Calcola l'indice della posizione dell'elemento maggiore tra due
def posVin(A, indice1, indice2):
    if A[indice1]> A[indice2]:
        return indice1, A[indice1]
    else:
        return indice2, A[indice2]

#Effettua lo scambio tra due elementi della lista
def scambio(elementi, a , b):
    tmp = elementi[a]
    elementi[a] = elementi[b]
    elementi[b] = tmp    

def mediano(A):
    #Primo torneo tra i primi quattro elementi
    pos12_T1, vin12_T1 = posVin(A, POS_ELEM_1, POS_ELEM_2) 
    pos34_T1, vin34_T1 = posVin(A, POS_ELEM_3, POS_ELEM_4)
    posVin_T1, vin_T1 = posVin(A, pos12_T1, pos34_T1)

    #Secondo torneo: al posto del vincitore del primo torneo inserisco il quinto elemento della lista
    scambio(A, posVin_T1, POS_ELEM_5)
    
    if posVin_T1==POS_ELEM_1 or posVin_T1 == POS_ELEM_2:
        #L'elemento che non ha partecipato al primo torneo è in una delle due prime posizioni
        pos12_T2, vin12_T2 = posVin(A, POS_ELEM_1, POS_ELEM_2)
        pos34_T2 = pos34_T1
    else:
        #L'elemento che non ha partecipato al primo torneo è nella terza o quarta posizione
        pos34_T2, vin34_T2 = posVin(A, POS_ELEM_3, POS_ELEM_4)
        pos12_T2 = pos12_T1 

    posVin_T2, vin_T2 = posVin(A, pos12_T2, pos34_T2)

    #Determino la posizione del primo sconfitto dal vincitore del secondo torneo 
    if posVin_T2 == POS_ELEM_1:
        posPrimoSconfittoVinT2 = POS_ELEM_2 
    if posVin_T2 == POS_ELEM_2:
        posPrimoSconfittoVinT2 = POS_ELEM_1
    if posVin_T2 == POS_ELEM_3:
        posPrimoSconfittoVinT2 = POS_ELEM_4
    if posVin_T2 == POS_ELEM_4:
        posPrimoSconfittoVinT2 = POS_ELEM_3

    
    if posVin_T2 == POS_ELEM_1 or posVin_T2 == POS_ELEM_2:
        pos_mediano, vinT3 = posVin(A, posPrimoSconfittoVinT2, pos34_T2)
    else:
        pos_mediano, vinT3 = posVin(A, posPrimoSconfittoVinT2, pos12_T2)

    return A[pos_mediano]
    
print("Per cortesia inserisci cinque valori numerici")
elementi=list()

while(True):
    try:
        elementi.append(int(input()))

        if len(elementi) == N_MAX_ELEM:
            break
    except ValueError:
        print("Il valore inserito non è un numero. Per cortesia riprova")
    except:
        print("Errore generico. Per cortesia riprova")
        
print("I cinque elementi inseriti sono:", sep='', end=' ')
print(elementi)

medio = mediano(elementi)
print("\nIl mediano dei cinque elementi inseriti è:", sep='', end=' ')
print(medio)

Alla fine dell'implementazione e della fase di verifica dell'algoritmo mi sono chiesto che valenza didattica possa avere un quesito di questo genere in una scuola superiore. Se da un certo punto di vista il problema posto è sufficientemente semplice e maneggiabile da poter lasciare allo studente la libertà di provare a risolverlo senza che sia mai stato formalizzato prima il concetto di selezione del mediano, ci si accorge poi che andando per tentativi la risoluzione non è così immediata, anzi. Probabilmente gli allievi più dotati arriverebbero a formalizzare, almeno in modo intuitivo, una soluzione ma credo che il resto degli studenti dopo alcuni tentativi rinuncerebbero. Altra cosa che mi sembra interessante è la complessità che si incontra nel passare da pseudocodifica a codifica. Nella pseudocodifica per tenere conto del fatto che alcuni confronti tra elementi adiacenti della lista tra tornei successivi non variano è sufficiente una indicazione formale e l'algoritmo viene scritto in poche righe. Nella codifica in Python per tenere conto di questo fatto e evitare di rifare confronti già effettuati la complessità aumenta e come detto è necessario aggiungere variabili e condizioni del tutto assenti nella prima fase di progettazione dell'algoritmo. Ultima cosa legata al linguaggio Python. La possibilità di poter restituire più valori con un singolo return di una funzione è un beneficio che ho apprezzato (inizialmente avevo codificato due funzioni che facevano quello che fa ora una singola funzione). Poi però riflettendoci bene mi sono chiesto se in effetti fosse proprio solo un vantaggio. Nel senso che forse si corre il rischio abusando di questa opportunità di far fare a una funzione troppe cose con il rischio di veder venir meno quel principio di modularità sempre necessario se vogliamo mantenere chiaro il concetto di una sola azione per funzione. Per cui anche qui dovendo introdurre Python a scuola prima terrei questa particolarità del linguaggio ben celata e solo quando gli studenti hanno radicato il concetto di modularità parlerei della possibilità di utilizzare questa particolarità del linguaggio facendo ben presente vantaggi e svantaggi.--Savino (discussioni) 20:44, 15 mar 2015 (CET)

Vorrei fare alcune osservazioni sulla complessità dell'algoritmo sopra. L'algoritmo trova il mediano effettuando un numero fisso di confronti tra gli elementi pari a 6. Tuttavia il vincolo di dover fare varie operazioni intermedie aumenta la sua complessità reale. Infatti si necessitano di 17 assegnamenti + 9 confronti in totale in tutti i casi. Una versione che diminuisce la complessità reale potrebbe essere la seguente basata sul concetto di divide et impera. Si sacrifica un confronto tra elementi per guadagnare sul complesso delle operazioni.

def mediano(v):
    if(v[0] > v[1]):
        tmp = v[0]
        v[0] = v[1]
        v[1] = tmp
    
    if(v[2] > v[3]):
        tmp = v[2]
        v[2] = v[3]
        v[3] = tmp

    if(v[4] < v[2]):
        tmp = v[4]
        v[4] = v[3]
        v[3] = v[2]
        v[2] = tmp
    elif(v[4] < v[3]):
        tmp = v[3]
        v[3] = v[4]
        v[4] = tmp
    
    i=0
    j=2
    if(v[i]<v[j]):
        i = i + 1
    else:
        j = j + 1
    if(v[i]<v[j]):
        i = i + 1
    else:
        j = j + 1
    if(v[i]<v[j]):
        return v[i]
    else:
        return v[j]

L'algoritmo divide il vettore di 5 elementi in due parti e le ordina. Nella fase finale trova il mediano sfruttando il fatto di avere due parti del vettore ordinate. Nel caso peggiore effettua 12 assegnamenti + 7 confronti + 2 incrementi. Nel caso migliore 2 assegnamenti + 7 confronti + 2 incrementi. Per il caso medio i primi due blocchi degli if verranno eseguiti il 50% delle volte mentre i blocchi successivi verranno eseguiti con una probabilità di 1/3. Quindi otterremo 3 assegnamenti + 7/3 assegnamenti. Il confronto del ramo elif verrà eseguito con probabilità 2/3. Sommando tutto si ottiene: 22/3 assegnamenti + 20/3 assegnamenti + 2 incrementi.

Infine per mostrare gli step successivi del raffinamento di un algoritmo la soluzione ottima:

def mediano2(v):
    #ordino la prima coppia di elementi
    if(v[0] > v[1]):
        tmp = v[0]
        v[0] = v[1]
        v[1] = tmp

    #ordino la seconda coppia elementi
    if(v[2] > v[3]):
        tmp = v[2]
        v[2] = v[3]
        v[3] = tmp

    #elimino il minore dei minori perché non può essere il mediano
    #al suo posto metto l'ultimo elemento e ordino la rispettiva coppia
    if(v[0]<v[2]):
        if(v[1]<v[4]):
            v[0] = v[1]
            v[1] = v[4]
        else:
            v[0] = v[4]
    else:
        if(v[3]<v[4]):
            v[2] = v[3]
            v[3] = v[4]
        else:
            v[2] = v[4]

    #A questo punto ho due coppie ordinate nelle prime quattro posizioni
    #devo trovare il secondo elemento più piccolo
    if(v[0]<v[2]):
        if(v[1]<v[2]):
            return v[1]
        else:
            return v[2]
    else:
        if(v[0]<v[3]):
            return v[0]
        else:
            return v[3]

Il caso pessimo necessita di 8 assegnamenti + 6 confronti. Il caso ottimo 1 assegnamento + 6 confronti

Esercizio 6

Propongo gli esercizi della Verifica di Laboratorio sugli array mono e bidimensionali che ho somministrato ai miei alunni di terza IT. In seguito riporto il mio svolgimento in linguaggio Python.

Testo 1: Creare un programma che prenda in input un vettore di numeri naturali di 15 elementi e lo stampi al contrario. Stampare poi tutti i numeri pari del vettore.

dim = 15
seq = range(0,dim)
vet = [int(input("Inserisci un numero reale: ")) for _ in seq]

#alternativa
#vet = [0 for _ in seq]
#for i in seq:
    #vet[i] = int(input("Inserisci un numero naturale "))

print("Il vettore al contrario e': ")
print(vet[::-1])

#alternativa
#print([vet[dim-1-i] for i in seq])

print("I numeri pari del vettore sono: ")
print([vet[i] for i in seq if vet[i]%2==0])

Testo 2: Dati due vettori di 20 elementi generati casualmente tra 0 e 10, salvare in un terzo vettore la somma dei precedenti e stamparlo. Infine ordinare in ordine decrescente il terzo vettore e stamparlo.

import random

def reverse_selection_sort(v):
    for i in range(len(v)):
        for j in range(i+1,len(v)):
            if v[j] > v[i]:
                v[i],v[j]=v[j],v[i]


dim = 20
seq = range(0,dim)
array1 = [random.random()*10 for _ in seq]
print("Il primo vettore e': ")
print(array1)
array2 = [random.random()*10 for _ in seq]
print("Il secondo vettore e': ")
print(array2)
array3 = [array1[i] + array2[i] for i in seq]
print("La somma dei due vettori e': ")
print(array3)
reverse_selection_sort(array3)

#alternativa
#array3.sort(reverse=True)

print("Il vettore ordinato in ordine decrescente e': ")
print(array3)

Testo 3: Un negozio di articoli online dispone di una tabella con le seguenti caratteristiche: la prima colonna contiene il numero identificativo dell'articolo, la seconda colonna il prezzo dell'articolo e l'ultima colonna la quantità di articoli presenti in negozio.

Creare un programma che prenda in input un numero di articoli a scelta dell'utente, con le loro caratteristiche (prezzo e quantità) su un massimale di 50 articoli. Ordinare successivamente la tabella in ordine crescente di prezzo.

row = 0
column = 3
while True:
    row = int(input("Inserisci il numero di articoli: "))
    if row <= 50:
       break
matrix = [tuple([0 for _ in range(column)]) for _ in range(row)]
for i in range(row):
    code = input("Inserisci il codice dell'articolo: ")
    price = float(input("Inserisci il prezzo dell'articolo: "))
    number = int(input("Inserisci il numero di articoli presenti in negozio: "))
    matrix[i] = tuple([code, price, number])
from operator import itemgetter
matrix = sorted(matrix, key=itemgetter(1))
print("I prodotti ordinati per prezzo sono: ")
print(matrix)

Osservazione. Per semplicità, non è stato richiesto agli studenti il controllo sull'univocità dei codici degli articoli.--Elena (discussioni) 20:16, 15 mar 2015 (CET)

Esercizio 7

prima versione

Ne propongo uno nuovo anch'io...

#!/usr/bin/env python3
import sys

numbers=[("miliard",0,10**9), ("milion",0,10**6), ("mila",0,10**3), ("mille",1,1000),
  ("cento",100,0),
  ("vent",20,0), ("trent",30,0), ("quarant",40,0), ("cinquant", 50,0),
  ("sessant",60,0), ("settant",70,0), ("ottant",80,0), ("novant",90,0),
  ("undici",11,0), ("dodici",12,0), ("tredici",13,0), ("quattordici",14,0), ("quindici",15,0),
  ("sedici",16,0), ("diciassette",17,0), ("diciotto",18,0), ("diciannove",19,0),
  ("un",1,0), ("due",2,0), ("tre",3,0), ("quattro",4,0), ("cinque",5,0),
  ("sei",6,0), ("sette",7,0), ("otto",8,0), ("nove",9,0), ("dieci",10,0),
  ("zero",0,0), ("di",0,0)]

def str2num(s):
  hi = lo = last = 0
  err = 1
  while s:
    for ns,num,mul in numbers:
      if s[:len(ns)] == ns:
        if mul:
          if lo==0:
            lo = num
          if last > mul:
            hi,lo = hi+lo*mul,0
          else:
            hi,lo = (hi+lo)*mul,0
          last = mul
        elif num > lo:
          lo = lo*num if lo else num
        else:
          lo = lo+num
        s,err = s[len(ns):],0
        break;
    else:
      if err:
        return -1
      else:
        s,err = s[1:],1
  return hi+lo

if __name__ == "__main__":
  n=str2num(sys.argv[1])
  print(n)

... cosa fa? quali sono i principi di funzionamento?

Il programma calcola un numero a partire dalla sua rappresentazione in lettere (il contrario del mio !!!). Provo a descriverne sommariamente il funzionamento riservandomi un'analisi più dettagliata in seguito. Il programma scorre il numero da sinistra a destra cercando una corrispondenza nelle stringhe definite nella struttura iniziale. Trovata la corrispondenza incrementa il numero in base alle caratteristiche definite nella struttura e in base allo stato corrente dell'iterazione. Ogni volta che si incontra un potenza di 1000 si moltiplica il numero per il terzo valore mentre negli altri casi si mantiene la somma degli elementi. Il programma funziona correttamente quando si inseriscono stringhe valide. Se si inserisco numeri tipo "centocento" o "unomille" il programma fallisce il calcolo dando in output nel primo caso 200 nel secondo 2000 (2000 dato dal fatto che il primo giro trova 1 e lo tiene in memoria al secondo giro trova mille quindi somma 1 all'uno specificato nel secondo valore della struttura dati e poi moltiplica per 1000 specificato nel terzo valore della struttura dati).

Aggiornamento: (rd 20150319) "centocento" viene ancora convertito in 200 ma ora "unomille" fa 1000

seconda versione

(il sottotitolo e': "is it a bug or a feature?")

#!/usr/bin/env python3
import sys

class num:
        def __init__(self,n):
                self.val=n

class mul(num):
        pass

class onemul(mul):
        pass

class plus():
        pass

class times():
        pass

class numlanguage():
        def __init__(self):
                self.dict={}
        def __setitem__(self,s,op):
                self.dict[s]=op
                for l in range(len(s)-1,0,-1):
                        if s[:l] in self.dict:
                                break
                        else:
                                self.dict[s[:l]]=None
                return op
        def match(self,s):
                matchlen,obj=0,None
                for l in range(1,len(s)+1):
                        if s[:l] not in self.dict:
                                break
                        else:
                                matchedobj=self.dict[s[:l]]
                                if matchedobj:
                                        matchlen,obj=l,matchedobj
                return matchlen,obj

def str2num(langnum,s):
        hi=lo=last=0
        lastop=None
        while s:
                if s[0] in " -\t\n":
                        s=s[1:]
                else:
                        ml,obj=langnum.match(s)
                        if obj:
                                if isinstance(obj,num):
                                        if isinstance(obj,mul):
                                                if isinstance(obj,onemul) and lo == 0:
                                                        lo = 1
                                                if (last <= obj.val or isinstance(lastop,times)) and not isinstance(lastop,plus):
                                                        hi,lo = (hi+lo)*obj.val,0
                                                else:
                                                        hi,lo = hi+lo*obj.val,0
                                                last=obj.val
                                        else: 
                                                if obj.val <= lo or isinstance(lastop,plus):
                                                        lo += obj.val
                                                else:
                                                        lo = lo*obj.val if lo else obj.val
                                        lastop=None
                                else:
                                        lastop=obj
#                               print(s[:ml],hi,lo,last,lastop)
                                s=s[ml:]
                        else:
                                return -1
        return hi+lo

def num_it():
        nl=numlanguage()
        nl["zero"]=num(0) 
        nl["uno"]=nl["un"]=nl["una"]=num(1) 
        nl["due"]=num(2) 
        nl["tre"]=num(3) 
        nl["quattro"]=num(4) 
        nl["cinque"]=num(5) 
        nl["sei"]=num(6) 
        nl["sette"]=num(7) 
        nl["otto"]=num(8) 
        nl["nove"]=num(9) 
        nl["dieci"]=num(10) 
        nl["undici"]=num(11) 
        nl["dodici"]=num(12) 
        nl["tredici"]=num(13) 
        nl["quattordici"]=num(14) 
        nl["quindici"]=num(15) 
        nl["sedici"]=num(16) 
        nl["diciassette"]=num(17) 
        nl["diciotto"]=num(18) 
        nl["diciannove"]=num(19) 
        nl["venti"]=nl["vent"]=num(20) 
        nl["trenta"]=nl["trent"]=num(30) 
        nl["quaranta"]=nl["quarant"]=num(40) 
        nl["cinquanta"]=nl["cinquant"]=num(50) 
        nl["sessanta"]=nl["sessant"]=num(60) 
        nl["settanta"]=nl["settant"]=num(70) 
        nl["ottanta"]=nl["ottant"]=num(80) 
        nl["novanta"]=nl["novant"]=num(90) 
        nl["cento"]=num(100) 
        nl["mille"]=onemul(10**3) 
        nl["mila"]=nl["migliaia"]=mul(10**3) 
        nl["milioni"]=nl["milione"]=mul(10**6) 
        nl["miliardi"]=nl["miliardo"]=mul(10**9) 
        nl["dozzine"]=nl["dozzina"]=mul(12) 
        nl["decine"]=nl["decina"]=mul(10) 
        nl["centinaia"]=mul(100) 
        nl["di"]=times() 
        nl["e"]=plus() 
        return nl

def num_en():
        nl=numlanguage()
        nl["zero"]=nl["null"]=num(0)
        nl["one"]=num(1)
        nl["two"]=num(2)
        nl["three"]=num(3)
        nl["four"]=num(4)
        nl["five"]=num(5)
        nl["six"]=num(6)
        nl["seven"]=num(7)
        nl["eight"]=num(8)
        nl["nine"]=num(9)
        nl["ten"]=num(10)
        nl["eleven"]=num(11)
        nl["twelve"]=num(12)
        nl["thirteen"]=num(13)
        nl["fourteen"]=num(14)
        nl["fifteen"]=num(15)
        nl["sixteen"]=num(16)
        nl["seventeen"]=num(17)
        nl["eighteen"]=num(18)
        nl["nineteen"]=num(19)
        nl["twenty"]=num(20)
        nl["thirty"]=num(30)
        nl["forty"]=num(40)
        nl["fifty"]=num(50)
        nl["sixty"]=num(60)
        nl["seventy"]=num(70)
        nl["eighty"]=num(80)
        nl["ninety"]=num(90)
        nl["hundred"]=num(100)
        nl["thousand"]=mul(10**3)
        nl["million"]=mul(10**6)
        nl["billion"]=mul(10**9)
        nl["trillion"]=mul(10**12)
        nl["dozen"]=mul(12)
        nl["and"]=plus()
        nl["of"]=times()
        return nl

def num_fr():
        nl=numlanguage()
        nl["zero"]=num(0)
        nl["un"]=num(1)
        nl["deux"]=num(2)
        nl["trois"]=num(3)
        nl["quatre"]=num(4)
        nl["cinq"]=num(5)
        nl["six"]=num(6)
        nl["sept"]=num(7)
        nl["huit"]=num(8)
        nl["neuf"]=num(9)
        nl["dix"]=num(10)
        nl["onze"]=num(11)
        nl["douze"]=num(12)
        nl["treize"]=num(13)
        nl["quatorze"]=num(14)
        nl["quinze"]=num(15)
        nl["seize"]=num(16)
        nl["vingt"]=num(20)
        nl["trente"]=num(30)
        nl["quarante"]=num(40)
        nl["cinquante"]=num(50)
        nl["soixante"]=num(60)
        nl["cent"]=num(100)
        nl["mille"]=onemul(10**3)
        nl["million"]=mul(10**6)
        nl["milliard"]=mul(10**9)
        nl["douzaine"]=mul(12)
        nl["et"]=plus()
        nl["de"]=times()
        return nl

def num_de():
        nl=numlanguage()
        nl["null"]=num(0)
        nl["eins"]=nl["ein"]=num(1)
        nl["zwei"]=nl["zwo"]=num(2)
        nl["drei"]=num(3)
        nl["vier"]=num(4)
        nl["fünf"]=num(5)
        nl["sechs"]=num(6)
        nl["sieben"]=num(7)
        nl["acht"]=num(8)
        nl["neun"]=num(9)
        nl["zehn"]=num(10)
        nl["elf"]=num(11)
        nl["zwölf"]=num(12)
        nl["dreizehn"]=num(13)
        nl["vierzehn"]=num(14)
        nl["fünfzehn"]=num(15)
        nl["sechzehn"]=num(16)
        nl["siebzehn"]=num(17)
        nl["achtzehn"]=num(18)
        nl["neunzehn"]=num(19)
        nl["zwanzig"]=num(20)
        nl["dreiβig"]=num(30)
        nl["vierzig"]=num(40)
        nl["fünfzig"]=num(50)
        nl["sechzig"]=num(60)
        nl["siebzig"]=num(70)
        nl["achtzig"]=num(80)
        nl["neunzig"]=num(90)
        nl["hundert"]=num(100)
        nl["tausend"]=mul(10**3)
        nl["million"]=mul(10**6)
        nl["milliard"]=mul(10**9)
        nl["und"]=plus()
        return nl

def num_es():
        nl=numlanguage()
        nl["cero"]=num(0)
        nl["uno"]=num(1)
        nl["dos"]=num(2)
        nl["tres"]=num(3)
        nl["cuatro"]=num(4)
        nl["cinco"]=num(5)
        nl["seis"]=num(6)
        nl["siete"]=num(7)
        nl["ocho"]=num(8)
        nl["nueve"]=num(9)
        nl["diez"]=num(10)
        nl["once"]=num(11)
        nl["doce"]=num(12)
        nl["trece"]=num(13)
        nl["catorce"]=num(14)
        nl["quince"]=num(15)
        nl["dieciséis"]=num(16)
        nl["diecisiete"]=num(17)
        nl["dieciocho"]=num(18)
        nl["diecinueve"]=num(19)
        nl["veinte"]=nl["veinti"]=num(20)
        nl["treinta"]=num(30)
        nl["cuarenta"]=num(40)
        nl["cincuenta"]=num(50)
        nl["sesenta"]=num(60)
        nl["setenta"]=num(70)
        nl["ochenta"]=num(80)
        nl["noventa"]=num(90)
        nl["cien"]=nl["cientos"]=num(100)
        nl["quinientos"]=num(500)
        nl["setecientos "]=num(700)
        nl["novecientos"]=num(900)
        nl["mil"]=onemul(10**3)
        nl["millón"]=nl["millones"]=mul(10**6)
        nl["billón"]=nl["billones"]=mul(10**12)
        nl["y"]=plus()
        return nl

if __name__ == "__main__":
        itnum=num_it()
        print("it",str2num(itnum,sys.argv[1]))
        ennum=num_en()
        print("en",str2num(ennum,sys.argv[1]))
        frnum=num_fr()
        print("fr",str2num(frnum,sys.argv[1]))
        denum=num_de()
        print("de",str2num(denum,sys.argv[1]))
        esnum=num_es()
        print("es",str2num(esnum,sys.argv[1]))

terza versione

Un altro modo per risolvere lo stesso problema, forse in maniera più leggibile:

#!/usr/bin/python3

unita = ['', 'uno', 'due', 'tre', 'quattro', 'cinque', 'sei', 'sette', 'otto', 'nove', 'dieci', 
'undici', 'dodici', 'tredici', 'quattordici', 'quindici', 'sedici', 'diciassette', 
'diciotto', 'diciannove' ]

decine = ['', 'dieci', 'venti', 'trenta', 'quaranta', 'cinquanta', 'sessanta', 'settanta', 
'ottanta', 'novanta']

def parole_meno_di_mille(n):
    r = ''
    c = n // 100
    if c > 0:
        if c > 1:
            r = r + unita[c]
        r = r + 'cento'
        n = n - 100 * c

    if n < 20:
        return r + unita[n]

    d = n // 10
    u = n - d * 10
    if u == 1 or u == 8:
        r = r + decine[d][:-1]
    else:
        r = r + decine[d]
    return r + unita[u]

def parole(n):
    if n == 0:
        return 'zero'

    r = ''

    miliardi = n // 1000000000
    if miliardi > 0:
        if miliardi == 1:
            r = r + 'unmiliardo'
        else:
            r = r + parole_meno_di_mille(miliardi) + 'miliardi'
        n = n - miliardi * 1000000000

    milioni = n // 1000000
    if milioni > 0:
        if milioni == 1:
            r = r + 'unmilione'
        else:
            r = r + parole_meno_di_mille(milioni) + 'milioni'
        n = n - milioni * 1000000

    migliaia = n // 1000
    if migliaia > 0:
        if migliaia == 1:
            r = r + 'mille'
        else:
            r = r + parole_meno_di_mille(migliaia) + 'mila'
        n = n - migliaia * 1000

    r = r + parole_meno_di_mille(n)

    return r

n = int(input('inserisci un numero: '))

print(parole(n))

Esercizi proposti da Michael Lodi

--Michael (discussioni) 22:02, 16 mar 2015 (CET)

Esercizio di lettura + esercizio di scrittura

x = 42
y = 3.14

print("All'inizio x vale %5.2f e y vale %5.2f" % (x, y))

x = x + y
y = x - y
x = x - y

print("Ora x vale {:5.2f} e y vale {:5.2f}".format(x,y))
  • Che cosa ho fatto qui?
  • Potrebbero sorgere dei problemi?
  • Se non avessi problemi a usare altre variabili, come otterrei lo stesso risultato?
  • In Python c'è un terzo modo ancora più veloce (ma più "oscuro")?

Semplici esercizi di Debug

Per capire alcune funzionalità del Python, propongo una serie di semplici esercizi (ispirati a quelli proposti come esercizi da svolgere a casa in in "BJC", qui svolti da me) in cui però ho inserito un (anzi, almeno un ^^') bug, che aiuta a capire alcune funzionalità del Python.

Nei seguenti programmi:

  • scopri che intenzioni avevo (l'inglese aiuta...)
  • prova il programma
  • correggi il bug
  • riprova il programma!


def first_x_positive_even_nums(x):
    for num in range(1, x):
        print (2 * num)


def reverse_string(string):
    res = ""
    for i in range(len(string)-1, 0):
        res = res + string[i]
    return res
e nemmeno così funziona...
def reverse_string(string):
    res = ""
    for i in range(len(string)-1, -1):
        res = res + string[i]
    return res


def palindrome(string):
    if (len(string) < 2):
        return True
    elif (string[0]!=string[len(string)-1]):
        return False
    else:
        return palindrome(string[1:len(string)])


def push_odd_back(lst):
        for n in lst:
                if (n%2)!=0:
                        lst.pop(n)
                        lst.append(n)
                        break


def flatten(2dlst):
        flatlist = []
        for a1dlst in 2dlst:
                for el in a1dlst:
                        flatlist.append(el)
        return flatlist


# N.B. voglio poter usare la funzione seguente sia su liste di numeri che su liste di stringhe
def combine(lst):
        res = lst[0]
        for el in lst:
                res += el
        return res


Esercizi per comprendere l'importanza dei cicli (e delle funzioni)

Preparando una lezione sui cicli in Scratch, ho giocato con la sua classica funzione "penna", ereditata dal Logo. Poiché il modulo turtle di Python si ispira proprio al Logo, è stato immediato tradurre il mio progetto in un esercizio Python. La lezione è nei commenti. Iniziare a leggere dal main, ovviamente.

import turtle
from time import sleep
import random


def poligono_regolare(numero_lati):
    if numero_lati>2:
        for i in range(0,numero_lati):
            turtle.forward(100)
            turtle.left(360/numero_lati)

def poligono_regolare_lato(numero_lati, lunghezza_lato):
    if numero_lati>2:
        for i in range(0,numero_lati):
            turtle.forward(lunghezza_lato)
            turtle.left(360/numero_lati)  
    
def disegnatore_di_scuole(dimensione):
    poligono_regolare_lato(4,dimensione)
    #Porta (doppia)
    for i in range(0,2):
        turtle.penup()
        turtle.forward(dimensione/4)
        turtle.pendown()
        poligono_regolare_lato(4,dimensione/4)
    turtle.penup()
    turtle.left(90)
    turtle.forward(dimensione/2)
    turtle.right(90)
    turtle.pendown()
    #Oblo'
    turtle.circle(dimensione/4.5)
    #Tetto
    turtle.penup()
    turtle.left(90)
    turtle.forward(dimensione/2)
    turtle.right(90)
    turtle.backward(dimensione/2)
    turtle.pendown()
    poligono_regolare_lato(3,dimensione)



if __name__ == "__main__":
    #Disegnare un quadrato, senza loop
    turtle.forward(100)
    turtle.left(90)
    turtle.forward(100)
    turtle.left(90)
    turtle.forward(100)
    turtle.left(90)
    turtle.forward(100)
    turtle.left(90)

    turtle.clearscreen()
    
    #Usare un loop puo' essere utile... per esempio per cambiare la dimensione una sola volta!
    for i in range(0,4):
        turtle.forward(100)
        turtle.left(90)

    turtle.clearscreen()
    
    #E se volessi fare un triangolo?
    for i in range(0,3):
        turtle.forward(100)
        turtle.left(120)

    turtle.clearscreen()
    #E un pentagono?
    for i in range(0,5):
        turtle.forward(100)
        turtle.left(72)

    #E' il caso di generalizzare? Una funzione puo' fare al caso nostro
    for i in range(0, 10):
        print "Disegno un poligono di lato"+str(i)
        poligono_regolare(i)
        turtle.clearscreen()

    #A cosa mi sto avvicinando? Proviamo
    poligono_regolare(360)

    turtle.clearscreen()

    #Forse e' bene parametrizzare anche la lunghezza del lato
    poligono_regolare_lato(360, 1)

    turtle.clearscreen()


    #Proviamo a disegnare una scuola molto... regolare!

    #Edificio
    poligono_regolare_lato(4,100)
    #Porta (doppia)
    for i in range(0,2):
        turtle.penup()
        turtle.forward(25)
        turtle.pendown()
        poligono_regolare_lato(4,25)
    turtle.penup()
    turtle.left(90)
    turtle.forward(50)
    turtle.right(90)
    turtle.pendown()
    #Oblo'
    poligono_regolare_lato(360,0.314)
    #Tetto
    turtle.penup()
    turtle.left(90)
    turtle.forward(50)
    turtle.right(90)
    turtle.backward(50)
    turtle.pendown()
    poligono_regolare_lato(3,100)

    turtle.clearscreen()

    #Disegnamo scuole di dimensioni diverse, aiutandoci con una funzione
    for i in range(1,5):
        disegnatore_di_scuole(i*25)
        sleep(2) #aspetta 2 secondi per ammirare la tua creazione!
        turtle.clearscreen()

    #Una stellina
    for i in range(0,5):
        turtle.forward(100)
        turtle.right(144)

    turtle.clearscreen()

    #Un fiore colorato
    turtle.colormode(255) #Per passare alla modalita' RGB
    turtle.pencolor(random.randint(0,255),random.randint(0,255),random.randint(0,255))
    
    turtle.penup()
    turtle.pensize(10)
    for i in range(0,8):
        for i in range(0,10):
            turtle.pendown()
            turtle.forward(10)
            turtle.pensize(turtle.pensize()+5)
        turtle.penup()
        turtle.backward(100)
        turtle.right(45)
        turtle.pensize(10)
        turtle.pencolor(random.randint(0,255),random.randint(0,255),random.randint(0,255)) 

Proposte di MrC

Counting sort - ordinamento molto semplice, ma poco considerato

Premessa:

  • si basa su particolarità dei dati (numeri interi)
  • non è basato su confronti e scambi e conviene utilizzarlo quando il valore (massimo - minimo) è piccolo rispetto alla lunghezza dell'array
  • la versione analoga per numeri in virgola mobile si chiama Radix Sort

"Il Counting sort è un algoritmo di ordinamento per valori numerici interi con complessità lineare (rispetto la lunghezza dell'array). "L'algoritmo si basa sulla conoscenza a priori dell'intervallo in cui sono compresi i valori da ordinare" (maxval)

"L'algoritmo conta il numero di occorrenze di ciascun valore presente nell'array da ordinare, memorizzando questa informazione in un array temporaneo di dimensione pari all'intervallo di valori. Il numero di ripetizioni dei valori inferiori indica la posizione del valore immediatamente successivo. Si calcolano i valori massimo e minimo dell'array e si prepara un array ausiliario C di dimensione pari all'intervallo dei valori con C[i] che rappresenta la frequenza dell'elemento i+valore minimo nell'array di partenza. Si visita l'array aumentando l'elemento di C corrispondente. Dopo si visita l'array C in ordine e si scrivono sull'array originale, C[i] copie del valore i+valore minimo."


#!/usr/bin/env python
 
def counting_sort(array, maxval):
    """counting sort"""
    m = maxval + 1
    count = [0] * m               # inizializza l'array di dimensione maxval con zeri
    for a in array:
        count[a] += 1             # conta le occorrenze (eq. ordina l'array)
    
    i = 0
    for a in range(m):            # riordina l'array originale
        for c in range(count[a]):
            array[i] = a
            i += 1
    return (array,count)
 
print counting_sort( [1, 4, 7, 2, 1, 3, 2, 1, 4, 2, 3, 2, 1], 7 )
# STAMPA: [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 4, 4, 7],[0, 4, 4, 2, 2, 0, 0, 1]

Semplice Web Server

... che avevo scritto come esempio in un corso.

Funzionamento:

  • Main - Il server ascolta sulla porta 80 "per sempre" richiamando MRCHandler
  • Main - Se arriva un interruzione da tastiera il server termina
  • Main - Se c'è un errore il server stampa il codice di errore 500 e termina
  • MRCHandler - Lavora solo sul medoto GET
  • MRCHandler - Se il path richiesto è / allora viene servito il file index.html
  • MRCHandler - Se il path richiesto è /TEST allora viene stampata la data e l'ora corrente
  • MRCHandler - Se il path non è uno dei due precententi viene ritornato il codice di errore 415

Si chiedeva di collegarsi al webserver con un client grafico (es. Firefox) e a mano (es. tramite NetCat o Telnet), poi provare a modificare/integrare il programma e a controllare i vari codici di errore (es. 415).

MRC prima di Handler voleva sottolineare che si possono creare e personalizzare differenti gestori in differenti modi...


#!/usr/bin/env python

import string,cgi,time
from os import curdir, sep
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
from time import gmtime, strftime

class MRCHandler(BaseHTTPRequestHandler):

	prginfo = "Simple Python web server v0.1 - By MrC"

	def do_GET(self):
		try:
			if self.path == '/' :    
				f = open(curdir + sep + "index.html")
				self.send_response(200)
				self.send_header('Content-type','text/html')
				self.end_headers()
				self.wfile.write(f.read())
				f.close()
				return     
		
			# serve your pages here 
				
			if self.path == '/TEST':
				self.send_response(200)
				self.send_header('Content-type','text/html')
				self.end_headers()
				self.wfile.write("<html>\n<title>%s</title><body>\n" % MRCHandler.prginfo)
				self.wfile.write("<br>\nTEST PAGE<br>\n")
				self.wfile.write("Example of dynamic data: " + strftime("%a, %d %b %Y %H:%M:%S +0000", gmtime()))
				self.wfile.write("\n</body>\n</html>")
				return
		
			else:
				# Is 415 correct?
				self.send_error(415,'This server not serve files different from main page or TEST')
				return
		
		except Exception, err:
			self.send_error(500,'%s' % str(err))
			return

	# POST ?
	
def main():
	try:
		server = HTTPServer(('', 80), MRCHandler)
		print "\n\n"+MRCHandler.prginfo+"\n"
		print "Server STARTED.\n"
		print "Waiting for connections (ctrl+c to exit)...\n\n"
		server.serve_forever()
	
	except KeyboardInterrupt:
		print ' => Shutting down server!'
		server.socket.close()
	
	except Exception, err:
		self.send_error(500,'Unrecoverable error: %s Server closed.' % str(err))
		server.socket.close()

if __name__ == '__main__':
	main()

Proposta Antonio Vallone

Vorrei proporre un esercizio di lettura che ho assegnato recentemente ad un compito in classe ad una seconda liceo. Riporto la versione in c perchè è il linguaggio utilizzato e la versione in Python per farne un confronto. Il programma riduce ai minimi termini una frazione.

C

#include <stdio.h>

int main(){
int n=12;
int d=18;	

int i=2;
while(i<n){
   if(n%i==0 && d%i==0) {
	n=n/i;
	d=d/i;
   }
   else
	i=i+1;	
}
printf(" %d\n",n);
printf("---\n");
printf(" %d\n",d);
}

Python


n=12
d=18
i=2
while i<n:
     if n%i==0 and d%i==0:
	  n=n/i
	  d=d/i
     else:
	  i=i+1;	

print n
printf "---"
printf d

Esercizio 11

Prodotto tra polinomi con algoritmo ricorsivo

def moltiplicaPolinomiRicorsivo(p, q, r, n):
  if n==1:
    r.extend([p[0] * q[0]])
    return r
  else:
    #Separa i due polinomi p(x) e q(x) in parte sinistra e in parte destra
    ps=p[0:int(n/2)]
    pd=p[int(n/2):int(n+1)]
    qs=q[0:int(n/2)]
    qd=q[int(n/2):int(n+1)]
    
    rs=[]
    rd=[]
    rm=[]
    rmsd=[]
    
    psd=[(ps[i] + pd[i]) for i in range(int(n/2))]
    qsd=[(qs[i] + qd[i]) for i in range(int(n/2))]
    
    #Il valore del prodotto e' r=x^n * rs + x^(n/2)[rmsd - rd - rs] + rd
    moltiplicaPolinomiRicorsivo(ps, qs, rs, n/2) 
    moltiplicaPolinomiRicorsivo(pd, qd, rd, n/2)
    moltiplicaPolinomiRicorsivo(psd, qsd, rm, n/2)
    
    rmsd=[(rm[i] - rd[i] - rs[i]) for i in range(int(2*n/2 -1))]
    
    #Il caso n=2 e' composto di soli tre coefficienti
    if n==2:
      r.extend(rs)
      r.extend(rmsd)
      r.extend(rd)
    else:
      #Ricombino rs, rmsd e rd per ottenere r. Si tenga presente che l'ultimo elemento di rs e 
      #il primo di rmsd hanno lo stesso grado. Lo stesso vale per l'ultimo elemento di rmsd e
      #il primo di rd 
      r.extend(rs[0:int(2*n/2-2)])
      r.extend([rs[int(2*n/2-2)] + rmsd[0]])
      r.extend(rmsd[1:int(2*n/2-2)])
      r.extend([rmsd[int(2*n/2-2)] + rd[0]])
      r.extend(rd[1:int(2*n/2-1)])
  
#Si fa l'assunzione che il numero dei coefficienti del polinomio sia una potenza di 2. Se cosi'
#non fosse si riempia di zeri le liste che costituiscono p(x) e q(x) fino al piu' piccolo valore
#che costituisce una potenza di 2. Altra assunzione i coefficienti dei polinomi dovrebbero essere
#inseriti in modo che nelle posizioni con indice inferiore delle liste ci siano i coefficiente delle
#potenze di grado superiore.  Ad esempio 1x^3+2x^2+3x+4 dovrebbe essere inserito in forma di lista
#come [1, 2, 3, 4]     
if __name__=="__main__":
  #Valori di test
  #n=2
  #p=[4, 5]
  #q=[3, 2]
  #n=4
  #p=[0, 0, 0, 5]
  #q=[0, 0, 0, 2]
  #p=[0, 1, 0, -1]
  #q=[0, 1, 0,  1]
  n=8
  p=[0, 0, 0, 0, 1, 2, 3, 4]
  q=[0, 0, 0, 0, 5, 6, 7, 8]
  
  r=[]
  
  moltiplicaPolinomiRicorsivo(p, q, r, n)
  print("I coefficienti del polinomio prodotto sono ", r)

Ho "semplicemente" messo in codice Python l'algoritmo di moltiplicazione rapida tra polinomi che si trova in forma di pseudocodice a pagina 229 del libro Algoritmi e Strutture Dati di Bertossi, Montresor. Come già sottolineavo nei commenti all'esercizio 5 il passaggio tra pseudocodice e codice reale nasconde delle insidie che a mio parere sono a volte paragonabili alla "individuazione" dell'algoritmo che permette di risolvere il problema in esame. Altro mio grande problema è effettuare il debug di un algoritmo ricorsivo. A me riesce molto difficile perchè se uso il medoto di stampare delle tracce nel programma succede che finisco per non capire in che punto del programma avvenga la stampa in quanto anche questa viene stampata ricorsivamamte. Analogamente con il procedimento di debug passo passo tramite ambiente integrato. Non sempre mi trovo a capire lo stack delle chiamate per cui alla fine ci rinuncio e preferisco effettuare un debug su carta con una dimensione dell'input del problema che riesco ad affrontare.--Savino (discussioni) 05:58, 25 mar 2015 (CET)

Giovanni

Come primo esercizio, per prendere confidenza con Python, ho deciso di giocare all'impiccato. Nomen omen

import random

#Dizionario delle parole da indovinare (si può pensare di collegarlo al dizionario openoffice, per esempio)
parole =["casa","mattone","biciletta","materasso","scrivania","campanello","cuscino","stendibiancheria","monetine"]

#Scelgo una parola random
obiettivo = random.choice(parole)

#Creo l'elenco delle lettera
elenco_lettere = set(obiettivo)

#creo la parola corrente inizializzando i valori
corrente = list(obiettivo)
for i in range(0,len(corrente)):
		corrente[i] ="*"
		
#stabilisco il numero di tentativi
tentativi = 5

#finche' ho tentativi disponibili e non ho indovinato
while tentativi > 0 and obiettivo !=  ''.join(corrente):
	
	#inserisco una lettera
	scelta = raw_input('LETTERA: ')
	
	#se la lettera e' presente nella parola, aggiorno la parola corrente
	if scelta in elenco_lettere:
		for i in range(0,len(obiettivo)):
			#costruisco la parola corrente
			if scelta == obiettivo[i]:
				corrente[i] = scelta
		#visualizzo lo stato attuale della parola
		print "      ", ''.join(corrente)
	#altrimenti diminuisco i tentativi
	else:
		print "Doh! Lettera non presente, ti rimangono ", tentativi, "tentativi"
		tentativi -= 1
		
#se all'uscita dal ciclo mi sono rimasti tentativi ho vinto, altrimenti ho perso
if tentativi > 0:
	print "HAI VINTO"
else:
	print "RITENTA"

Esercizio proposto da Raoul

Gli odierni computer su cui sono eseguiti i programmi, benché possano eseguire istruzioni in modo molto rapido e siano dotati di memoria in cui registrare le informazioni, tempo e spazio non sono risorse illimitate. Gli informatici devono essere consapevoli delle risorse consumate da un dato algoritmo e se esiste una pluralità di algoritmi che svolgono lo stesso compito, devono preferire quello che usa meno risorse. Efficienza è il termine usato per descrivere l'uso attento delle risorse da parte di un algoritmo e una delle caratteristiche desiderabili di un algoritmo. Grazie ai rapidi progressi della tecnologia i computer di oggi hanno maggiore capacità di memoria ed eseguono istruzioni in modo molto più rapido rispetto a quelli di pochi anni fa. L'efficienza degli algoritmi sembra un aspetto secondario: basta attendere la prossima generazione tecnologica e non sarà più cosi importante considerare il tempo o lo spazio richiesto. C'è del vero in questa considerazione, ma all'aumentare della capacità di memoria e della velocità di elaborazione, le persone trovano problemi più complessi da risolvere, perciò i limiti delle risorse dei computer vengono continuamente spinti in avanti. Inoltre esistono algoritmi che consumano molte risorse e che non potranno mai essere considerati di utilità pratica indipendentemente dai progressi tecnologici che si verificheranno.

Alla luce di queste riflessione è evidente che la progettazione di un percorso didattico volto all'apprendimento del concetto di algoritmo è significativo e copre diversi aspetti pratici e teorici per svariate ragioni:

- le molteplici applicazioni pratiche forniscono una motivazione chiara ed un vasto insieme di esempi;

- l'algoritmo e le sue proprietà sono sufficientemente semplici da consentire una trattazione completa e rigorosa;

- ha applicazioni sia di tipo non numerico che di tipo numerico, consentendo un collegamento interdisciplinare con il parallelo insegnamento di Matematica;

- l'implementazione degli algoritmi in programmi può essere affidata come esercizio guidato agli studenti stessi, mostrando come gli aspetti teorici (matematici) e quelli pratici (programmazione) dell'informatica siano distinti ma fortemente intrecciati.

L'esempio seguente mostra l'implementazione in Python 3 dell'algoritmo per la moltiplicazione di due matrici A e B: A di dimensione (m x p) e B di dimensione (p x m). Il risultato è una matrice C di dimensione (m x n). Successivamente presento una variante che propone una gestione della memoria ottimizzata (minore complessità nella gestione degli indirizzi di memoria e miglioramento dell'accesso agli elementi delle strutture memorizzate da parte del sistema operativo), invece di utilizzare due matrici bidimensionale, allochiamo vettori unidimensionali e memorizziamo le nostre strutture matriciali per riga.

import sys
import random

def print_matrix(msg, matrix, row, column):
    print(msg, row, column)
    for r in matrix:
        print(r)
    print('\n')

def mul_matrix(a_row, a_column, b_column):

    rng = random.Random()
    
    a_matrix = [[0 for i in range(0, a_column)] for j in range(0, a_row)]
    for i in range(a_row):
        for j in range(a_column):
            a_matrix[i][j] = rng.randint(1, 10)
    
    print_matrix('A: ', a_matrix, a_row, a_column)
    
    
    b_matrix = [[0 for i in range(0, b_column)] for j in range(0, a_column)]
    for i in range(a_column):
        for j in range(b_column):
            b_matrix[i][j] = rng.randint(1, 10)
    
    print_matrix('B: ', b_matrix, a_column, b_column)
       
    c_matrix = [[0 for i in range(0, b_column)] for j in range(0, a_row)]
    for i in range(a_row):
        for j in range(b_column):
            for k in range(a_column):
                c_matrix[i][j] = c_matrix[i][j] + (a_matrix[i][k] * b_matrix[k][j])
    
    print_matrix('C: ', b_matrix, a_row, b_column)

if __name__ == "__main__":
    print('Inserisci il numero di righe di A: ')
    a_row = int(input())
    
    print('Inserisci il numero di colonne di A: ')
    a_column = int(input())
    
    print('Inserisci il numero di righe di B: ')
    b_row = int(input())
    
    print('Inserisci il numero di colonne di B: ')
    b_column = int(input())
    
    if a_column != b_row:
        print('Le dimensioni delle matrici non sono compatibili: ')
        sys.exit(0)
     
    mul_matrix(a_row, a_column, b_column);

Variante con vettori unidimensionali

import sys
import random

def print_vector(msg, vector, row, column):
    len_vector = row * column
    print(msg, len_vector)
    for i in range(row):
        begin = i * column
        end = begin + column
        print(vector[begin:end])
    print('\n')
    

def mul_vector(a_row, a_column, b_column):

    rng = random.Random()
    
    a_vector = [0 for k in range(0, a_row * a_column)]
    for i in range(a_row):
        for j in range(a_column):
            k = (i * a_column) + j
            a_vector[k] = rng.randint(1, 10)
            
   
    print_vector('A: ', a_vector, a_row, a_column)    
       
    b_vector = [0 for k in range(0, a_column * b_column)]
    for i in range(a_column):
        for j in range(b_column):
            k = (i * b_column) + j
            b_vector[k] = rng.randint(1, 10)
            
    print_vector('B: ', b_vector, a_column, b_column)
    
    c_vector = [0 for k in range(0, a_row * b_column)]
    for i in range(a_row):
        for j in range(b_column):
            cdx = (i * b_column) + j
            for k in range(a_column):            
                c_vector[cdx] = c_vector[cdx] + (a_vector[(i * a_column) + k] * b_vector[(k * b_column) + j])
    
    print_vector('C: ', c_vector, a_row, b_column)

    
if __name__ == "__main__":
    print('Inserisci il numero di righe di A: ')
    a_row = int(input())
    
    print('Inserisci il numero di colonne di A: ')
    a_column = int(input())
    
    print('Inserisci il numero di righe di B: ')
    b_row = int(input())
    
    print('Inserisci il numero di colonne di B: ')
    b_column = int(input())
    
    if a_column != b_row:
        print('Le dimensioni delle matrici non sono compatibili: ')
        sys.exit(0)
     
    mul_vector(a_row, a_column, b_column);

Esercizio proposto da Samuele

--Samuele.cattabriga (discussioni) 10:05, 27 mar 2015 (CET) )

Ispirato da un piccolo esempio sviluppato in classe durante il tirocinio, propongo un esercizio risolto un questo caso in maniera imperativa "semplice", ma che potrebbe essere molto più significativamente realizzato ad oggetti.

#triangolo.py
import math

def pitagora(a, b):
    return math.sqrt(a**2+b**2)

def isPitagorical(lista):
    lista.sort() 
    return lista[2]==pitagora(lista[0], lista[1])
   
def isTriangle(lati):
    lati.sort()
    return (lati[2]<lati[0]+lati[1])
    
def tipoTriangle(lati):
    sentence=""
    if lati[0]!=lati[1]!=lati[2]:
        sentence+="scaleno"
    elif lati[0]==lati[1]==lati[2]:
        sentence+="equilatero"
    else: sentence+="isoscele"
    if isPitagorical(segmenti): 
        sentence+=" e rettangolo"
    return sentence
            
def perimetro(lati):
    return lati[0]+lati[1]+lati[2]
    
def area(lati):
    p=perimetro(lati)/2
    return math.sqrt(p*(p-lati[0])*(p-lati[1])*(p-lati[2]))

if __name__=="__main__":
    a,b,c=raw_input("Inserisci tre valori: ").split()
    a,b,c=float(a), float(b), float(c)
    segmenti=[a,b,c]
    if isTriangle(segmenti):
        print ("L'insieme di valori inseriti costituisce un possibile triangolo {} di perimetro {} e area {}".format(tipoTriangle(segmenti), perimetro(segmenti), area(segmenti)))

    else: 
        print ("Non e' possibile formare un triangolo con i valori inseriti") 

Il programma, dati tre valori in input, verifica se questi possano o meno costituire un triangolo di lati pari a tali valori; qualora questo sia possibile, esso definisce il tipo di triangolo in esame e ne calcola perimetro ed area.

Per eseguire quanto descritto, nel codice si ricorre ad alcune funzioni internamente definite

  • def isTriangle(lati):
        lati.sort()
        return (lati[2]<lati[0]+lati[1])
    

    che, per verificare l'esistenza del triangolo, sfrutta la proprietà secondo cui la somma dei cateti sia sempre maggiore dell'ipotenusa. Al suo interno, viene richiamato l'ordinamento di default di Python, assumendo che non ci interessi l'efficienza del programma nell'ordinamento di tre numeri (necessario per ordinare la lista dei lati in input);

  •      
    def tipoTriangle(lati):
        sentence=""
        if lati[0]!=lati[1]!=lati[2]:
            sentence+="scaleno"
        elif lati[0]==lati[1]==lati[2]:
            sentence+="equilatero"
        else: sentence+="isoscele"
        if isPitagorical(segmenti):
            sentence+=" e rettangolo"
        return sentence
    

    che determina il tipo di triangolo esaminandone i lati e la loro correlazione e sfruttando il teorema di Pitagora

    def pitagora(a, b):
        return math.sqrt(a**2+b**2)
     
    def isPitagorical(lista):
        lista.sort()
        return lista[2]==pitagora(lista[0], lista[1])
    

    (l'uso della radice quadrata è subordinato all'inclusione del modulo math di Python);

  • def perimetro(lati):
        return lati[0]+lati[1]+lati[2]
         
    def area(lati):
        p=perimetro(lati)/2
        return math.sqrt(p*(p-lati[0])*(p-lati[1])*(p-lati[2]))
    

    che calcolano area e perimetro. La seconda funzione, in particolare, non compie assunzioni sulla forma del triangolo ed è applicabile per ogni tipologia, essendo basata sulla Formula di Erone

Esercizio 12

Propongo gli esercizi di un'esercitazione di ripasso di Laboratorio sulle stringhe che ho somministrato ai miei alunni di terza IT. In seguito riporto il mio svolgimento in linguaggio Python.

Testo 1: scrivere un programma che, richiesti in input una stringa e due caratteri, sostituisca all'interno della stringa tutte le occorrenze del primo carattere con il secondo.

stringa = input("Inserisci una stringa: ")
car1 = input("inserisci un carattere: ")
car2 = input("Inserisci un carattere: ")

stringa = stringa.replace(car1,car2)
print(stringa) 

Testo 2: presa in input una stringa ristamparla con tutte le lettere maiuscole.

stringa = input("Inserisci una stringa: ")
stringa = stringa.upper()
print(stringa)

Testo 3: prese in input 6 stringhe, ordinarle in ordine alfabetico e indicare quale stringa è più lunga e quale più corta.

stringhe = [input("Inserisci stringa numero " + str(i)+ ": ") for i in range(1,7)]
stringhe.sort(key=str.lower)
print(stringhe)

stringa_min = min(stringhe, key = len)
stringa_max = max(stringhe, key = len)

print("La stringa piu' lunga e': " + stringa_max)
print("La stringa piu' corta e': " + stringa_min)

Testo 4: prese in input due stringhe, creare una terza stringa contenente i caratteri alternati delle due precedenti.

stringa1 = input("Inserisci stringa una stringa: ")
stringa2 = input("Inserisci stringa una stringa: ")

len_max = (len(stringa1) if len(stringa1) > len(stringa2) else len(stringa2))

stringa3 = ""
for i in range(0, len_max):
    stringa3 +=  (stringa1[i] if len(stringa1) > i else "")
    stringa3 +=  (stringa2[i] if len(stringa2) > i else "")

print(stringa3)

Testo 5: prendere in input 2 stringhe s1 e s2, stamparle e stampare le loro lunghezze l1 e l2.

  • Se le due lunghezze sono uguali, concatenare le due stringhe e stampare la nuova stringa e la sua lunghezza.
  • Se l1 è maggiore di l2, stampare la stringa che viene prima in ordine alfabetico
  • Se l1 è minore di l2, creare una terza stringa che contenga il contenuto della stringa più lunga e stamparla.
  • Contare il numero di vocali presenti nelle due stringhe, salvarle in una nuova stringa e stampare quest'ultima al contrario.
stringa1 = input("Inserisci stringa una stringa: ")
stringa2 = input("Inserisci stringa una stringa: ")

print("Prima stringa di lunghezza " + str(len(stringa1)) + ": " + stringa1)
print("Seconda stringa di lunghezza " + str(len(stringa2)) + ": " + stringa2)

if(len(stringa1) == len(stringa2)):
    stringa3 = stringa1 + " " + stringa2
    print("Nuova stringa di lunghezza " + str(len(stringa3)) + ": " + stringa3)
elif (len(stringa1) > len(stringa2)):
    if stringa1 > stringa2:
        print(stringa2)
    else:
        print(stringa1)
else:
    stringa3 = stringa2
    print(stringa3)

num_vocali_stringa1 = sum(1 for x in stringa1 if(x.upper() in "AEIOU"))
num_vocali_stringa2 = sum(1 for x in stringa2 if(x.upper() in "AEIOU"))

stringa3 = ""
for i in range(0,len(stringa1)):
     if(stringa1[i].upper() in "AEIOU"):
         stringa3 += stringa1[i]
for i in range(0,len(stringa2)):
     if(stringa2[i].upper() in "AEIOU"):
         stringa3 += stringa2[i]
print("Numero di vocali nella prima stringa: " + str(num_vocali_stringa1))
print("Numero di vocali nella seconda stringa: " + str(num_vocali_stringa2))
print(stringa3[::-1])

Elena (discussioni) 22:00, 07 apr 2015 (CET) )

Esercizio 13 'Reti Combinatorie' di Raoul

Come alcuni di voi sanno, da un pò di tempo sono impegnato nella lettura del libro "The Elements of Computing Systems" edito da MIT Press di Noam Nisan e Shimon Schocken. Ormai alla fine del quinto capitolo ho cominciato a riflettere sulla possibilità di inserire alcune attività, volte alla comprensione dell'architettura di un computer, nella scaletta di alcune lezioni pomeridiane che mi accingo a tenere presso la scuola in cui effettuo il tirocinio. Sebbene i contenuti proposti esulino dal programma di quarta liceo delle scienze applicate, alcuni studenti curiosi hanno deciso di aderire a questa iniziativa. L'idea è quella di semplificare molto rispetto a quanto proposto nel sopracitato libro, ma nel contempo di non rinunciare ai concetti fondamentali sui quali si fondano i moderni computer. Perciò ho selezionato alcuni strumenti che credo siano utili per comprendere il funzionamento delle logiche programmabili: in particolare di una semplice rete combinatoria come può essere l'unita aritmetica logica presentata nel libro. Per rappresentare graficamente le reti e simularne il comportamento ho utilizzato una applicazione con licenza proprietaria gratuita (Digital Works) e reperibile al seguente link: www.mecanique.co.uk/shop/index.php?route=product/category&path=89, naturalmente altre soluzioni con licenze libere sono equivalenti. Successivamente allo sviluppo grafico, proprio come procedono Nisan e Schocken, ho deciso di realizzare tramite un linguaggio di programmazione orientato agli oggetti, le funzioni logiche di base: Not, And, Or, NAnd, Nor da cui mediante composizione è possibile realizzare altre funzione più complesse. Di seguito mostro una serie di classi che già permettono di realizzare reti più sofisticate. Come esempio di partenza è stata realizzata la funzione XOR. Successivamente gli studenti potranno migliorare il codice qui proposto ed aggiungere nuove classi che simulino gli elementi che via via saranno studiati...

#-------------------------------------------------------------------------------
# Name:        SimDigitalCircuit
# Purpose:
#
# Author:      Raoul Gioia
#
# Created:     09/04/2015
# Copyright:   (c) Raoul Gioia 2015
# Licence:     <GPL>
#-------------------------------------------------------------------------------

#Classe base astratta che definisce una generica porta logica
class PortaLogica:

    def __init__(self, nome):
        self.nome = nome
        self.inputs = None
        self.output = None

    def getNome(self):
        return self.nome

    def setInputs(self, inputs):
        self.inputs = inputs

    def getInputs(self, idxPin):
        return int(self.inputs[idxPin] if type(self.inputs) == type([]) else self.inputs)

    def getOutput(self):
        self.output = self.funzioneLogica()
        return self.output

#Classe che deriva da 'PortaLogica' e definisce una porta logica con un solo pin di input
class Porta1Pin(PortaLogica):

    def __init__(self, nome):
        PortaLogica.__init__(self, nome)

        self.pin = None

    def getPin(self):
        if self.pin == None:
            return self.getInputs(0)
        else:
            return self.pin.getFrom().getOutput()

    def collegaPin(self, valore):
        if self.pin == None:
            self.pin = valore
        else:
            print("Impossibile creare la connessione: Nessun Pin libero!!!")

    def __str__(self):
        return "pin = {0} -> output = {2}".format(self.inputs, self.output)

#Classe che deriva da 'PortaLogica' e definisce una porta logica con due pin di input
class Porta2Pin(PortaLogica):

    def __init__(self, nome):
        PortaLogica.__init__(self, nome)

        self.pin0 = None
        self.pin1 = None

    def getPin0(self):
        if self.pin0 == None:
            return self.getInputs(0)
        else:
            return self.pin0.getPartenza().getOutput()

    def getPin1(self):
        if self.pin1 == None:
            return self.getInputs(1)
        else:
            return self.pin1.getPartenza().getOutput()

    def collegaPin(self, valore):
        if self.pin0 == None:
            self.pin0 = valore
        elif self.pin1 == None:
            self.pin1 = valore
        else:
            print("Impossibile creare la connessione: Nessun Pin libero!!!")

    def __str__(self):
        return "pin0 = {0}, pin1 = {1} -> output = {2}".format(self.inputs[0], self.inputs[1], self.output)

#Implementazione del connettore di porte
class Connettore:

    def __init__(self, partenza, arrivo):
        self.partenza = partenza
        self.arrivo = arrivo


    def connetti(self):
        self.arrivo.collegaPin(self)

    def getPartenza(self):
        return self.partenza

    def getarrivo(self):
        return self.arrivo

#Implementazione delle porte logiche di base Not, And, Or
class Not(Porta1Pin):

    def __init__(self, nome):
        Porta1Pin.__init__(self, nome)

    def funzioneLogica(self):
        pin = self.getPin()
        return 0 if (pin == 1) else 1

class And(Porta2Pin):

    def __init__(self, nome):
        Porta2Pin.__init__(self, nome)

    def funzioneLogica(self):
        pin0 = self.getPin0()
        pin1 = self.getPin1()
        return 1 if (pin0 == 1 and pin1 == 1) else 0

class Or(Porta2Pin):

    def __init__(self, nome):
        Porta2Pin.__init__(self, nome)

    def funzioneLogica(self):
        pin0 = self.getPin0()
        pin1 = self.getPin1()
        return 1 if (pin0 == 1 or pin1 == 1) else 0

class NAnd(Porta2Pin):

    def __init__(self, nome):
        Porta2Pin.__init__(self, nome)

    def funzioneLogica(self):
        pin0 = self.getPin0()
        pin1 = self.getPin1()
        return 0 if (pin0 == 1 and pin1 == 1) else 1

class NOr(Porta2Pin):

    def __init__(self, nome):
        Porta2Pin.__init__(self, nome)

    def funzioneLogica(self):
        pin0 = self.getPin0()
        pin1 = self.getPin1()
        return 0 if (pin0 == 1 or pin1 == 1) else 1

class Xor(Porta2Pin):

    def __init__(self, nome):
        Porta2Pin.__init__(self, nome)
        self.A1 = And("A1")
        self.A2 = And("A2")
        self.N1 = Not("N1")
        self.N2 = Not("N2")
        self.O1 = Or("O1")

        self.c0 = Connettore(self.N1, self.A1)
        self.c0.connetti()
        self.c1 = Connettore(self.N2, self.A2)
        self.c1.connetti()

        self.c2 = Connettore(self.A1, self.O1)
        self.c2.connetti()
        self.c3 = Connettore(self.A2, self.O1)
        self.c3.connetti()

    def funzioneLogica(self):
        return self.O1.getOutput()

    def setInputs(self, inputs):
        self.inputs = inputs
        self.A1.setInputs(inputs[0])
        self.N2.setInputs(inputs[0])
        self.A2.setInputs(inputs[1])
        self.N1.setInputs(inputs[1])

def main():
    X1 = Xor('X1')

    X1.setInputs(['0','0'])
    X1.getOutput()
    print(X1)
    
    X1.setInputs(['0','1'])
    X1.getOutput()
    print(X1)
    
    X1.setInputs(['1','0'])
    X1.getOutput()
    print(X1)
    
    X1.setInputs(['1','1'])
    X1.getOutput()
    print(X1)
    

if __name__ == '__main__':
    main()

Esercizio 14 Gioco Scopa 1.0 di fabrizio

Nel tentativo di imparare e il Pythonese, rispolverare la programmazione e sviluppare un attrattore fatale ho provato a implementare un videogioco. Fatto un pò di esperimenti il codice è bruttino, il gioco non completo. Ho provato a usare l'italiano per magari farlo vedere ai ragazzi, cattiva idea è innaturale. di seguito il codice

'''
Created on Apr 27, 2015
Scopa v1.0
@author: fabrizio
'''

from random import randint
#definisce la classe carta
class Carta: 
    Pali = ["X", "Denari", "Bastoni", "Coppe", "Spade"] 
    Valori = ["X", "Asso", "2", "3", "4", "5", "6", "7", "Donna", "Fante", "Re"] 

    def __init__(self, Palo, Valore): 
        self.Palo = Palo 
        self.Valore = Valore 

    def __str__(self): 
        return (self.Valori[self.Valore] + " di " +  self.Pali[self.Palo]) 

#definisce la classe Mazzo, gestita come stack
class Mazzo: 
    #crea un mazzo Napoletano di 40 carte
    def __init__(self): 
        self.carte = [] 
        for P in range(1,5): 
            for V in range(1,11): 
                self.inserisci(Carta(P, V))
        self.mischia()

    def __str__(self):
        lun = len(self.carte)
        st = ""
        for i in range(lun):
            st +=  str(self.carte[i]) + ", "
            if (i+1) % 10 == 0:
                st += "\n"
        return st[:len(st)-2]
    
    def mischia(self):
        lun = len(self.carte)
        for i in range (lun):
            j = randint(0,lun-1)
            self.carte[i], self.carte[j] = self.carte[j], self.carte[i]
    
    def pesca(self):
        return self.carte.pop()
    
    def inserisci(self,carta):
        self.carte.append(carta)

#mazzetto delle carte prese, inizializzato a lista vuota
#sottoclasse di Mazzo    
class Mazzetto(Mazzo):
    def __init__(self):
        self.carte = [] 

#le carte sul tavolo, definisco solo init e str
#non puo essere stack ma  lista      
class Board():
    def __init__(self, mazzo):
        self.board = []
        for i in range(4):
            self.board.append(mazzo.pesca())
    
    def __str__(self):
        st = " "
        for x in self.board:
            st += str(x) + ",  "
        return "\t\------------- BOARD:   "+ st[:len(st)-3]+ "----------------"

        
#classe giocatore generico        
class Giocatore:
    
    def __init__(self,nome):
        self.nome = nome
        self.punti = 0
        self.mano = []
        self.denari = Mazzetto()
        self.mazzetto = Mazzetto()
    
    def __str__(self):
        st = ""
        for x in self.mano:
            st += str(x) + ",  "
        return self.nome +"\n" + st[:len(st)-3]
    
    def punto(self):
        self.punti +=1

#pesca 3 carte dal mazzo
    def servi_mano(self,mazzo):
        for i in range(3):
            self.mano.append(mazzo.pesca())
    
    def gioca(self,board):
        # polimorfismo a seconda del tipo di giocatore
        s = self.scegli(board)
        ho_preso = False
        print("Carta giocata :  " + str(s))
        
        #se la carta giocata è a terra le prende, altrimenti
        #resta sul board
        for x in board.board:
            if s.Valore == x.Valore:
                board.board.remove(x)
                self.mazzetto.inserisci(x)
                self.mazzetto.inserisci(s)
                ho_preso = True
                print("Hai preso: %s, %s   " %(x,s))
                break
        else:
            board.board.append(s)
        
        print(board)
        self.mano.remove(s)        
        return ho_preso  

#sottoclasse giocatare umano, scelta input utente                 
class Giocatore_Umano(Giocatore):
    def scegli(self,board):
        cond = True
        ck = []
        while cond:
            if len(self.mano) == 3:
                s = input("1 -- 2 -- 3:   ")
                ck = ['1','2','3']
            elif len(self.mano) == 2:
                s = input("1 -- 2:   ")
                ck = ['1','2']
            else:
                s = input("1   (Scelta Obbligata)  ")
                ck = ['1']
            if s  in ck:
                cond = False
            else:
                print("Errore di inserimento, ripeti")
        return self.mano[int(s)-1]

#sottoclasse giocatare umano, scelta IA!!!          
class Giocatore_Com(Giocatore): 
    def scegli(self, board):
        s = None
        for x in self.mano:
            for y in board.board:
                if x.Valore == y.Valore:
                    return x
        else:
            s = self.mano[0]
        return s
                    
class Partita:
    #crea il mazzo, il board e 2 players
    def __init__(self):
        self.mazzo = Mazzo()
        self.board = Board(self.mazzo)
        self.giocatore1 = Giocatore_Umano("TU")
        self.giocatore2 = Giocatore_Com("Com")
        self.ultimo_a_prendere = 0
        print(self.board)
        self.mani()
        self.fine()
# le 6 mani della partita, dà carte       
    def mani(self):
        for i in range(6):
            self.giocatore1.servi_mano(self.mazzo)
            self.giocatore2.servi_mano(self.mazzo)
            self.turni()   

# Turno interno alla mano     
    def turni(self):
        for i in range (3):
            print(self.giocatore1)
            if self.giocatore1.gioca(self.board) : 
                self.ultimo_a_prendere = 1 
            
            print(self.giocatore2)
            if self.giocatore2.gioca(self.board):
                 self.ultimo_a_prendere = 2

    def  calcola_punti(self):
        #carte prese
        if len(self.giocatore1.mazzetto.carte)> len(self.giocatore2.mazzetto.carte):
            self.giocatore1.punto()
        elif len(self.giocatore1.mazzetto.carte)< len(self.giocatore2.mazzetto.carte):
            self.giocatore2.punto()
        
        #carte di denari  
        self.giocatore1.denari.carte = [x for x in self.giocatore1.mazzetto.carte if x.Palo == 1] 
        self.giocatore2.denari.carte = [x for x in self.giocatore2.mazzetto.carte if x.Palo == 1]     
       
        
        if len(self.giocatore1.denari.carte) > len(self.giocatore2.denari.carte):
            self.giocatore1.punto()
        elif len(self.giocatore1.denari.carte) < len(self.giocatore2.denari.carte):
            self.giocatore2.punto()
            
        #settebello 
        settebello = Carta(1,7)
        if settebello in self.giocatore1.denari.carte:
            self.giocatore1.punto()
        else:
            self.giocatore2.punto()
           
#l'ultimo che ha preso si prende le rimanenti       
    def fine(self):
        if self.ultimo_a_prendere ==1:
            self.giocatore1.mazzetto.carte.extend(self.board.board)
        else:
            self.giocatore2.mazzetto.carte.extend(self.board.board)
        
        self.calcola_punti()
        print('----------------------------------------------------------------------------------')
        print(self.giocatore1.nome)
        print("Carte:  %s" %len(self.giocatore1.mazzetto.carte))
        print(self.giocatore1.mazzetto)
        print("Denari:  %s" %len(self.giocatore1.denari.carte))
        print(self.giocatore1.denari)
        print("Punti: %s" %self.giocatore1.punti)
        
        print('----------------------------------------------------------------------------------')
        print(self.giocatore2.nome)
        print("Carte:  %s" %len(self.giocatore2.mazzetto.carte))
        print(self.giocatore2.mazzetto)
        print("Denari:  %s" %len(self.giocatore2.denari.carte))
        print(self.giocatore2.denari)
        print("Punti: %s" %self.giocatore2.punti)
        

if __name__ == "__main__":
    partita = Partita()


Esercizio 15 Comunicazione SPI con Arduino di Francesco

Siccome a lezione abbiamo visto Raspberry Pi e Arduino, di seguito mostro un esempio di comunicazione SPI tra Arduino Mega e un ADC, precisamente l' AD7195. Ovviamente non sarà in Python ma ogni tanto può tornare utile anche il vecchio e buon C/C++. Nell'esempio si utilizza l'ADC per prelevare due segnali analogici, e arduino "scrivera' sul monitor seriale" i valori letti.

Di seguito il codice

/*
AD7195 
CS:
SCLK
DIN
DOUT/DRY
*/

// the sensor communicates using SPI, so include the library:
#include <SPI.h>

#define SPICLOCK      52//sck  
#define DATAIN        50//MISO   
#define DATAOUT       51//MOSI  
#define SLAVESELECT   53//ss  

//SPI_CLOCK_DIV128 => 31,25kHz => T_MCLK = 32usec

#define T_MCLK 32          //usec


byte byte1; byte byte2; byte byte3; byte byte4;
// declare 3 bytes = 24 bits
// 4 byte per sapere di quale canale si tratta

// the setup function runs once when you press reset or power the board
void setup()
{
  Serial.begin(19200);

  pinMode(DATAIN, INPUT);
  pinMode(DATAOUT, OUTPUT);
  pinMode(SLAVESELECT,OUTPUT);
  
  
  SPI.begin();
  SPI.setBitOrder(MSBFIRST);
  SPI.setDataMode(SPI_MODE3);
  SPI.setClockDivider(SPI_CLOCK_DIV2);

  delay(1);  //TEMPO PER SET CONFIGURATION
  
  Serial.println("\n---------------LETTURA CONFIGURAZIONE-----------------");
  readconfig_AD7195();

  delay(1);

  Serial.println("\n---------------CAMBIO CONFIGURAZIONE-----------------");  
  set_config_AD7195();

  delay(1);
  Serial.println("\n---------------CONFIGURAZIONE ATTUALE---------------");
  readconfig_AD7195();
  
  delay(1);

//----------------------------------------------------------------

  //Esempio di lettura non continua
  digitalWrite(SLAVESELECT, LOW);
  
  for(int i=0; i<20;i++){
     SPI.transfer(B01011000);        //leggi nel communications register -> mode register
     while (digitalRead(DATAIN) == HIGH) 
       ;
     
     byte1 = SPI.transfer(0x00);
     byte2 = SPI.transfer(0x00);
     byte3 = SPI.transfer(0x00);
     byte4 = SPI.transfer(0x00);    //canale
     Serial.print("Lettura ");
     Serial.print(i,DEC);
     Serial.print(" ");
     stampa_value(byte1, byte2, byte3);
  }
  
  digitalWrite(SLAVESELECT, HIGH);
  delayMicroseconds(0.08);

//----------------------------------------------------------------  
  //Esempio di lettura continua
  digitalWrite(SLAVESELECT, LOW);
  SPI.transfer(B01011100);  //continuos reading
  
 
}

// the loop function runs over and over again forever
void loop()
{
  
   if (digitalRead(DATAIN) == LOW) {
     byte1 = SPI.transfer(0x00);
     byte2 = SPI.transfer(0x00);
     byte3 = SPI.transfer(0x00);
     byte4 = SPI.transfer(0x00);    //canale
     stampa_value(byte1, byte2, byte3);
     if( byte4 ==7 ){
       Serial.print("CANALE 4 ");
       Serial.println(byte4, BIN);
     }
     else
      if(byte4 ==6 ){
         Serial.print("CANALE 3 ");
         Serial.println(byte4, BIN);
      }
       else{
         Serial.print("----------ERRORE----------- ");
         Serial.println(byte4, BIN);
      }
  }
  
  
}



void reset_adc()
{
  digitalWrite(DATAOUT, HIGH);
  delayMicroseconds(40*T_MCLK);      //40 serial clock cycles
  digitalWrite(DATAOUT, LOW);
  delayMicroseconds(500);             //500 tempo dopo il reset
}

void set_config_AD7195()
{
  digitalWrite(SLAVESELECT, LOW);
  
  SPI.transfer(B00001000);        //scrivi nel communications register -> mode register
//SPI.transfer(B00111100);        //Single conversion mode.  
  SPI.transfer(B00011000);        //enable continuous read
  SPI.transfer(B00000000);          
  SPI.transfer(B00100000);        //Filter Word 32

  delay(1);

  SPI.transfer(B00010000);        //scrivi nel communications register -> configuration register
  SPI.transfer(B00000000);        //  
  SPI.transfer(B11000000);        //Abilitati AIN4 AIN3
  SPI.transfer(B00011000);        
  
  digitalWrite(SLAVESELECT, HIGH);
  
}

void readconfig_AD7195()
{
   digitalWrite(SLAVESELECT, LOW);

   //STATUS
   SPI.transfer(B01000000);        //leggi nel communications register -> status register
   byte1 = SPI.transfer(0x00);
   Serial.println("status register");
   Serial.println(byte1, BIN);

   //MODE
   SPI.transfer(B01001000);        //leggi nel communications register -> mode register
   byte1 = SPI.transfer(0x00);
   byte2 = SPI.transfer(0x00);
   byte3 = SPI.transfer(0x00);

   Serial.println("mode register");
   Serial.println(byte1, BIN);
   Serial.println(byte2, BIN);
   Serial.println(byte3, BIN);  

   //CONFIGURATION
   SPI.transfer(B01010000);        //leggi nel communications register -> configuration register
   byte1 = SPI.transfer(0x00);
   byte2 = SPI.transfer(0x00);
   byte3 = SPI.transfer(0x00);

   Serial.println("configuration register");  
   Serial.println(byte1, BIN);
   Serial.println(byte2, BIN);
   Serial.println(byte3, BIN);  

   digitalWrite(SLAVESELECT, HIGH);
}

void stampa_byte(byte byte1, byte byte2, byte byte3)
{
 Serial.println(byte1, BIN);
 Serial.println(byte2, BIN);
 Serial.println(byte3, BIN);
}


long stampa_value(byte byte1, byte byte2, byte byte3)
{
  long app = (long)byte1 << 16 | (long)byte2 << 8 | (long)byte3;
  Serial.print("VALORE LETTO: ");
  Serial.print(app);
  Serial.print("   in BIN: ");
  Serial.println(app, BIN);  
  
  return app;
}

Strumenti personali
Namespace

Varianti
Azioni
Navigazione
Strumenti