## Exercice 1

# 1)

def est_voyelle(lettre):
    if lettre in "aeiouyAEIOUY":
        return True
    else:
        return False

# ou plus simplement :

def est_voyelle(lettre):
    return lettre in "aeiouyAEIOUY"

# 2)

def nombre_de_voyelles(chaine):
    nb = 0
    for lettre in chaine:
        if est_voyelle(lettre):
            nb += 1
    return nb

# 3)

def voyelles_etoiles(chaine):
    nv_chaine = ''
    for lettre in chaine:
        if est_voyelle(lettre):
            nv_chaine += '*'
        else:
            nv_chaine += lettre
    return nv_chaine


## Exercice 2

# Avec slicing :

def est_palindrome(chaine):
    return chaine[::-1] == chaine

# Sans slicing, on compare chaque caractère avec son 'symétrique' :

def est_palindrome(chaine):
    n = len(chaine)
    for i in range(n//2):  # il suffit d'aller jusqu'à la moitié de la chaîne
        if chaine[i] != chaine[n-i-1]:
            return False
    return True


## Exercice 3

def positions(lettre, chaine):
    liste_positions = []
    for i in range(len(chaine)):
        if chaine[i] == lettre:
            liste_positions.append(i)
    return liste_positions

# Ou avec une liste par compréhension :

def positions(lettre, chaine):
    return [i for i in range(len(chaine)) if chaine[i] == lettre]


## Exercice 4

# 1)

caracteres = {}
for i in range(65, 91):
    caracteres[i] = chr(i)
print(caracteres)

# Remarque : on peut créer des dictionnaires par compréhension :

caracteres = {i: chr(i) for i in range(65, 91)}
print(caracteres)

# 2)

codes = {}
for i in range(65, 91):
    codes[chr(i)] = i
print(codes)


## Exercice 5

# 1)

def moyenne1(L):
    s = 0
    for x in L:
        s += x
    return s / len(L)

# ou en utilisant la fonction sum :

def moyenne(L):
    return sum(L) / len(L)

# 2)

def moyennes(notes):
    moy = {}
    for eleve in notes:
        moy[eleve] = moyenne(notes[eleve])
    return moy


## Exercice 6

# 1) Il y a plusieurs manières de faire.

# On peut prendre les lettres de l'alphabet l'une après l'autre et compter le
# nombre d'occurrences de chaque lettre dans la chaîne :

def occurrences(c):
    alphabet = "abcdefghijklmnopqrstuvwxyz"
    d = {}
    for lettre in alphabet:
        d[lettre] = 0
        for l in c:
            if l == lettre:
                d[lettre] += 1
    return d

# L'inconvénient est qu'on parcourt 26 fois la chaîne.

# Dans la fonction suivante on remplit d'abord le dictionaire avec des 0 et on
# parcourt la chaîne une seule fois.

def occurrences(c):
    alphabet = "abcdefghijklmnopqrstuvwxyz"
    d = {}
    for lettre in alphabet:
        d[lettre] = 0
    for lettre in c:
        if lettre in alphabet:
            d[lettre] += 1
    return d

# Cette fonction est nettement plus rapide que la précédente.

# Enfin, comme pour les listes, on peut construire des dictionnaires par compréhension :

def occurrences(c):
    return {lettre: c.count(lettre) for lettre in "abcdefghijklmnopqrstuvwxyz"}

# c.count(lettre) compte le nombre de fois que lettre apparaît dans c.

# 2)

def lettre_frequence_max(c):
    maxi = 0
    d = occurrences(c)
    for lettre in d:
        if d[lettre] > maxi:
            maxi = d[lettre]
            lmax = lettre
    return lmax


## Exercice 7

# 1)

def est_sur(mot):
    if len(mot) < 10:
        return False
    chiffre = minuscule = majuscule = False
    for lettre in mot:
        if lettre in '0123456789':
            chiffre = True
        elif lettre in 'abcdefghijklmnopqrstuvwxyz':
            minuscule = True
        elif lettre in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ':
            majuscule = True
    return chiffre and minuscule and majuscule

# 2)

MOTSDEPASSE = {}

def inscription():
    login = input("Nom d'utilisateur : ")
    while True:    # permet de faire une boucle infinie
        mdp = input("Mot de passe : ")
        if est_sur(mdp):
            break  # pour sortir de la boucle
        print("Ce mot de passe n'est pas sûr.")
    while True:
        if mdp == input("Confirmer mot de passe : "):
            MOTSDEPASSE[login] = mdp
            break
    print("Inscription terminée")

# 3)

def login():
    login = input("Nom d'utilisateur : ")
    if login not in MOTSDEPASSE:
        return "Utilisateur non inscrit"
    while True:
        mdp = input("Mot de passe : ")
        if mdp == MOTSDEPASSE[login]:
            print("Accès autorisé")
            return True
        print("Mot de passe incorrect")


## Exercice 8

# L'énoncé ne le précise pas, mais on va considérer ici que les textes sont
# entièrement en minuscules.

# Les fonctions ord et chr sont pratiques ici.

def rot13(chaine):
    chaine_decodee = ''
    for c in chaine:
        n = ord(c)
        if 97 <= n <= 109:    # si c est entre 'a' et 'm'
            chaine_decodee += chr(n + 13)
        elif 110 <= n <= 122: # si c est entre 'n' et 'z'
            chaine_decodee += chr(n - 13)
        else:                 # on ne modifie pas les autres caractères
            chaine_decodee += c
    return chaine_decodee

# ou :

def rot132(chaine):
    chaine_decodee = ''
    for c in chaine:
        if 97 <= ord(c) <= 122:  # minuscules
            chaine_decodee += chr((ord(c)-84) % 26 + 97)
        else:                    # autres caractères
            chaine_decodee += c
    return chaine_decodee

    
## Exercice 9

def jours_2022():
    jours = ['lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi', 'samedi', 'dimanche']
    mois = ['janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet', 'août',
            'septembre', 'octobre', 'novembre', 'décembre']
    nb_jours = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
    numero_jour, numero_mois = 1, 0
    for i in range(365):
        print(jours[(i + 5) % 7] + ' ' + str(numero_jour) + ' ' + mois[numero_mois])
        numero_jour += 1
        if numero_jour > nb_jours[numero_mois]:
            numero_jour = 1
            numero_mois += 1


## Exercice 10

from random import choice

LISTE_DE_MOTS = ['exemple']  # à remplir !

def pendu():
    mot_secret = choice(LISTE_DE_MOTS)
    n = len(mot_secret)
    mot = '*' * n
    essais_restants = 10
    while True:
        print(mot)
        lettre = input('Lettre ? ')
        est_dedans = False
        for i in range(n):
            if lettre == mot_secret[i]:
                mot = mot[:i] + lettre + mot[i+1:] # on remplace * par la lettre
                est_dedans = True
        if not est_dedans:
            print('Pas dedans.')
            essais_restants -= 1
            if essais_restants > 1:
                print('Il reste', essais_restants, 'essais.')
            elif essais_restants == 1:
                print('Il reste 1 essai.')  # pour éviter les fautes d'orthographe !
            else:
                print('Perdu !')
                print('Le mot était', mot_secret + '.')
                break
        if mot == mot_secret:
            print(mot)
            print('Gagné !')
            break

# Le programme suivant permet de remplir la liste des mots à partir d'un fichier.

def construire_liste_de_mots(fichier, encodage='utf-8'):
    global LISTE_DE_MOTS
    f = open(fichier, encoding=encodage) # on ouvre le fichier
    texte = f.read() # on récupère le contenu du fichier
    f.close() # on ferme le fichier
    liste_mots = []
    for mot in texte.split():
        if len(mot) < 5:  # on élimine les mots trop petits
            continue # permet de passer à l'itération suivante
        if mot.isalpha() and mot not in liste_mots:  # pour avoir de "vrais" mots qu'on n'a pas déjà ajoutés
            mot = mot.lower()  # pour convertir les majuscules en minuscules
            liste_mots.append(mot)
        if len(liste_mots) > 1000:
            break
    LISTE_DE_MOTS = liste_mots


## Exercice 11

ALPHABET_MORSE = ".- -... -.-. -.. . ..-. --. .... .. .--- -.- .-.. -- -. --- .--. --.- .-. ... - ..- ...- .-- -..- -.-- --..".split()

def encodage_morse(chaine):
    chaine_morse = ''
    for c in chaine:
        if c == ' ':
            chaine_morse += ' '
        else:
            chaine_morse += ALPHABET_MORSE[ord(c) - 97] + ' '
    return chaine_morse[:-1]  # pour enlever l'espace final

def decodage_morse(chaine):
    chaine_clair = ''
    for c in chaine.split(' '):
        if c == '':  # espace entre deux mots
            chaine_clair += ' '
        else:
            chaine_clair += chr(ALPHABET_MORSE.index(c) + 97)
    return chaine_clair

# index permet de repérer la position d'un élément dans une liste ou une chaîne.

# On peut aussi utiliser des dictionnaires :

ALPHABET = 'abcdefghijklmnopqrstuvwxyz'
D_MORSE = {ALPHABET[i]: ALPHABET_MORSE[i] for i in range(26)}
D_MORSE_INVERSE = {ALPHABET_MORSE[i]: ALPHABET[i] for i in range(26)}

def encodage_morse(chaine):
    chaine_morse = ''
    for c in chaine:
        if c == ' ':
            chaine_morse += ' '
        else:
            chaine_morse += D_MORSE[c] + ' '
    return chaine_morse[:-1]  # pour enlever l'espace final

def decodage_morse(chaine):
    chaine_clair = ''
    for c in chaine.split(' '):
        if c == '':  # espace entre deux mots
            chaine_clair += ' '
        else:
            chaine_clair += D_MORSE_INVERSE[c]
    return chaine_clair
