Difference between revisions of "Esempi didattici in Python"
m |
m |
||
(4 intermediate revisions by the same user not shown) | |||
Line 3: | Line 3: | ||
=== Divisori === | === Divisori === | ||
Esempio sui divisori. Il primo programma ha uno stile Pascal o C: | Esempio sui divisori. Il primo programma ha uno stile Pascal o C: | ||
− | + | <source lang=python> | |
#!/usr/bin/env python3 | #!/usr/bin/env python3 | ||
Line 36: | Line 36: | ||
Ma il Python ha anche il tipo insieme (set) che e' meglio indicato per questo esempio: | Ma il Python ha anche il tipo insieme (set) che e' meglio indicato per questo esempio: | ||
− | <source lang= | + | |
+ | <source lang=python> | ||
#!/usr/bin/env python3 | #!/usr/bin/env python3 | ||
Line 69: | Line 70: | ||
Lo stesso esempio con la Set Comprehension (come si traduce? si traduce?): | Lo stesso esempio con la Set Comprehension (come si traduce? si traduce?): | ||
− | <source lang= | + | |
+ | <source lang=python> | ||
#!/usr/bin/env python3 | #!/usr/bin/env python3 | ||
Line 95: | Line 97: | ||
Il metodo migliore per calcolare il massimo comun divisore e' l'algoritmo di Euclide: | Il metodo migliore per calcolare il massimo comun divisore e' l'algoritmo di Euclide: | ||
− | <source lang= | + | <source lang=python> |
def gcd(x, y): | def gcd(x, y): | ||
while True: | while True: | ||
Line 167: | Line 169: | ||
Ma le code e le pile possono venir viste anche come classi derivate della classe liste. | Ma le code e le pile possono venir viste anche come classi derivate della classe liste. | ||
La prima versione chiama i metodi della classe lista esplicitamente: | La prima versione chiama i metodi della classe lista esplicitamente: | ||
− | <source lang= | + | <source lang=python> |
class queue(list): | class queue(list): | ||
def __init__(self): | def __init__(self): | ||
Line 198: | Line 200: | ||
La seconda versione usa la ereditarieta': i metodi vengono richiamati semplicemente per nome, assumendo che si faccia riferimento alla prima definizione utile presente in una delle classi "ave" (anchestor). | La seconda versione usa la ereditarieta': i metodi vengono richiamati semplicemente per nome, assumendo che si faccia riferimento alla prima definizione utile presente in una delle classi "ave" (anchestor). | ||
− | <source lang= | + | <source lang=python> |
class queue(list): | class queue(list): | ||
def __init__(self): | def __init__(self): | ||
Line 233: | Line 235: | ||
Puo' essere interessante per introdurre gli insiemi in Python. La definizione appare naturale e descrittiva. | Puo' essere interessante per introdurre gli insiemi in Python. La definizione appare naturale e descrittiva. | ||
− | <source lang= | + | <source lang=python> |
def sieve(n): | def sieve(n): | ||
sv={x for x in range(1,n)} | sv={x for x in range(1,n)} | ||
Line 248: | Line 250: | ||
Sort per selezione: | Sort per selezione: | ||
− | <source lang= | + | <source lang=python> |
def selection_sort(v): | def selection_sort(v): | ||
for i in range(len(v)): | for i in range(len(v)): | ||
Line 257: | Line 259: | ||
Sort per inserzione: | Sort per inserzione: | ||
− | <source lang= | + | <source lang=python> |
def insertion_sort(v): | def insertion_sort(v): | ||
for i in range(1,len(v)): | for i in range(1,len(v)): | ||
Line 266: | Line 268: | ||
Bubblesort: | Bubblesort: | ||
− | <source lang= | + | <source lang=python> |
def bubblesort(v): | def bubblesort(v): | ||
for i in range(1,len(v)): | for i in range(1,len(v)): | ||
Line 275: | Line 277: | ||
Una implementazione del quicksort molto compatta e elegante si ottiene con la List Comprehension (copia il vettore come il metodo standard ''sorted''): | Una implementazione del quicksort molto compatta e elegante si ottiene con la List Comprehension (copia il vettore come il metodo standard ''sorted''): | ||
− | <source lang= | + | <source lang=python> |
def rqsorted(v): | def rqsorted(v): | ||
if v: | if v: | ||
Line 287: | Line 289: | ||
Il mergesort e' un po' piu' macchinoso. La prima versione prevede l'ordinamento del vettore stesso, vengono copiati temporaneamente i vettori parziali e poi le sequenze vengono reinserite nel vettore originale: | Il mergesort e' un po' piu' macchinoso. La prima versione prevede l'ordinamento del vettore stesso, vengono copiati temporaneamente i vettori parziali e poi le sequenze vengono reinserite nel vettore originale: | ||
− | <source lang= | + | <source lang=python> |
def merge(v1,v2): | def merge(v1,v2): | ||
v=[] | v=[] | ||
Line 311: | Line 313: | ||
La seconda versione del mergesort copia il vettore. Anche la funzione rmerge e' ricorsiva. | La seconda versione del mergesort copia il vettore. Anche la funzione rmerge e' ricorsiva. | ||
− | <source lang= | + | <source lang=python> |
def rmerge(v1,v2): | def rmerge(v1,v2): | ||
if not v1: | if not v1: |
Latest revision as of 10:48, 28 October 2019
Questa pagina contiene alcuni esempi didattici di codice Python
Divisori
Esempio sui divisori. Il primo programma ha uno stile Pascal o C:
#!/usr/bin/env python3
def divisori(x):
s=[]
for i in range(2,x):
if x%i == 0:
s.append(i)
return s;
def primo(x):
if divisori(x):
return False
else:
return True
def divisoriprimi(x):
s=[]
for i in divisori(x):
if (primo(i)):
s.append(i)
return s
if __name__ == '__main__':
n=int(input("dammi n "))
if primo(n):
print(n ,"e' primo")
else:
print("i divisori di ", n, "sono", divisori(n))
print("i divisori primi di ", n, "sono", divisoriprimi(n))
Ma il Python ha anche il tipo insieme (set) che e' meglio indicato per questo esempio:
#!/usr/bin/env python3
def divisori(x):
s=set()
for i in range(2,x):
if x%i == 0:
s.add(i)
return s;
def primo(x):
if divisori(x):
return False
else:
return True
def divisoriprimi(x):
s=set()
for i in divisori(x):
if (primo(i)):
s.add(i)
return s
if __name__ == '__main__':
n=int(input("dammi n "))
if primo(n):
print(n ,"e' primo")
else:
print("i divisori di ", n, "sono", divisori(n))
print("i divisori primi di ", n, "sono", divisoriprimi(n))
Lo stesso esempio con la Set Comprehension (come si traduce? si traduce?):
#!/usr/bin/env python3
def divisori(x):
return {y for y in range(2,x) if x%y == 0}
def primo(x):
return not divisori(x)
def divisoriprimi(x):
return {y for y in divisori(x) if primo(y)}
if __name__ == '__main__':
n=int(input("dammi n "))
if primo(n):
print(n ,"e' primo")
else:
print("i divisori di ", n, "sono", divisori(n))
print("i divisori primi di ", n, "sono", divisoriprimi(n))
Il primo e' piu' algoritmico, passo a passo, ma anche piu' contorto. Il secondo e' piu' elegante ma puo' apparire magico-misterioso.
Fattorizzazione, mcm e MCD
Il metodo migliore per calcolare il massimo comun divisore e' l'algoritmo di Euclide:
def gcd(x, y):
while True:
if x < y:
x, y = y, x
x -= y
if x == 0:
return y
def lcm(x, y):
return x * y // gcd(x, y)
Coda/Pila e programmazione a oggetti
Le code e le pile (queue e stack) possono essere implementate a partire dalle liste. Le funzioni enqueue/dequeue per le code e push/pop per le pile possono essere implementate cosi':
def enqueue(s,x):
s.append(x)
def dequeue(s):
return s.pop(0)
def push(s,x):
s.append(x)
def pop(s):
return s.pop()
Passando alla programmazione a oggetti, la versione migliore e' quella con un attributo nascosto "lista", perche' una coda ha una lista, non è una lista
class queue:
def __init__(self):
self._list=[]
def enqueue(self, x):
self._list.append(x)
def dequeue(self):
return self._list.pop(0)
def empty(self):
return not self._list
def head(self):
return self._list[0]
def __str__(self):
return str(self._list)
class stack:
def __init__(self):
self._list=[]
def push(self, x):
self._list.append(x)
def pop(self):
return self._list.pop()
def empty(self):
return not self._list
def __str__(self):
return str(self._list)
Il setaccio di Eratostene
Ai miei tempi si chiamava crivello!
Puo' essere interessante per introdurre gli insiemi in Python. La definizione appare naturale e descrittiva.
def sieve(n):
sv={x for x in range(1,n)}
for i in range(2,n//2):
if i in sv:
sv -= {x for x in range(2*i,n,i)}
return [x for x in range(n) if x in sv]
Ordinamento
Ecco una carrellata di funzioni per l'ordinamento... Le prime sono funzioni per l'ordinamento di vettori/liste sul posto, modificando la sequenza degli elementi.
Sort per selezione:
def 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]
Sort per inserzione:
def insertion_sort(v):
for i in range(1,len(v)):
for j in range(i):
if v[j] > v[i]:
v.insert(j, v.pop(i))
Bubblesort:
def bubblesort(v):
for i in range(1,len(v)):
for j in range(len(v)-i):
if v[j+1] < v[j]:
v[j+1],v[j]=v[j],v[j+1]
Una implementazione del quicksort molto compatta e elegante si ottiene con la List Comprehension (copia il vettore come il metodo standard sorted):
def rqsorted(v):
if v:
pivot=v[0]
lesser=[x for x in v[1:] if x <= pivot]
greater=[x for x in v[1:] if x > pivot]
return rqsorted(lesser) + [pivot] + rqsorted(greater)
else:
return []
Il mergesort e' un po' piu' macchinoso. La prima versione prevede l'ordinamento del vettore stesso, vengono copiati temporaneamente i vettori parziali e poi le sequenze vengono reinserite nel vettore originale:
def merge(v1,v2):
v=[]
while True:
if not v1:
return v+v2
elif not v2:
return v+v1
else:
if v1[0] < v2[0]:
v.append(v1.pop(0))
else:
v.append(v2.pop(0))
def mergesort(v):
lv=len(v)
ls=1;
while v[ls:]:
for i in range(0,lv,2*ls):
v[i:i+2*ls]=merge(v[i:i+ls],v[i+ls:i+2*ls])
ls *= 2
La seconda versione del mergesort copia il vettore. Anche la funzione rmerge e' ricorsiva.
def rmerge(v1,v2):
if not v1:
return v2
elif not v2:
return v1
elif v1[0] < v2[0]:
return v1[0:1]+rmerge(v1[1:],v2)
else:
return v2[0:1]+rmerge(v1,v2[1:])
def rmergesorted(v):
half=len(v)//2
if half == 0:
return v
else:
return rmerge(rmergesorted(v[:half]),rmergesorted(v[half:]))
Le definizioni delle funzioni merge e rmerge non sono state inserite nella definizione delle funzioni mergesort e rmergesorted (rispettivamente) perche' hanno una funzionalita' specifica di fusione di vettori ordinati e possono essere usate anche indipendentemente dal mergesort.