<file_sep>"""

ESERCIZIO 4

Ritorna un generatore che genera una sequenza contenente n stringhe, con queste 
regole:

- si suppone che il primo elemento della sequenza sia ad indice zero

se si sta generando una stringa:
- ad indice pari, la stringa deve contenere la lettera 'a'
- ad indice dispari, la stringa deve contenere la lettera 'b'
- ad indice divisibile per 3, la stringa deve contenere la lettera 'c'. 
  Tale lettera deve essere posta alla fine della stringa
  
Per esempio: 

list(gen(7)) 

deve dare

['ac','b','a','bc','a','b','ac'] 

Perchè

Indice    Stringa   Perchè
  0        'ac'     0 è pari e divisibile per 3
  1        'b'      1 è dispari 
  2        'a'      2 è pari
  3        'bc'     3 è dispari e divisibile per tre
  4        'a'      4 è pari
  5        'b'      5 è dispari 
  6        'ac'     6 è pari e divisibile per tre

Suggerimenti
- se volete usare i moduli, per vedere se un indice i è divisibile per m scrivete i % m == 0
- se avete letto la documentazione dei generatori, in alternativa ai moduli c'è 
  un'altro modo più furbo che potete usare
"""

def gen(n):
    
    # Scrivi qui



# INIZIO TEST - NON TOCCARE !!!


import types
assert isinstance(gen(0), types.GeneratorType) # verifico che pari ritorni un generatore e non una lista
            
assert list(gen(1)) == ['ac']
assert list(gen(2)) == ['ac','b'] 
assert list(gen(3)) == ['ac','b','a']
assert list(gen(4)) == ['ac','b','a','bc']
assert list(gen(5)) == ['ac','b','a','bc','a']
assert list(gen(6)) == ['ac','b','a','bc','a','b'] 
assert list(gen(7)) == ['ac','b','a','bc','a','b','ac'] 

# FINE TEST



<file_sep># Challenges 
## Challenge 1: Dataset personaggi storici
Starting csv:
![](images/wiki2.png)
Python Script Execution:
![](images/wiki1.png)
Results:
![](images/wiki0.png)<file_sep>
"""
Prende in input una lista con n numeri interi, e RITORNA una NUOVA lista che 
contiene n tuple ciascuna da due elementi. Ogni tupla contiene un numero 
preso dalla corrispondente posizione della lista di partenza, e il suo doppio. 

Per esempio:

doppie([ 5, 3, 8])

deve dare la nuova lista

[(5,10), (3,6), (8,16)]

"""
def doppie(lista):
    ret = []
    for elemento in lista:
        ret.append((elemento, elemento * 2))
    return ret

assert doppie([]) == []
assert doppie([3]) == [(3,6)]
assert doppie([2,7]) == [(2,4),(7,14)]
assert doppie([5,3,8]) == [(5,10), (3,6), (8,16)]

"""
Quando si analizza una frase, può essere utile processarla per rimuovere parole molto comuni, come per 
esempio gli articoli e le preposizioni: "un libro su Python" si può semplificare in "libro Python"

Le parole 'poco utili' vengono chiamate 'stopwords'. Questo processo è per esempio eseguito dai motori di ricerca per ridurre la complessità della stringa di input fornita dall'utente.


Implementare una funzione che prende una stringa e RITORNA la stringa di input senza le stopwords

SUGGERIMENTO 1: le stringhe in Python sono *immutabili* ! Per rimuovere le parole dovete creare una 
_nuova_ stringa a partire dalla stringa di partenza. 
 
SUGGERIMENTO 2: create una lista di parole così:
    lista = stringa.split(" ")
SUGGERIMENTO 3: operate le opportune trasformazioni su lista, e poi costruite la stringa da restituire con  
    " ".join(lista)
"""
def nostop(stringa, stopwords):
    lista = stringa.split(" ")
    for s in stopwords:
        if s in lista:
            lista.remove(s)
    return " ".join(lista)

assert nostop("un", ["un"]) == ""
assert nostop("un", []) == "un"
assert nostop("", []) == ""
assert nostop("", ["un"]) == ""
assert nostop("un libro", ["un"]) == "libro"
assert nostop("un libro su Python", ["un","su"]) == "libro Python"
assert nostop("un libro su Python per principianti", ["un","uno","il","su","per"]) == "libro Python principianti"

"""
Restituisce un dizionario con n coppie chiave-valore, dove le chiavi sono 
numeri interi da 1 a n incluso, e ad ogni chiave i è associata una lista di numeri 
da 1 a i

NOTA: le chiavi sono *numeri interi*, NON stringhe !!!!!

Esempio:

dilist(3)

deve dare:

 { 
    1:[1],
    2:[1,2],
    3:[1,2,3]
}


"""
def dilist(n):
    ret = dict()
    for i in range(1,n+1):
        lista = []
        for j in range(1,i+1):
            lista.append(j)
        ret[i] = lista
    return ret

assert dilist(0) == dict()
assert dilist(1) == {
                        1:[1]
                    }
assert dilist(2) == { 
                        1:[1],
                        2:[1,2]
                    }
assert dilist(3) == { 
                        1:[1],
                        2:[1,2],
                        3:[1,2,3]
                    }


import numpy as np

"""
RESTITUISCE una NUOVA matrice numpy che ha i numeri della matrice numpy 
di input ruotati di una colonna. 

Per ruotati intendiamo che:
- se un numero nella matrice di input si trova alla colonna j, nella matrice 
di output si troverà alla colonna j+1 nella stessa riga.
- Se un numero si trova nell'ultima colonna, nella matrice di output 
si troverà nella colonna zeresima.

Esempio:

Se abbiamo come input 

np.array(   [
                [0,1,0],
                [1,1,0],
                [0,0,0],
                [0,1,1]
            ])

Ci aspettiamo come output

np.array(   [
                [0,0,1],
                [0,1,1],
                [0,0,0],
                [1,0,1]
            ])

"""
def matrot(matrice):

    ret = np.zeros(matrice.shape)

    for i in range(matrice.shape[0]):
        ret[i,0] = matrice[i,-1]
        for j in range(1, matrice.shape[1]):
            ret[i,j] = matrice[i,j-1]
    return ret

m1 = np.array(  [
                    [1]
                ])
mat_attesa1 = np.array( [
                            [1]
                        ])

assert np.allclose(matrot(m1), mat_attesa1)

m2 = np.array(  [
                    [0,1]
                ])
mat_attesa2 = np.array( [
                            [1,0]
                        ])
assert np.allclose(matrot(m2), mat_attesa2)

m3 = np.array(  [
                    [0,1,0]
                ])
mat_attesa3 = np.array(
                [
                    [0,0,1]
                ])

assert np.allclose(matrot(m3), mat_attesa3)

m4 = np.array(  [ 
                    [0,1,0],
                    [1,1,0]
                ])
mat_attesa4 = np.array( [
                            [0,0,1],
                            [0,1,1]
                        ])
assert np.allclose(matrot(m4), mat_attesa4)


m5 = np.array([
                [0,1,0],
                [1,1,0],
                [0,0,0],
                [0,1,1]
              ])
mat_attesa5 = np.array([
                        [0,0,1],
                        [0,1,1],
                        [0,0,0],
                        [1,0,1]
                       ])
assert np.allclose(matrot(m5), mat_attesa5)
<file_sep>"""
     ESAME <NAME>ORITMI PYTHON   21 Giugno 2018


    - NON CAMBIATE IL NOME DELLE FUNZIONI
        - SE VOLETE POTETE AGGIUNGERE FUNZIONI VOSTRE, MA DOVETE SEMPRE
          RICHIAMARLE DALLE FUNZIONI CHE VI HO SCRITTO IO

    - QUANDO SCRIVO 'RITORNA', LA FUNZIONE DEVE _RITORNARE_ DEI VALORI,
      NON STAMPARLI CON LA PRINT !!!!

    - COMUNQUE, PRINT ADDIZIONALI DI DEBUG SONO CONCESSE

    - NON RIASSEGNATE I PARAMETRI IN INPUT! TRADOTTO: NON SCRIVETE _MAI_
      QUALCOSA DEL GENERE !!!

         def f(x):
            x = .....

    - OGNI FUNZIONE E' SEGUITA DAGLI ASSERT DI TEST, SE QUANDO ESEGUITE
      IL CODICE NON VEDETE ERRORI PROBABILMENTE IL CODICE E' GIUSTO
      (MA NON FIDATEVI TROPPO, I TEST NON SONO ESAUSTIVI !)


    - USARE EDITOR SPYDER. 
      - Per eseguire tutto lo script: F5
      - Per eseguire solo la linea corrente o la selezione:  F9

    *** DA FARE: IMPLEMENTATE QUESTE 4 FUNZIONI: ***
    
    - powers
    - onomat
    - flip
    - gen

"""



"""
ESERCIZIO 1


RITORNA un dizionario in cui le chiavi sono numeri interi da 1 a n inclusi, e i rispettivi 
valori sono i quadrati delle chiavi 

powers(3)

Ritorna

{
 1:1,
 2:4,
 3:9
}

"""
def powers(n):
    # scrivi qui
    d=dict()
    for i in range(1,n+1):
        d[i]=i**2
    return d


# INIZIO TEST - NON TOCCARE !!!
assert powers(1) == {1:1}
assert powers(2) == {
                        1:1,
                        2:4
                    }
assert powers(3) == {
                        1:1,
                        2:4,
                        3:9
                    }

assert powers(4) == {
                        1:1,
                        2:4,
                        3:9,
                        4:16
                    }
# FINE TEST


"""
ESERCIZIO 2 


INPUT: 
  - frase da arricchire
  - Il sentimento da usare, che è codificato come un valore numerico.
  - un dizionario di sentimenti, in cui si associa al codice numerico 
di ogni sentimento un dizionario contenente un espressione onomatopeica tipica per quel sentimento,
e la posizione in cui deve figurare all'interno di una frase. Le posizioni sono indicate come 'i'
per inizio e 'f' per fine.


OUTPUT

- La frase arricchita con l'espressione onomatopeica scelta in base al sentimento. L'espressione
  va aggiunta sempre prima o dopo la frase, e sempre separata da uno spazio. 



Per esempio

sentimenti = {
                1:  {
                        "espressione": "Gulp!",
                        "posizione": "i"
                    }
                2:  {
                        "espressione": "Sgaragulp !",
                        "posizione": "i"
                    }
                3:  {
                        "espressione": "Uff..",
                        "posizione": "f"
                    }
}


onomat("Ma quelli sono i bassotti!", 1, sentimenti) 

Deve tornare

"Gulp! Ma quelli sono i bassotti!"

Mentre 

onomat("Non voglio alzarmi dall'amaca.", 3, sentimenti) 

Deve tornare 

"Non voglio alzarmi dall'amaca. Uff.."


NOTA: Ricordarsi lo spazio tra espressione e frase!

"""
def onomat(frase, sentimento, sentimenti):
    
    sent = sentimenti[sentimento]
    if sent["posizione"] == "i":
        return sent["espressione"] + " " + frase
    else:
        return frase + " " + sent["espressione"]



# INIZIO TEST - NON TOCCARE !!!


sentimenti = {
                1:  {
                        "espressione": "Gulp!",
                        "posizione": "i"
                    },
                2:  {
                        "espressione": "Sgaragulp!",
                        "posizione": "i"
                    },
                3:  {
                        "espressione": "Uff..",
                        "posizione": "f"
                    },
                4:  {
                        "espressione": "Yuk yuk!",
                        "posizione": "f"
                    },
                5:  {
                        "espressione": "Sgrunt!",
                        "posizione": "i"
                    },
                6:  {
                        "espressione": "Gasp!",
                        "posizione" : "i"
                    }
            }


assert onomat("Mi chiamo Pippo.", 4, sentimenti) == "Mi chiamo Pippo. Yuk yuk!"
assert onomat("Quel topastro mi ha rovinato un'altra rapina!", 5, sentimenti) == "Sgrunt! Quel topastro mi ha rovinato un'altra rapina!"
assert onomat("Non voglio alzarmi dall'amaca.", 3, sentimenti) == "Non voglio alzarmi dall'amaca. Uff.."

# FINE TEST

"""

Esercizio 3 

Prende una matrice come lista di liste in ingresso contenenti zeri e uni, e 
RITORNA una nuova matrice (sempre come lista di liste), costruita prima 
invertendo tutte le righe della matrice di input e poi rovesciando tutte le righe

- Invertire una lista vuol dire trasformare gli 0 in 1 e gli 1 in 0.
  Per esempio,
    [0,1,1] diventa [1,0,0]
    [0,0,1] diventa [1,1,0]
    
- Rovesciare una lista vuol dire che rovesciare l'ordine degli elementi:

    Per esempio 
      [0,1,1] diventa [1,1,0]
      [0,0,1] diventa [1,0,0]

Combinando inversione e rovesciamento, per esempio se partiamo da


[
  [1,1,0,0],
  [0,1,1,0],
  [0,0,1,0]
]


Prima invertiamo ciascun elemento:

[
  [0,0,1,1],
  [1,0,0,1],
  [1,1,0,1]
]


e poi rovesciamo ciascuna riga:

[
  [1,1,0,0],
  [1,0,0,1],
  [1,0,1,1]

]

Suggerimenti

 - per rovesciare una lista usare il metodo .reverse() come in   mia_lista.reverse()
   NOTA: mia_lista.reverse() modifica mia_lista, *non* ritorna una nuova lista !!
 - ricordarsi ll return !!
"""
def flip(matrice):
    
    ret = []
    for riga in matrice:
        nuova_riga = []
        for elem in riga:
            nuova_riga.append(1 - elem)
        
        nuova_riga.reverse()
        ret.append(nuova_riga)
    return ret

  
# INIZIO TEST - NON TOCCARE !!!

assert flip([[]]) == [[]]
assert flip([[1]]) == [[0]]
assert flip([[1,0]]) == [[1,0]]
  
m1 = [
      [1,0,0],
      [1,0,1]
     ]
mat_attesa1 = [
    [1,1,0],
    [0,1,0]
]
assert flip(m1) == mat_attesa1
  
  
m2 = [
  [1,1,0,0],
  [0,1,1,0],
  [0,0,1,0]
]

mat_attesa2 = [
  [1,1,0,0],
  [1,0,0,1],
  [1,0,1,1]

]

assert flip(m2) == mat_attesa2

# verifica che l'm originale non è cambiato !
assert m2 == [   
  [1,1,0,0],
  [0,1,1,0],
  [0,0,1,0]
]

# FINE TEST

"""

ESERCIZIO 4

Ritorna un generatore che genera una sequenza contenente n stringhe, con queste 
regole:

- si suppone che il primo elemento della sequenza sia ad indice zero

se si sta generando una stringa:
- ad indice pari, la stringa deve contenere la lettera 'a'
- ad indice dispari, la stringa deve contenere la lettera 'b'
- ad indice divisibile per 3, la stringa deve contenere la lettera 'c'. 
  Tale lettera deve essere posta alla fine della stringa
  
Per esempio: 

list(gen(7)) 

deve dare

['ac','b','a','bc','a','b','ac'] 

Perchè

Indice    Stringa   Perchè
  0        'ac'     0 è pari e divisibile per 3
  1        'b'      1 è dispari 
  2        'a'      2 è pari
  3        'bc'     3 è dispari e divisibile per tre
  4        'a'      4 è pari
  5        'b'      5 è dispari 
  6        'ac'     6 è pari e divisibile per tre

Suggerimenti
- se volete usare i moduli, per vedere se un indice i è divisibile per m scrivete i % m == 0
- se avete letto la documentazione dei generatori, in alternativa ai moduli c'è 
  un'altro modo più furbo che potete usare
"""

def gen(n):
    
    for i in range(n):
        if i % 2 == 0:
            if i % 3 == 0:
                yield "ac"
            else:
                yield "a"
        else:
            if i % 3 == 0:
                yield "bc"
            else:
              
                yield "b"


# INIZIO TEST - NON TOCCARE !!!



import types
assert isinstance(gen(0), types.GeneratorType) # verifico che pari ritorni un generatore e non una lista
                       
assert list(gen(1)) == ['ac']
assert list(gen(2)) == ['ac','b'] 
assert list(gen(3)) == ['ac','b','a']
assert list(gen(4)) == ['ac','b','a','bc']
assert list(gen(5)) == ['ac','b','a','bc','a']
assert list(gen(6)) == ['ac','b','a','bc','a','b'] 
assert list(gen(7)) == ['ac','b','a','bc','a','b','ac'] 

# FINE TEST



<file_sep>'''
Esercizio 1

Dato un dizionario strutturato ad albero riguardante i voti di uno studente in classe V e VI, 
RESTITUIRE un array contente la media di ogni materia

Esempio: 

medie([
  {'id' : 1, 'subject' : 'math', 'V' : 70, 'VI' : 82},
  {'id' : 1, 'subject' : 'italian', 'V' : 73, 'VI' : 74},
  {'id' : 1, 'subject' : 'german', 'V' : 75, 'VI' : 86}
])

ritorna 

[ (70+82)/2 , (73+74)/2, (75+86)/2 ]

ovvero

[ 76.0 , 73.5, 80.5 ]


'''

def medie(lista):
    # scrivi qui
  
  
  
# INIZIO TEST - NON TOCCARE !
import math

'''
Verifica che i numeri float in lista1 siano simili a quelli di lista2 
'''
def is_list_close(lista1, lista2):
  if len(lista1) != len(lista2):
      return False
    
  for i in range(len(lista1)):
      if not math.isclose(lista1[i], lista2[i]):
          return False
  
  return True


assert is_list_close(medie([
                            {'id' : 1, 'subject' : 'math', 'V' : 70, 'VI' : 82},
                            {'id' : 1, 'subject' : 'italian', 'V' : 73, 'VI' : 74},
                            {'id' : 1, 'subject' : 'german', 'V' : 75, 'VI' : 86}
                          ]),         
                     [ 76.0 , 73.5, 80.5 ])
# FINE TEST
<file_sep>"""
ESERCIZIO 2 


INPUT: 
  - frase da arricchire
  - Il sentimento da usare, che è codificato come un valore numerico.
  - un dizionario di sentimenti, in cui si associa al codice numerico 
di ogni sentimento un dizionario contenente un espressione onomatopeica tipica per quel sentimento,
e la posizione in cui deve figurare all'interno di una frase. Le posizioni sono indicate come 'i'
per inizio e 'f' per fine.


OUTPUT

- La frase arricchita con l'espressione onomatopeica scelta in base al sentimento. L'espressione
  va aggiunta sempre prima o dopo la frase, e sempre separata da uno spazio. 



Per esempio

sentimenti = {
                1:  {
                        "espressione": "Gulp!",
                        "posizione": "i"
                    }
                2:  {
                        "espressione": "Sgaragulp !",
                        "posizione": "i"
                    }
                3:  {
                        "espressione": "Uff..",
                        "posizione": "f"
                    }
}


onomat("Ma quelli sono i bassotti!", 1, sentimenti) 

Deve tornare

"Gulp! Ma quelli sono i bassotti!"

Mentre 

onomat("Non voglio alzarmi dall'amaca.", 3, sentimenti) 

Deve tornare 

"Non voglio alzarmi dall'amaca. Uff.."


NOTA: Ricordarsi lo spazio tra espressione e frase!

"""
def onomat(frase, sentimento, sentimenti):
    
    # Scrivi qui



# INIZIO TEST - NON TOCCARE !!!


sentimenti = {
                1:  {
                        "espressione": "Gulp!",
                        "posizione": "i"
                    },
                2:  {
                        "espressione": "Sgaragulp!",
                        "posizione": "i"
                    },
                3:  {
                        "espressione": "Uff..",
                        "posizione": "f"
                    },
                4:  {
                        "espressione": "Yuk yuk!",
                        "posizione": "f"
                    },
                5:  {
                        "espressione": "Sgrunt!",
                        "posizione": "i"
                    },
                6:  {
                        "espressione": "Gasp!",
                        "posizione" : "i"
                    }
            }


assert onomat("Mi chiamo Pippo.", 4, sentimenti) == "Mi chiamo Pippo. Yuk yuk!"
assert onomat("Quel topastro mi ha rovinato un'altra rapina!", 5, sentimenti) == "Sgrunt! Quel topastro mi ha rovinato un'altra rapina!"
assert onomat("Non voglio alzarmi dall'amaca.", 3, sentimenti) == "Non voglio alzarmi dall'amaca. Uff.."

# FINE TEST
<file_sep>'''
Esercizio 2


RESTITUISCE un generatore che produce una sequenza dei primi n elevati al quadrato

Esempio

potenza(4) resituirà 

0 (0*0)
1 (1*1)
4 (2*2)
9 (3*3)
16 (4*4)


'''
def potenza(n):
  # scrivi qui


      
# INIZIO TEST - NON TOCCARE !

import types
assert isinstance(potenza(0), types.GeneratorType) # verifico che pari ritorni un generatore e non una lista
            
assert list(potenza(0)) == [0]
assert list(potenza(1)) == [0,1]
assert list(potenza(2)) == [0,1,4]
assert list(potenza(3)) == [0,1,4,9]
assert list(potenza(4)) == [0,1,4,9,16]

# FINE TEST
<file_sep># # METODI
# "trento".capitalize()
# print("trento".capitalize())
# "trento".upper()
# print("trento".upper())
# "trento".count("t")
# print("trento".count("t"))


# def char3(phrase):
# 	print(phrase)
# 	subdiv = phrase.split(" ")
# 	lastword = subdiv[-1]
# 	numchar = int(subdiv[1])
# 	export = lastword[0:numchar]
# 	return export


# frase = "Prendi 4 lettere"       # lett
# a = char3(frase)
# print(a)

# frase = "Prendere 5 caratteri"  # carat
# a = char3(frase)
# print(a)

# frase = "Take 10 characters"    # characters
# a = char3(frase)
# print(a)

# # scrivi qui




arrivi = ['sedie', 'lampade', 'cavi']  # magazzino diventa:  {'B': 'sedie', 'C': 'lampade', 'F': 'cavi'}
#arrivi = ['caraffe', 'giardinaggio']  # magazzino diventa:  {'D': 'caraffe', 'E': 'giardinaggio'}
#arrivi = ['stufe']                    # magazzino diventa: {'A': 'stufe'}

catalogo = {'stufe' : 'A',
            'sedie' : 'B',
            'caraffe' : 'D',
            'lampade' : 'C',
            'cavi' : 'F',
            'giardinaggio' : 'E'}

magazzino = dict()
for oggetto in arrivi:
#	print("Oggetto: ", oggetto)
	if oggetto in catalogo:
#		print(catalogo[oggetto])
		magazzino[ catalogo[oggetto] ] = oggetto
print(magazzino)
# scrivi qui

<file_sep># -----------------------------------------------------------------------------------------------------
# -----------------------------------------------------------------------------------------------------
# Esercizio 1
# """
# Prende in input una lista con n numeri interi, e RITORNA una NUOVA lista che
# contiene n tuple ciascuna da due elementi. Ogni tupla contiene un numero
# preso dalla corrispondente posizione della lista di partenza, e il suo doppio.
# Per esempio:
# doppie([ 5, 3, 8])
# deve dare la nuova lista
# [(5,10), (3,6), (8,16)]
# """
# def doppie(lista):
# 	lista2x = []
# 	n = len(lista)
# 	print("-" * 25)
# 	print("list: ", lista, "length: ", n )
# 	lista2x = [(x,2*x) for x in lista]
# 	print(lista2x)
# 	print("-" * 25)
# 	return lista2x

# # INIZIO TEST - NON TOCCARE !
# assert doppie([]) == []
# assert doppie([3]) == [(3,6)]
# assert doppie([2,7]) == [(2,4),(7,14)]
# assert doppie([5,3,8]) == [(5,10), (3,6), (8,16)]
# # FINE TEST

# # -----------------------------------------------------------------------------------------------------
# # -----------------------------------------------------------------------------------------------------
# # Esercizio 2
# """
# Quando si analizza una frase, può essere utile processarla per rimuovere parole molto comuni, come
# gli articoli e le preposizioni:
# Per esempio:
# "un libro su Python per principianti"
# si può semplificare in
# "libro Python principianti"
# Le parole 'poco utili' vengono chiamate 'stopwords'. Questo processo è per esempio eseguito
# dai motori di ricerca per ridurre la complessità della stringa di input fornita dall'utente.
# Implementare una funzione che prende una stringa e RITORNA la stringa di input senza le
# stopwords
# SUGGERIMENTO 1: le stringhe in Python sono *immutabili* ! Per rimuovere le parole dovete
# creare una _nuova_ stringa a partire dalla stringa di partenza.
# SUGGERIMENTO 2: create una lista di parole così:
# lista = stringa.split(" ")
# SUGGERIMENTO 3: operate le opportune trasformazioni su lista, e poi costruite la stringa
# da restituire con " ".join(lista)
# """
# def nostop(stringa, stopwords):
# 	readstr = stringa.split(" ")
# 	print(readstr)

# 	for i in range(0,len(stopwords)):
# 		n = readstr.count(stopwords[i])
# 		word2remove=stopwords[i]
# 		print("Parola da rimuovere: \"",word2remove, "\" ",n," volte")

# 		for j in range(0,n):
# 			readstr.remove(word2remove)
# 			print(readstr)
# 			j =+ 1

# 	print("finale", " ".join(readstr))
# 	print("-" * 25)
# 	return " ".join(readstr)


# # INIZIO TEST - NON TOCCARE !
# assert nostop("un", ["un"]) == ""
# assert nostop("un", []) == "un"
# assert nostop("", []) == ""
# assert nostop("", ["un"]) == ""
# assert nostop("un libro", ["un"]) == "libro"
# assert nostop("un libro su Python", ["un","su"]) == "libro Python"
# assert nostop("un libro su Python per principianti", ["un","uno","il","su","per"]) == "libro Python principianti"
# # FINE TEST
# # -----------------------------------------------------------------------------------------------------
# # -----------------------------------------------------------------------------------------------------

# -----------------------------------------------------------------------------------------------------
# -----------------------------------------------------------------------------------------------------
# Esercizio 3
"""
Restituisce un dizionario con n coppie chiave-valore, dove le chiavi sono
numeri interi da 1 a n incluso, e ad ogni chiave i è associata una lista di numeri
da 1 a i
NOTA: le chiavi sono *numeri interi*, NON stringhe !!!!!
Esempio:
dilist(3)
deve dare:
{
1:[1],
2:[1,2],
3:[1,2,3]
}
"""


# def dilist(n):
# # # scrivi qui
# 	diz = dict()
# 	for voce in range(1,n+1):
# 		diz[voce] = list(range(1,voce+1))
# #		print("incremento diz;" , diz)
		
# 	print("Diz.: ", diz)
# 	print("-"*25)
# 	return diz 

# #INIZIO TEST - NON TOCCARE !
# assert dilist(0) == dict()
# assert dilist(1) == {
# 1:[1]
# }
# assert dilist(2) == {
# 1:[1],
# 2:[1,2]
# }
# assert dilist(3) == {
# 1:[1],
# 2:[1,2],
# 3:[1,2,3]
# }
# # FINE TEST

# -----------------------------------------------------------------------------------------------------
# -----------------------------------------------------------------------------------------------------
# Esercizio 4
import numpy as np
"""
RESTITUISCE una NUOVA matrice numpy che ha i numeri della matrice numpy
di input ruotati di una colonna.
Per ruotati intendiamo che:
- se un numero nella matrice di input si trova alla colonna j, nella matrice
di output si troverà alla colonna j+1 nella stessa riga.
- Se un numero si trova nell'ultima colonna, nella matrice di output
si troverà nella colonna zeresima.
Esempio:
Se abbiamo come input
np.array( [
[0,1,0],
[1,1,0],
[0,0,0],
[0,1,1]
])
Ci aspettiamo come output
np.array( [
[0,0,1],
[0,1,1],
[0,0,0],
[1,0,1]
])
"""
def matrot(matrice):
	raise Exception
# scrivi qui
# INIZIO TEST - NON TOCCARE !
m1 = np.array( [
[1]
])
mat_attesa1 = np.array( [
[1]
])
assert np.allclose(matrot(m1), mat_attesa1)
m2 = np.array( [
[0,1]
])
mat_attesa2 = np.array( [
[1,0]
])
assert np.allclose(matrot(m2), mat_attesa2)
m3 = np.array( [
[0,1,0]
])
mat_attesa3 = np.array(
[
[0,0,1]
])
assert np.allclose(matrot(m3), mat_attesa3)
m4 = np.array( [
[0,1,0],
[1,1,0]
])
mat_attesa4 = np.array( [
[0,0,1],
[0,1,1]
])
assert np.allclose(matrot(m4), mat_attesa4)
m5 = np.array([
[0,1,0],
[1,1,0],
[0,0,0],
[0,1,1]
])
mat_attesa5 = np.array([
[0,0,1],
[0,1,1],
[0,0,0],
[1,0,1]
])
assert np.allclose(matrot(m5), mat_attesa5)
# FINE TEST
<file_sep>"""
Quando si analizza una frase, può essere utile processarla per rimuovere parole molto comuni, 
come articoli e le preposizioni:

Per esempio:

  "un libro su Python per principianti" 
   
  si può semplificare in 

      "libro Python principianti"

Le parole 'poco utili' vengono chiamate 'stopwords'. Questo processo è per esempio eseguito dai motori di ricerca per ridurre la complessità della stringa di input fornita dall'utente.

Implementare una funzione che prende una stringa e RITORNA la stringa di input senza le stopwords

SUGGERIMENTO 1: le stringhe in Python sono *immutabili* ! Per rimuovere le parole dovete creare una 
_nuova_ stringa a partire dalla stringa di partenza. 
 
SUGGERIMENTO 2: create una lista di parole così:
    lista = stringa.split(" ")

SUGGERIMENTO 3: operate le opportune trasformazioni su lista, e poi costruite la stringa da restituire con  
    " ".join(lista)
"""
def nostop(stringa, stopwords):
    # scrivi qui


# INIZIO TEST - NON TOCCARE !
assert nostop("un", ["un"]) == ""
assert nostop("un", []) == "un"
assert nostop("", []) == ""
assert nostop("", ["un"]) == ""
assert nostop("un libro", ["un"]) == "libro"
assert nostop("un libro su Python", ["un","su"]) == "libro Python"
assert nostop("un libro su Python per principianti", ["un","uno","il","su","per"]) == "libro Python principianti"
# FINE TEST<file_sep>"""
Prende in input una lista con n numeri interi, e RITORNA una NUOVA lista che 
contiene n tuple ciascuna da due elementi. Ogni tupla contiene un numero 
preso dalla corrispondente posizione della lista di partenza, e il suo doppio. 

Per esempio:

doppie([ 5, 3, 8])

deve dare la nuova lista

[(5,10), (3,6), (8,16)]

"""
def doppie(lista):
    # scrivi qui


# INIZIO TEST - NON TOCCARE !
assert doppie([]) == []
assert doppie([3]) == [(3,6)]
assert doppie([2,7]) == [(2,4),(7,14)]
assert doppie([5,3,8]) == [(5,10), (3,6), (8,16)]
# FINE TEST<file_sep>'''
Esercizio 3

ATTENZIONE: IN QUESTO ESERCIZIO NUMPY NON DEVE ESSERE UTILIZZATO 

RESTITUISCE True se la matrice come lista di liste in input è Toeplitz, mentre RESTITUISCE False se non lo è.

Una matrice è Toeplitz se e solo se tutti gli elementi su ogni diagonale contiene gli stessi elementi.

assumiamo che la matrice contenga sempre almeno una riga di almeno un elemento


SUGGERIMENTO: usare due for, nel primo scorrere la matrice per righe, nel secondo per colonne

Chiedersi: 
- da che riga occorre partire per la scansione? La prima è utile?
- da che colonna occorre partire per la scansione? La prima è utile?
- se scorriamo le righe dalla prima verso l'ultima e stiamo esaminando un certo 
  numero ad una certa riga, che condizione deve rispettare quel numero
  affinchè la matrice sia toepliz ?

ESEMPIO:

matrix = [[1,2,3,4],[5,1,2,3],[9,5,1,2]]

1 2 3 4
5 1 2 3
9 5 1 2

Su ogni diagonale ci sono gli stessi numeri e quindi viene restituito True

1 2 3 4
5 1 4 3
9 3 1 2

Restituisce False. Ci sono due diagonali con numeri diversi: (5,3) e (2,4,2)

'''

def toepliz(matrix):
    # scrivi qui

  
  
# INIZIO TEST - NON TOCCARE !  
assert toepliz([[1]]) == True
assert toepliz([[3,7],
                [5,3]]) == True
assert toepliz([[3,7],
                [3,5]]) == False
assert toepliz([[3,7],
                [3,5]]) == False
assert toepliz([[3,7,9],
                [5,3,7]]) == True
assert toepliz([[3,7,9],
                [5,3,8]]) == False

assert toepliz([[1,2,3,4],
                [5,1,2,3],
                [9,5,1,2]]) == True

assert toepliz([[1,2,3,4],
                [5,9,2,3],
                [9,5,1,2]]) == False
# FINE TEST
<file_sep>"""
ESERCIZIO 1


RITORNA un dizionario in cui le chiavi sono numeri interi da 1 a n inclusi, e i rispettivi 
valori sono i quadrati delle chiavi 

powers(3)

Ritorna

{
 1:1,
 2:4,
 3:9
}

"""
def powers(n):
    # scrivi qui


# INIZIO TEST - NON TOCCARE !!!
assert powers(1) == {1:1}
assert powers(2) == {
                        1:1,
                        2:4
                    }
assert powers(3) == {
                        1:1,
                        2:4,
                        3:9
                    }

assert powers(4) == {
                        1:1,
                        2:4,
                        3:9,
                        4:16
                    }
# FINE TEST
<file_sep>
import numpy as np

"""
RESTITUISCE una NUOVA matrice numpy che ha i numeri della matrice numpy 
di input ruotati di una colonna. 

Per ruotati intendiamo che:
- se un numero nella matrice di input si trova alla colonna j, nella matrice 
di output si troverà alla colonna j+1 nella stessa riga.
- Se un numero si trova nell'ultima colonna, nella matrice di output 
si troverà nella colonna zeresima.

Esempio:

Se abbiamo come input 

np.array(   [
                [0,1,0],
                [1,1,0],
                [0,0,0],
                [0,1,1]
            ])

Ci aspettiamo come output

np.array(   [
                [0,0,1],
                [0,1,1],
                [0,0,0],
                [1,0,1]
            ])

"""
def matrot(matrice):
    # scrivi qui


# INIZIO TEST - NON TOCCARE !

m1 = np.array(  [
                    [1]
                ])
mat_attesa1 = np.array( [
                            [1]
                        ])

assert np.allclose(matrot(m1), mat_attesa1)

m2 = np.array(  [
                    [0,1]
                ])
mat_attesa2 = np.array( [
                            [1,0]
                        ])
assert np.allclose(matrot(m2), mat_attesa2)

m3 = np.array(  [
                    [0,1,0]
                ])
mat_attesa3 = np.array(
                [
                    [0,0,1]
                ])

assert np.allclose(matrot(m3), mat_attesa3)

m4 = np.array(  [ 
                    [0,1,0],
                    [1,1,0]
                ])
mat_attesa4 = np.array( [
                            [0,0,1],
                            [0,1,1]
                        ])
assert np.allclose(matrot(m4), mat_attesa4)


m5 = np.array([
                [0,1,0],
                [1,1,0],
                [0,0,0],
                [0,1,1]
              ])
mat_attesa5 = np.array([
                        [0,0,1],
                        [0,1,1],
                        [0,0,0],
                        [1,0,1]
                       ])
assert np.allclose(matrot(m5), mat_attesa5)
# FINE TEST
<file_sep>
# import sys

# locate_python = sys.exec_prefix
# print(locate_python)

# # To launch this library on Jupyter
# # matplotlib inline
# Useful link to plot things inside Sublime Text 3
# https://github.com/sschuhmann/Helium/issues

# To install the library for the first time:
# python -m pip install matplotlib 
import matplotlib
import matplotlib.pyplot as plt
import numpy as np

x = [1 ,2, 3, 4, 5, 6, 7, 8, 9, 10]
y = [10, 20 ,30, 40, 50, 60 , 70 , 80, 90 , 100]

plt.plot(x,y,'b')
plt.show()

x = np.arange(0,11,1.)
y = 2*x+y

fig = plt.figure(figsize=(10,2)) # larghezza 10 pollici, altezza 2 pollici
<file_sep>"""
     ESAME S<NAME>ORITMI PYTHON   14 Giugno 2018


    - NON CAMBIATE IL NOME DELLE FUNZIONI
        - SE VOLETE POTETE AGGIUNGERE FUNZIONI VOSTRE, MA DOVETE SEMPRE
          RICHIAMARLE DALLE FUNZIONI CHE VI HO SCRITTO IO

    - QUANDO SCRIVO 'RITORNA', LA FUNZIONE DEVE _RITORNARE_ DEI VALORI,
      NON STAMPARLI CON LA PRINT !!!!

    - COMUNQUE, PRINT ADDIZIONALI DI DEBUG SONO CONCESSE

    - NON RIASSEGNATE I PARAMETRI IN INPUT! TRADOTTO: NON SCRIVETE _MAI_
      QUALCOSA DEL GENERE !!!

         def f(x):
            x = .....

    - OGNI FUNZIONE E' SEGUITA DAGLI ASSERT DI TEST, SE QUANDO ESEGUITE
      IL CODICE NON VEDETE ERRORI PROBABILMENTE IL CODICE E' GIUSTO
      (MA NON FIDATEVI TROPPO, I TEST NON SONO ESAUSTIVI !)


    - USARE EDITOR SPYDER. 
      - Per eseguire tutto lo script: F5
      - Per eseguire solo la linea corrente o la selezione:  F9

    *** DA FARE: IMPLEMENTATE QUESTE 4 FUNZIONI: ***
    
      - medie
      - potenza
      - toepliz
      - quadranti
"""

'''
Esercizio 1

Dato un dizionario strutturato ad albero riguardante i voti di uno studente in classe V e VI, 
RESTITUIRE un array contente la media di ogni materia

Esempio: 

medie([
  {'id' : 1, 'subject' : 'math', 'V' : 70, 'VI' : 82},
  {'id' : 1, 'subject' : 'italian', 'V' : 73, 'VI' : 74},
  {'id' : 1, 'subject' : 'german', 'V' : 75, 'VI' : 86}
])

ritorna 

[ (70+82)/2 , (73+74)/2, (75+86)/2 ]

ovvero

[ 76.0 , 73.5, 80.5 ]


'''

def medie(lista):
    ret = [0.0, 0.0, 0.0]
    
    for i in range(len(lista)):
        ret[i] = (lista[i]['V'] + lista[i]['VI']) / 2
   
    return ret

  
  
# INIZIO TEST - NON TOCCARE !
import math


'''
Verifica che i numeri float in lista1 siano simili a quelli di lista2 
'''  
def is_list_close(lista1, lista2):
  if len(lista1) != len(lista2):
      return False
    
  for i in range(len(lista1)):
      if not math.isclose(lista1[i], lista2[i]):
          return False
  
  return True

assert is_list_close(medie([
                            {'id' : 1, 'subject' : 'math', 'V' : 70, 'VI' : 82},
                            {'id' : 1, 'subject' : 'italian', 'V' : 73, 'VI' : 74},
                            {'id' : 1, 'subject' : 'german', 'V' : 75, 'VI' : 86}
                          ]),         
                     [ 76.0 , 73.5, 80.5 ])
# FINE TEST


'''
Esercizio 2


RESTITUISCE un generatore che produce una sequenza dei primi n elevati al quadrato 

Esempio

potenza(4) resituirà 

0 (0*0)
1 (1*1)
4 (2*2)
9 (3*3)
16 (4*4)


'''
def potenza(n):
  i = 0
  while i <= n:
      yield i * i
      i += 1

      
# INIZIO TEST - NON TOCCARE !

import types
assert isinstance(potenza(0), types.GeneratorType) # verifico che pari ritorni un generatore e non una lista
            
assert list(potenza(0)) == [0]
assert list(potenza(1)) == [0,1]
assert list(potenza(2)) == [0,1,4]
assert list(potenza(3)) == [0,1,4,9]
assert list(potenza(4)) == [0,1,4,9,16]

# FINE TEST



'''
Esercizio 3

ATTENZIONE: IN QUESTO ESERCIZIO NUMPY NON DEVE ESSERE UTILIZZATO 

RESTITUISCE True se la matrice come lista di liste in input è Toeplitz, mentre RESTITUISCE False se non lo è.

Una matrice è Toeplitz se e solo se tutti gli elementi su ogni diagonale contiene gli stessi elementi.

assumiamo che la matrice contenga sempre almeno una riga di almeno un elemento


SUGGERIMENTO: usare due for, nel primo scorrere la matrice per righe, nel secondo per colonne

Chiedersi: 
- da che riga occorre partire per la scansione? La prima è utile?
- da che colonna occorre partire per la scansione? La prima è utile?
- se scorriamo le righe dalla prima verso l'ultima e stiamo esaminando un certo 
  numero ad una certa riga, che condizione deve rispettare quel numero
  affinchè la matrice sia toepliz ?

ESEMPIO:

matrix = [[1,2,3,4],[5,1,2,3],[9,5,1,2]]

1 2 3 4
5 1 2 3
9 5 1 2

Su ogni diagonale ci sono gli stessi numeri e quindi viene restituito True

1 2 3 4
5 1 4 3
9 3 1 2

Restituisce False. Ci sono due diagonali con numeri diversi: (5,3) e (2,4,2)

'''

def toepliz(matrix):
    
    for i in range(1,len(matrix)):
        for j in range(1,len(matrix[0])):
            if matrix[i][j] != matrix[i-1][j-1]:
                return False
    return True

  
  
# INIZIO TEST - NON TOCCARE !  
assert toepliz([[1]]) == True
assert toepliz([[3,7],
                [5,3]]) == True
assert toepliz([[3,7],
                [3,5]]) == False
assert toepliz([[3,7],
                [3,5]]) == False
assert toepliz([[3,7,9],
                [5,3,7]]) == True
assert toepliz([[3,7,9],
                [5,3,8]]) == False

assert toepliz([[1,2,3,4],
                [5,1,2,3],
                [9,5,1,2]]) == True

assert toepliz([[1,2,3,4],
                [5,9,2,3],
                [9,5,1,2]]) == False
# FINE TEST


'''
Esercizio 4

ATTENZIONE: IN QUESTO ESERCIZIO DEVE ESSERE UTILIZZATO NUMPY

Data una matrice 2n * 2n, dividere la matrice in 4 parti quadrate uguali 
(vedi esempio per capire meglio) e RESTITUIRE una NUOVA matrice 2 * 2
contente la media di ogni quadrante

Si assume che la matrice sia sempre di dimensioni pari

SUGGERIMENTO: per dividere per 2 e ottenere un numero intero, usare l'operatore // 


Esempio:

 1, 2 , 5 , 7
 4, 1 , 8 , 0
 2, 0 , 5 , 1 
 0, 2 , 1 , 1 

si divide in 

  1, 2 | 5 , 7
  4, 1 | 8 , 0
----------------- 
  2, 0 | 5 , 1 
  0, 2 | 1 , 1 

e si restituisce 

  (1+2+4+1)/ 4  | (5+7+8+0)/4                        2.0 , 5.0 
  -----------------------------            =>        1.0 , 2.0 
  (2+0+0+2)/4   | (5+1+1+1)/4  


'''

import numpy as np

def quadranti(matrice):
    
    ret = np.zeros( (2,2) )
    
    dim = matrice.shape[0] 
    n = dim // 2
    elementi_per_quadrante = n * n
    
    for i in range(n):
        for j in range(n):
            ret[0,0] += matrice[i,j]
    ret[0,0] /=   elementi_per_quadrante
        
      
    for i in range(n,dim):
        for j in range(n):
            ret[1,0] += matrice[i,j]
    ret[1,0] /= elementi_per_quadrante

    for i in range(n,dim):
        for j in range(n,dim):
            ret[1,1] += matrice[i,j]
    ret[1,1] /= elementi_per_quadrante

    for i in range(n):
        for j in range(n,dim):
            ret[0,1] += matrice[i,j]
    ret[0,1] /= elementi_per_quadrante
    
    return ret
         
# INIZIO TEST - NON TOCCARE !

assert np.allclose(
    quadranti(np.array([
                          [3.0, 5.0],
                          [4.0, 9.0],
                       ])),
              np.array([
                          [3.0, 5.0],
                          [4.0, 9.0],
                       ])
      )

assert np.allclose(
    quadranti(np.array([    
                         [1.0, 2.0 , 5.0 , 7.0],
                         [4.0, 1.0 , 8.0 , 0.0],
                         [2.0, 0.0 , 5.0 , 1.0], 
                         [0.0, 2.0 , 1.0 , 1.0]    
                       ])), 
              np.array([ 
                         [2.0, 5.0],
                         [1.0, 2.0]
                       ])) 

# FINE TEST
<file_sep># -------------------------------------------------------------------------------------
# -------------------------------------------------------------------------------------
# # ESERCIZIO 4:

# def max_len_str(phrase):
# 	parser = frase.split(" ")
# 	length_parser = []
# 	for word in parser:
# 		lenword = len(word)
# 		length_parser.append(lenword)

# 	print(length_parser)
# 	max_value = max(length_parser)
# 	print(max_value)
# 	return max_value

# frase = "La strada si inerpica lungo il ciglio della montagna" # 8
# frase = "Il temibile pirata Le Chuck dominava spietatamente i mari del Sud"  # 13
# frase = "Praticamente ovvio" # 12

# max_len_str(frase)

# max([len(parola) for parola in frase.split()])

# # -------------------------------------------------------------------------------------
# # -------------------------------------------------------------------------------------
# # # ESERCIZIO 4:

# lista = [0, 0, 0, 0, 4, 0, 0, 0, 0] # -> [0, 1, 2, 3, 4, 3, 2, 1, 0]
# #lista = [0, 0, 0, 3, 0, 0, 0]      # -> [0, 1, 2, 3, 2, 1, 0]
# #lista = [0, 0, 2, 0, 0]            # -> [0, 1, 2, 1, 0]
# #lista = [0]  # -> [0]

# value = max([numero for numero in lista])
# pos = lista.index(value)
# print("Valore: ",value," in posizione: ",pos)
# nlista = []
# l1 = list(range(0,value)) + list(range(value,0,-1))
# print(l1)


# # -------------------------------------------------------------------------------------
# # -------------------------------------------------------------------------------------
# # # ESERCIZIO 4:

stringa,car1,car2 = "accatastare la posta nella stiva", 's','t'  # True
stringa,car1,car2 = "dadaista entusiasta", 's','t'    # False
# stringa,car1,car2 = "barbabietole", 't','o'           # True
# stringa,car1,car2 = "barbabietole", 'b','a'           # False
# stringa,car1,car2 = "a", 'a','b'                      # False
# stringa,car1,car2 = "ab", 'a','b'                     # True
# stringa,car1,car2 = "aa", 'a','b'                     # False

res = True
start_string = stringa
chars_i_want = (car1,car2)
print(chars_i_want)
final_string = ''.join(c for c in start_string if c in chars_i_want)
print(final_string)

if final_string[0] == car2:
	final_string=final_string[1:]

check2 = car1+car2
print(check2)

car = 0
while car+1<len(final_string) and res: 
#for car in range(0,len(final_string),2):
	try:
		temp = final_string[car] + final_string[car+1]		
		car += 1
		if temp != check2:
			res = False
		elif temp == check2:
			res = True
	except Exception:
		res = False

print(res)



# i = 0

# res = True

# if len(stringa) == 1:
#     res = False

# while i + 1 < len(stringa) and res:
#     if stringa[i] == car1 and stringa[i+1] != car2:
#         res = False
#     i += 1

# res<file_sep>
"""
Restituisce un dizionario con n coppie chiave-valore, dove le chiavi sono 
numeri interi da 1 a n incluso, e ad ogni chiave i è associata una lista di numeri 
da 1 a i

NOTA: le chiavi sono *numeri interi*, NON stringhe !!!!!

Esempio:

dilist(3)

deve dare:

 { 
    1:[1],
    2:[1,2],
    3:[1,2,3]
}


"""
def dilist(n):
    # scrivi qui


# INIZIO TEST - NON TOCCARE !

assert dilist(0) == dict()
assert dilist(1) == {
                        1:[1]
                    }
assert dilist(2) == { 
                        1:[1],
                        2:[1,2]
                    }
assert dilist(3) == { 
                        1:[1],
                        2:[1,2],
                        3:[1,2,3]
                    }
# FINE TEST
<file_sep>"""

Esercizio 3 

Prende una matrice come lista di liste in ingresso contenenti zeri e uni, e 
RITORNA una nuova matrice (sempre come lista di liste), costruita prima 
invertendo tutte le righe della matrice di input e poi rovesciando tutte le righe

- Invertire una lista vuol dire trasformare gli 0 in 1 e gli 1 in 0.
  Per esempio,
    [0,1,1] diventa [1,0,0]
    [0,0,1] diventa [1,1,0]
    
- Rovesciare una lista vuol dire che rovesciare l'ordine degli elementi:

    Per esempio 
      [0,1,1] diventa [1,1,0]
      [0,0,1] diventa [1,0,0]

Combinando inversione e rovesciamento, per esempio se partiamo da


[
  [1,1,0,0],
  [0,1,1,0],
  [0,0,1,0]
]


Prima invertiamo ciascun elemento:

[
  [0,0,1,1],
  [1,0,0,1],
  [1,1,0,1]
]


e poi rovesciamo ciascuna riga:

[
  [1,1,0,0],
  [1,0,0,1],
  [1,0,1,1]

]

Suggerimenti

 - per rovesciare una lista usare il metodo .reverse() come in   mia_lista.reverse()
   NOTA: mia_lista.reverse() modifica mia_lista, *non* ritorna una nuova lista !!
 - ricordarsi ll return !!
"""
def flip(matrice):
    
    # Scrvi qui

  
# INIZIO TEST - NON TOCCARE !!!

assert flip([[]]) == [[]]
assert flip([[1]]) == [[0]]
assert flip([[1,0]]) == [[1,0]]
  
m1 = [
      [1,0,0],
      [1,0,1]
     ]
mat_attesa1 = [
    [1,1,0],
    [0,1,0]
]
assert flip(m1) == mat_attesa1
  
  
m2 = [
  [1,1,0,0],
  [0,1,1,0],
  [0,0,1,0]
]

mat_attesa2 = [
  [1,1,0,0],
  [1,0,0,1],
  [1,0,1,1]

]

assert flip(m2) == mat_attesa2

# verifica che l'm originale non è cambiato !
assert m2 == [   
  [1,1,0,0],
  [0,1,1,0],
  [0,0,1,0]
]

# FINE TEST
<file_sep>

'''
Esercizio 4

ATTENZIONE: IN QUESTO ESERCIZIO DEVE ESSERE UTILIZZATO NUMPY

Data una matrice 2n * 2n, dividere la matrice in 4 parti quadrate uguali 
(vedi esempio per capire meglio) e RESTITUIRE una NUOVA matrice 2 * 2
contente la media di ogni quadrante

Si assume che la matrice sia sempre di dimensioni pari

SUGGERIMENTO: per dividere per 2 e ottenere un numero intero, usare l'operatore // 


Esempio:

 1, 2 , 5 , 7
 4, 1 , 8 , 0
 2, 0 , 5 , 1 
 0, 2 , 1 , 1 

si divide in 

  1, 2 | 5 , 7
  4, 1 | 8 , 0
----------------- 
  2, 0 | 5 , 1 
  0, 2 | 1 , 1 

e si restituisce 

  (1+2+4+1)/ 4  | (5+7+8+0)/4                        2.0 , 5.0 
  -----------------------------            =>        1.0 , 2.0 
  (2+0+0+2)/4   | (5+1+1+1)/4  


'''

import numpy as np

def quadranti(matrice):
    
    # scrivi qui


    
         
# INIZIO TEST - NON TOCCARE !

assert np.allclose(
    quadranti(np.array([
                          [3.0, 5.0],
                          [4.0, 9.0],
                       ])),
              np.array([
                          [3.0, 5.0],
                          [4.0, 9.0],
                       ])
      )

assert np.allclose(
    quadranti(np.array([    
                         [1.0, 2.0 , 5.0 , 7.0],
                         [4.0, 1.0 , 8.0 , 0.0],
                         [2.0, 0.0 , 5.0 , 1.0], 
                         [0.0, 2.0 , 1.0 , 1.0]    
                       ])), 
              np.array([ 
                         [2.0, 5.0],
                         [1.0, 2.0]
                       ])) 

# FINE TEST
<file_sep>import numpy as np

# Matrice di partenza
m = np.array( 
    [ 
#         0         1         2      
#        Gilberto   Rocky     Clelia
        [5.0,       8.0,      1.0],   # 0 Thè
        [7.0,       3.0,      2.0],   # 1 Caffè
        [9.0,       2.0,      8.0]    # 2 Ginseng
    ]
)

nomi = ["Gilberto","Rocky","Clelia"]
#print(nomi[0])
bevande = ["Thè","Caffè","Ginseng"]

print("-"*55)
print("<NAME> vs Bevande \n",m)
print("-"*55)

# Spesa dei singoli fruitori di bevande
num_righe, num_colonne = m.shape
somma = []
for col in range(0, num_colonne):
  spesa_col = m[:,col:col+1]
  somma_temp = np.sum(spesa_col)
  somma.append(somma_temp)

print("Spesa di ciascuno: \n Gilberto, Rocky, Clelia \n" , somma)
print("-"*55)

# Alternativa 1: non piace print 
spendaccione = np.array(somma)
index_spendaccione = np.where(spendaccione.max())
print("Prima alternativa di output:\n")
print("Dei tre ha speso di più il numero:",index_spendaccione, ", per un totale di: ",spendaccione[index_spendaccione],"\n")

# Alternativa 2
#l = [1,2,3,4,5] # Python list
#a = np.array(l) # NumPy array
spesePC = np.array(somma)
indicePCmaggiore = spesePC.tolist().index(spesePC.max()) # return index of max PC
print("Seconda alternativa di output:\n")
print("Dei tre ha speso di più il numero:",indicePCmaggiore, ", per un totale di: ",spesePC[indicePCmaggiore],"\n")

# Alternativa 3
print("Dei tre ha speso di più:",nomi[indicePCmaggiore], ", per un totale di: ",spesePC[indicePCmaggiore],"\n")
print("-"*55)


# Spesa singole bevande
somma = []
for riga in m:
  somma_temp = np.sum(riga)
  somma.append(somma_temp)

print("Spesa per tipo: \n Thé, Caffé, Ginseng \n" , somma)
print("-"*55)

speseBEV = np.array(somma)
indiceBEV = speseBEV.tolist().index(speseBEV.max())
print("La bevanda preferita è la numero:",indiceBEV,", per un costo di: ",speseBEV[indiceBEV])
print("-"*55)

print("La bevanda preferita è:",bevande[indiceBEV],", per un costo di: ",speseBEV[indiceBEV])
print("-"*55)
<file_sep># TOC: Esercizi matrici 
'''
	1. esrigaf(mat,i) : ritorna la i-esima riga
		1.a. con FOR
		1.b. con RANGE
		1.c. con SLICE
		1.d. con LIST COMPREHENSION
	1. escolf(mat,i) : ritorna la i-esima colonna
'''
# -------------------------------------------------------------------------------------
# -------------------------------------------------------------------------------------
# 1) ESERCIZIO: Implementa la funzione esrigaf, che RITORNA la i-esima riga da mat

# def esrigaf(mat, i):
#   riga = mat
#   return riga[i]
#   print("Prova",mat[i])
#   return mat[i]

# # RISOLUZIONE con FOR
# def esrigaf(mat, i):
#     riga = []
#     for x in mat[i]:
#         riga.append(x)
#     return riga

# # RISOLUZIONE con RANGE
# def esrigaf(mat, i):
#     riga = []
#     for j in range(len(mat[0])):
#         riga.append(mat[i][j])
#     return riga


# # RISOLUZIONE con SLICE
#return mat[i][:]
# def esrigaf(mat, i):
#     riga = []
# #    riga.append(riga.slice(0,len(mat[i])))
#     return riga
# print(len(m[0]))
# x = slice(1,len(m[1]),len(m[1]))
# print(m[x])
# print(type(m[0]))


# # # RISOLUZIONE con LIST COMPREHENSION
# def esrigaf(mat, i):
#      return [x for x in mat[i]]

# m = [ ['a','b'],
#       ['c','d'],
#       ['a','e'] ]




# assert esrigaf(m, 0) == ['a','b']
# assert esrigaf(m, 1) == ['c','d']
# assert esrigaf(m, 2) == ['a','e']

# # controlla che non abbia cambiato la matrice originale!
# r = esrigaf(m, 0)
# r[0] = 'z'
# assert m[0][0] == 'a'

# -------------------------------------------------------------------------------------
# -------------------------------------------------------------------------------------
# ESERCIZIO 2: colonna
# def escolf(mat, j):
# 	colonna = []
# 	for i in range(len(mat)):
# 		colonna.append(mat[i][j])
# 		#print(colonna)
# 	return colonna
	
# 	#   raise Exception('TODO IMPLEMENT ME !')

# m = [ ['a','b'],
#       ['c','d'],
#       ['a','e'] ]

# aa = escolf(m, 0)
# print(aa)
# assert escolf(m, 0) == ['a','c','a']
# assert escolf(m, 1) == ['b','d','e']

# # Controlla che la colonna ritornata non modifichi m
# c = escolf(m,0)
# c[0] = 'z'
# assert m[0][0] == 'a'

# # togli il commento se vuoi visualizzare l'esecuzione qui
# #jupman.pytut()

# def escolf(mat, j):
# 	return [x[j] for x in mat]
	
# 	#   raise Exception('TODO IMPLEMENT ME !')

# m = [ ['a','b'],
#       ['c','d'],
#       ['a','e'] ]

# aa = escolf(m, 0)
# print(m[0][0])

# -------------------------------------------------------------------------------------
# -------------------------------------------------------------------------------------
# ESERCIZIO 3: matrici vuote

# def matrice_vuota(n, m):
# 	temp = []
# 	for i in range(0,n):
# 		print("i",i)
# 		temp.append(0)
# 		print(temp)
# 		for j in range(0,m):
# 			print("j",j)
# 			temp.append(0)
# 			print(temp)
# #			temp[i][j] = 0
# 			print(temp) 
# 	return temp

# #   raise Exception('TODO IMPLEMENT ME !')
# # def matrice_vuota(n, m):
# # 	temp = []
# # 	for i in range(0,n):
# # 		riga = []
# # 		print("riga i",i)
# # 		temp.append(riga)
# # 		print(temp)
# # 		for j in range(0,m):
# # 			print("j",j)
# # 			riga.append(0)
# # 			print(temp) 
# # 	return temp

# prova = matrice_vuota(2,2)
# print(prova)
# assert matrice_vuota(1,1) == [ [0] ]

# assert matrice_vuota(1,2) == [ [0,0] ]

# assert matrice_vuota(2,1) == [ [0],
#                                [0] ]

# assert matrice_vuota(2,2) == [ [0,0],
#                                [0,0] ]

# assert matrice_vuota(3,3) == [ [0,0,0],
#                                [0,0,0],
#                                [0,0,0] ]<file_sep># Challenge DATASET  -  PERSONAGGI STORICI 
import os
import csv
import pdb

from typing import List # to enlist content directory


path_dir: str = r"C:\Users\chiar\Google Drive\GIT\PRV\Python\Jupyter\formats"
content_dir: List[str] = os.listdir(path_dir)

filename = 'personaggi-storici-trentino.csv'

path_file = os.sep.join([path_dir, filename])
print(path_file)
print("-" * 45)


# Dictionaries
map_unknown = {
  'sconosciuto': '',
  'sconosciuto ': '',
  'sconosciuto (forse Pavia)': '',
  'sconosciuto (in Slesia)': '',
  'probabilmente Termeno': ''
}
province = {
    'TN': 'Trento',
    'PI': 'Pisa',
    'MC': 'Macerata',
    'CO': 'Como',
    'ME': 'Messina',
    'MI': 'Milano'
}
secoli = {
     'I': 0,
     'II':100,
     'III':200,
     'IV':300,
     'V':400,
     'VI':500,
     'VII':600,
     'VIII':700,
     'IX':800,
     'X':900,
     'XI':1000,
     'XII':1100,
     'XIII':1200,
     'XIV': 1300,
     'XV':1400,
     'XVI':1500,
     'XVII':1600,
     'XVIII':1700,
     'XIX':1800,
     'XX':1900,
     'XXI':2000,
}


with open(path_file,encoding='latin-1') as f_lettura:

  lettore = csv.reader(f_lettura)
  header = next(lettore)
  nome = header[3]
  data_nascita = header[4]
  luogo_nascita = header[6]

  print(nome,data_nascita,luogo_nascita)
  next(lettore)

  with open('dascrivere.csv', 'w', encoding='utf-8') as f_scrittura:
    # header del csv da scrivere
    intestazione = [nome.lower(),  luogo_nascita.lower(),data_nascita.lower(), 'secolo']
    scrittore = csv.writer(f_scrittura, delimiter=',')    
    scrittore.writerow(intestazione)
    print("-" * 45)

    for riga in f_lettura:     
      
      iriga = next(lettore)        
      inome = iriga[3]
      idata = iriga[4]
      iluogo = iriga[6]
      # Fixed 'sconosciuto'
      if iluogo in map_unknown:
         iluogo = ''
      # Fixed 'Sigle province'
      for ikey in province: 
        iluogo = iluogo.replace(ikey,province[ikey])
        iluogo = iluogo.replace(',','')
        if not '(' in iluogo:
          iluogo = iluogo.replace(province[ikey],'('+province[ikey]+')')
        if not ' (' in iluogo:
          iluogo = iluogo.replace('(',' (')
          
      # Fixed 'Secolo'
      print("Conversione:")  
      isecolo = idata.replace('/',' ')

      data_split = isecolo.split()    #temp = idata.translate(None,not "123456789 ")
      # data_split = ['s1','s2','s3','s4']
      print(data_split)
      for iword in reversed(data_split):
        # iword = s1 --> s2 --> ...
        iword2check = ""
        for ichar in iword:
        # ichar = i-character di iword
          if ichar in "0123456789 X I V":
          # costruisci variabile numerica secolo
            iword2check += ichar
        if iword2check != '':
          print("Anno/Secolo da gestire:",iword2check)

        try: 
          if iword2check in secoli:
            #print("dentro dizionario",iword2check)
            isecolo = secoli.get(iword2check)
            #print("convertito",isecolo)
            if isecolo != '':
              print("Secolo identificato: ", isecolo)
            break
        except Exception:
          print("KKK: non ho trovato il secolo da convertire!")     

        try:  
          temp = int(iword2check) 
          if (isinstance(temp, int)):
            temp -= temp % +100
            isecolo = temp
          if isecolo != '':
            print("Secolo identificato: ", isecolo)
          break
        except ValueError:
          print(isecolo)
          pass #print("Riprova: ", iword)      

      print("-" * 55)
  
      i_stampa = [inome,iluogo,idata,isecolo]

      scrittore.writerow(i_stampa)     
     # print(i_stampa)
