from math import sqrt  # pour la fonction dist en dessous

"""Code du cours 08"""

def appartient (t, e):
    """Renvoie True si et seulement si e est dans le tableau t"""

    for x in t:
        if x == e:
            return True

    return False

# Le point important à retenir dans la fonction ci-dessus est
# le return au milieu de la boucle, qui interrompt la boucle immédiatement
# et quitte la fonction.


def test_appartient():
    "Test"
    assert appartient([1,2,3], 3)
    assert appartient([1,2,3,4,5], 3)
    assert not appartient([], 42)
    assert not appartient([1,2,3,10,121], 17)

test_appartient()

def contient_pair(t):
    """Renvoie True si et seulement si t contient un entier pair"""

    for x in t:
        if x % 2 == 0:
            return True

    return False


def index(t, e):
    """Renvoyer l'indice de l'élément e dans t, renvoie None si
    l'élément n'est pas dans t."""
    for i in range(len(t)):
        if t[i] == e:
            return i

    return None
# Deux points dans la fonction ci-dessus:
# - on doit itérer sur les indices, car c'est ce qui est demandé, donc for i in range(len(t))
# - le 'return None' en fin de fonction est redondant: une fonction qui se termine sans
#   effectuer de return renvoie None par défaut. Le code reste cependant plus lisible avec
#   ce return explicite.


def index_err(t, e):
    """Renvoyer l'indice de l'élément e dans t, lève l'exception
    ValueError si e n'est pas dans t."""
    for i in range(len(t)):
        if t[i] == e:
            return i

    raise ValueError("Valeur absente")
# Variante où on a levé une exception

###### Renvoyer tous les éléments qui vérifient une condition

def all_pos(t):
    """Renvoie le tableau de tous les entiers strictement positifs dans t"""
    res = []
    for x in t:
        if x > 0:
            res.append(x)
    return res


def all_lowercase(s):
    """Renvoie le tableau de toutes les lettres minuscules de s"""
    res = []
    for c in s:
        if c.islower(): #équivalent à ce qui a été vu en cours: c.isalpha() and c == c.lower()
            res.append(c)
    return res

def test_all_lowercase():

    assert all_lowercase("AaBbCc") == ['a','b','c']
    assert all_lowercase("AaBbCé") == ['a','b', 'é']

test_all_lowercase()


def somme(t):
    """Renvoie la somme des éléments du tableau t"""
    accu = 0
    for x in t:
        accu = accu + x
    return accu

def maximum(t):
    """Renvoie le plus grand entier du tableau t, renvoie None
       pour le tableau vide."""
    accu = None
    for x in t:
        if accu == None or x > accu:
            accu = x
    return accu

def maximum_alt(t):
    """Renvoie le plus grand entier du tableau t, 
    t est supposé non vide."""
    assert len(t) > 0
    accu = t[0]
    for x in t:
        if x > accu:
            accu = x
    return accu

### Variante du maximum: on veut renvoyer la valeur du tableau qui
### maximise une fonction (ici, la distance):

def dist(p):
    """Renvoie la distance à l'origine du point p"""
    x, y = p
    return sqrt(x*x + y*y)

def plus_loin(t):
    """Renvoie le point de t le plus éloigné de l'origine"""
    p_max = None

    for p in t:
        if p_max == None or dist(p) > dist(p_max):
            p_max = p
    
    return p_max

def plus_loin_opt(t):
    """Renvoie le point de t le plus éloigné de l'origine"""
    p_max = None
    dist_max = 0

    for p in t:
        dist_p = dist(p)
        if dist_p >= dist_max:
            p_max = p
            dist_max = dist_p

    return p_max
### La fonction ci-dessus ne fait pas de calculs inutiles de distance.
### elle set un peu moins lisible, mais doit être utilisée si à la place de
### la fonction dist on a une fonction coûteuse


### Algorithmes de groupement

notes = [("Kim", 20), ("Toto", 10), ("Titi", 15), 
        ("Kim", 17),  ("Tata", 17), ("Titi", 19)]

def note_max(t):

    notes_max = {}
    for x in t:
        nom, note = x
        if nom in notes_max:
            n = notes_max[nom]
            notes_max[nom] = max(note, n)
        else:
            notes_max[nom] = note

    return notes_max
