Aller au contenu

Dictionnaires

Chaque exercice est fourni avec un fichier Python à compléter et un énoncé « papier » distribué à l'élève et reproduit ci-dessous.

Remarques importantes

  1. Les exercices de cette page ne sont pas classés par ordre de « difficulté », cette notion de difficulté étant subjective et dépendante de chaque élève.

  2. Les solutions proposées ne sont que des propositions !
    Il existe d'autres codes valables pour répondre à chaque problème que ceux proposés ici : il ne faut pas hésiter à les soumettre à votre enseignant pour qu'il vous donne son avis sur les idées mises en oeuvre.

Dictionnaire cyclique ?

On considère au plus 26 personnes A, B, C, D, E, F ... qui peuvent s'envoyer des messages avec deux règles à respecter :

  • chaque personne ne peut envoyer des messages qu'à la même personne (éventuellement elle-même),
  • chaque personne ne peut recevoir des messages qu'en provenance d'une seule personne (éventuellement elle-même).

Voici un exemple - avec 6 personnes - de « plan d'envoi des messages » qui respecte les règles ci-dessus, puisque chaque personne est présente une seule fois dans chaque colonne :

  • A envoie ses messages à E
  • E envoie ses messages à B
  • B envoie ses messages à F
  • F envoie ses messages à A
  • C envoie ses messages à D
  • D envoie ses messages à C

Et le dictionnaire correspondant à ce plan d'envoi est le suivant :

plan_a = {'A': 'E', 'B': 'F', 'C': 'D', 'D': 'C', 'E': 'B', 'F': 'A'}
Sur le plan d'envoi plan_a des messages ci-dessus, il y a deux cycles distincts : un premier cycle avec A, E, B, F et un second cycle avec C et D.

En revanche, le plan d’envoi plan_b ci-dessous :

plan_b = {'A': 'C', 'B': 'F', 'C': 'E', 'D': 'A', 'E': 'B', 'F': 'D'}
comporte un unique cycle : A, C, E, B, F, D.

Dans ce cas, lorsqu’un plan d’envoi comporte un unique cycle, on dit que le plan d’envoi est cyclique.

Pour savoir si un plan d'envoi de messages comportant N personnes est cyclique, on peut utiliser l'algorithme ci-dessous :

On part de la personne A et on inspecte les N–1 successeurs dans le plan d'envoi :

  • Si un de ces N–1 successeurs est A lui-même, on a trouvé un cycle de taille inférieure ou égale à N–1. Il y a donc au moins deux cycles et le plan d'envoi n'est pas cyclique.

  • Si on ne retombe pas sur A lors de cette inspection, on a un unique cycle qui passe par toutes les personnes : le plan d'envoi est cyclique.

La fonction est_cyclique() doit prendre en paramètre un dictionnaire plan correspondant à un plan d'envoi de messages entre N personnes A, B, C, D, E, F ...(avec N <= 26). Elle renvoie Vrai si le plan d'envoi de messages est cyclique et Faux sinon.

Exemples

>>> est_cyclique({'A':'E', 'F':'A', 'C':'D', 'E':'B', 'B':'F', 'D':'C'})
False

>>> est_cyclique({'A':'E', 'F':'C', 'C':'D', 'E':'B', 'B':'F', 'D':'A'})
True
  1. Compléter la définition de la fonction est_cyclique().

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    def est_cyclique(plan):
        """
        plan - 
        Sortie: 
        >>> est_cyclique({'A':'E', 'F':'A', 'C':'D', 'E':'B', 'B':'F', 'D':'C'})
        False
        >>> est_cyclique({'A':'E', 'F':'C', 'C':'D', 'E':'B', 'B':'F', 'D':'A'})
        True
        """
        pass
    
    
    
    if __name__ == '__main__':
        import doctest
        doctest.testmod()
    
  2. Compléter le docstring de cette fonction.

  3. Ajouter au moins deux nouveaux tests avec affichage dans la partie principale du programme (le main).
Une solution possible
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
def est_cyclique(plan):
    """
    plan - dict, dictionnaire correspondant à un plan d'envoi de messages
           entre `N` personnes A, B, C, D, E, F ...(avec N <= 26)
    Sortie: bool - True si le plan d'envoi de messages est cyclique, False sinon 
    >>> est_cyclique({'A':'E', 'F':'A', 'C':'D', 'E':'B', 'B':'F', 'D':'C'})
    False
    >>> est_cyclique({'A':'E', 'F':'C', 'C':'D', 'E':'B', 'B':'F', 'D':'A'})
    True
    """
    personne = 'A'
    N = len(plan)
    for i in range(N-1):
        if plan[personne] == 'A':
            return False
        else:
            personne = plan[personne]
    return True


if __name__ == '__main__':
    import doctest
    doctest.testmod()

    print(est_cyclique({'A':'B', 'F':'C', 'C':'D', 'E':'A', 'B':'F', 'D':'E'}) == True)
    print(est_cyclique({'A':'B', 'F':'A', 'C':'D', 'E':'C', 'B':'F', 'D':'E'}) == False)

Occurrences des caractères d'une chaîne

L’occurrence d’un caractère dans un phrase est le nombre de fois où ce caractère est présent.

Exemples

  • L’occurrence du caractère 'o' dans 'bonjour' est 2 ;
  • L’occurrence du caractère 'b' dans 'Bébé' est 1 ;
  • L’occurrence du caractère 'B' dans 'Bébé' est 1 ;
  • L’occurrence du caractère ' ' dans 'Hello world !' est 2.

On cherche les occurrences des caractères dans une phrase. On souhaite stocker ces occurrences dans un dictionnaire dont les clefs seraient les caractères de la phrase et les valeurs associées l’occurrence de ces caractères.

La fonction occurrences_lettres() prend comme paramètre phrase, une chaîne de caractères. Cette fonction doit renvoyer un dictionnaire dont les clefs sont les caractères présents dans phrase et dont les valeurs associées sont les occurrences de ces caractères dans phrase.

Exemple

>>> occurrences_lettres('Hello world !')
{'H': 1, 'e': 1, 'l': 3, 'o': 2, ' ': 2, 'w': 1, 'r': 1, 'd': 1, '!': 1}
On rappelle que l’ordre des clefs n’a pas d’importance...

  1. Compléter la définition de la fonction occurrences_lettres().

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    def occurrences_lettres(phrase):
        """
        phrase - 
        Sortie: 
        >>> occurrences_lettres('Hello world !')
        {'H': 1, 'e': 1, 'l': 3, 'o': 2, ' ': 2, 'w': 1, 'r': 1, 'd': 1, '!': 1}
        """
        pass
    
    
    
    if __name__ == '__main__':
        import doctest
        doctest.testmod()
    
  2. Compléter le docstring de cette fonction.

  3. Ajouter au moins deux nouveaux tests avec affichage dans la partie principale du programme (le main).
Une solution possible
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
def occurrences_lettres(phrase):
    """
    phrase - str, chaîne de caractères quelconques
    Sortie: dict, dictionnaire tel que :
            - les clefs sont les caractères présents dans phrase
            - les valeurs associées sont les occurrences de ces caractères dans phrase.
    >>> occurrences_lettres('Hello world !')
    {'H': 1, 'e': 1, 'l': 3, 'o': 2, ' ': 2, 'w': 1, 'r': 1, 'd': 1, '!': 1}
    """
    dico = dict()
    for carac in phrase:
        if carac in dico.keys():
            dico[carac] += 1
        else:
            dico[carac] = 1
    return dico


if __name__ == '__main__':
    import doctest
    doctest.testmod()

    phrase = "Bonjour"
    print(occurrences_lettres(phrase) == {'B': 1, 'o': 2, 'n': 1, 'j': 1, 'u': 1, 'r': 1})

    phrase = "abracadabra"
    print(occurrences_lettres(phrase) == {'a': 5, 'b': 2, 'r': 2, 'c': 1, 'd': 1})

Élections

Les résultats d'un vote sont stockés dans un tableau.

Exemple

Pour trois candidats A, B et C et 10 votants :

urne = ['A', 'A', 'A', 'B', 'C', 'B', 'C', 'B', 'C', 'B']

La fonction depouille() doit permettre de compter le nombre de votes exprimés pour chaque candidat. Elle prend en paramètre un tableau et renvoie le résultat dans un dictionnaire dont les clés sont les noms des candidats et les valeurs le nombre de votes en leur faveur.

La fonction vainqueur() doit désigner le nom du ou des gagnants. Elle prend en paramètre un dictionnaire dont la structure est celle du dictionnaire renvoyé par la fonction depouille() et renvoie un tableau. Ce tableau peut donc contenir plusieurs éléments s’il y a des candidats ex-aequo.

Exemple

>>> urne = ['A', 'A', 'A', 'B', 'C', 'B', 'C', 'B', 'C', 'B']
>>> election = depouille(urne)
>>> election
{'A': 3, 'B': 4, 'C': 3}
>>> vainqueur(election)
['B']
On rappelle que l’ordre des clefs d'un dictionnaire n’a pas d’importance...

  1. Compléter la définition des fonctions depouille() et vainqueur().

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    def depouille(urne):
        """
        urne - 
        Sortie: 
        >>> urne = ['A', 'A', 'A','B', 'C', 'B', 'C','B', 'C', 'B']
        >>> depouille(urne)
        {'A': 3, 'B': 4, 'C': 3}
        """
        pass
    
    
    def vainqueur(election):
        """
        election - 
        Sortie: 
        >>> election = {'B': 4, 'A': 3, 'C': 3}
        >>> vainqueur(election)
        ['B']
        """
        pass
    
    
    
    if __name__ == '__main__':
        import doctest
        doctest.testmod()
    
  2. Compléter les docstring de ces fonctions.

  3. Ajouter au moins deux nouveaux tests avec affichage dans la partie principale du programme (le main).
Une solution possible
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
def depouille(urne):
    """
    urne - list, tableau de chaînes de caractères représentant des votes
           pour certains candidats
    Sortie: dict - Dictionnaire des occurrences des votes exprimés pour chaque candidat
    >>> urne = ['A', 'A', 'A','B', 'C', 'B', 'C','B', 'C', 'B']
    >>> depouille(urne)
    {'A': 3, 'B': 4, 'C': 3}
    """
    resultat = dict()
    for bulletin in urne:
        if bulletin in resultat.keys():
            resultat[bulletin] = resultat[bulletin] + 1
        else:
            resultat[bulletin] = 1
    return resultat

def vainqueur(election):
    """
    election - dict, Dictionnaire des occurrences des votes exprimés pour chaque candidat
    Sortie: list - Tableau des noms des candidats ayant eu le plus grand nombre de voix
    >>> election = {'B': 4, 'A': 3, 'C': 3}
    >>> vainqueur(election)
    ['B']
    """
    vainqueur = ''
    nmax = 0
    for candidat in election:
        if election[candidat] > nmax :
            nmax = election[candidat]
            vainqueur = candidat
    liste_finale = [nom for nom in election if election[nom] == nmax]
    return liste_finale


if __name__ == '__main__':
    import doctest
    doctest.testmod()

    urne = ['D', 'A', 'C', 'C', 'A', 'B', 'B', 'B', 'C', 'C', 'A', 'D', 'C', 'A', 'B']
    election = depouille(urne)
    print(election == {'D': 2, 'A': 4, 'C': 5, 'B': 4})
    print(vainqueur(election) == ['C'])

    urne = ['C', 'B', 'D', 'B', 'C', 'D', 'B', 'C', 'C', 'A', 'D', 'D', 'A', 'C', 'D']
    election = depouille(urne)
    print(election == {'C': 5, 'B': 3, 'D': 5, 'A': 2})
    print(vainqueur(election) == ['C', 'D'])

Minimum et maximum simultanés

Écrire une fonction rechercheMinMax() qui prend en paramètre un tableau non vide d'entiers non triés tab , et qui renvoie la plus petite et la plus grande valeur du tableau sous la forme d’un dictionnaire à deux clés 'min' et 'max'.

Exemple

>>> rechercheMinMax( [0, 1, 4, 2, -2, 9, 3, 1, 7, 1] )
{'min': -2, 'max': 9}

>>> rechercheMinMax( [] )
{'min': None, 'max': None}
  1. Compléter la définition de la fonction rechercheMinMax().

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    def rechercheMinMax(tab):
        """
        tab - 
        Sortie: 
        >>> rechercheMinMax( [0, 1, 4, 2, -2, 9, 3, 1, 7, 1] )
        {'min': -2, 'max': 9}
        >>> rechercheMinMax( [] )
        {'min': None, 'max': None}
        """
        pass
    
    
    if __name__ == '__main__':
        import doctest
        doctest.testmod()
    
  2. Compléter le docstring de cette fonction.

  3. Ajouter au moins deux nouveaux tests avec affichage dans la partie principale du programme (le main).
Une solution possible
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
def rechercheMinMax(tab):
    """
    tab - list, tableau de nombres non triés
    Sortie: dict, dictionnaire tel que :
            - les clefs sont 'min' et 'max'
            - les valeurs associées sont respectivement le plus petit et
            le plus grand des éléments de tab.
    >>> rechercheMinMax( [0, 1, 4, 2, -2, 9, 3, 1, 7, 1] )
    {'min': -2, 'max': 9}
    >>> rechercheMinMax( [] )
    {'min': None, 'max': None}
    """
    if len(tab) == 0:
        return {'min': None, 'max': None}
    else:
        dico = {'min': tab[0], 'max': tab[0]}
        for elt in tab:
            if elt < dico['min']:
                dico['min'] = elt
            if elt > dico['max']:
                dico['max'] = elt
    return dico


if __name__ == '__main__':
    import doctest
    doctest.testmod()

    print(rechercheMinMax( [-1, -7, 5, 9, -9, -8, 4, -5, -3, 4]  ) == {'min': -9, 'max': 9} )
    from random import randint
    tableau = [randint(-10, 10) for i in range(10)]
    print(tableau)
    print(rechercheMinMax(tableau))

Plus grande valeur associée

Sur le réseau social TipTop, on s’intéresse au nombre de « like » des abonnés. Les données sont stockées dans des dictionnaires où les clés sont les pseudos et les valeurs correspondantes sont les nombres de « like » comme ci-dessous :

{'Bob': 102, 'Ada': 201, 'Alice': 103, 'Tim': 50}

Écrire une fonction max_dico() qui :

  • prend en paramètre un dictionnaire dico non vide dont les clés sont des chaînes de caractères et les valeurs associées sont des entiers ;
  • renvoie un tuple dont :
    • la première valeur est la clé du dictionnaire associée à la valeur maximale ;
    • la seconde valeur est la valeur maximale présente dans le dictionnaire.

Si le maximum apparaît plusieurs fois, le « plus petit » pseudo par ordre alphabétique est renvoyé.

Exemple

>>> max_dico({'Bob': 102, 'Ada': 201, 'Alice': 103, 'Tim': 50})
('Ada', 201)

>>> max_dico({'Alan': 201, 'Ada': 201, 'Alice': 103, 'Tim': 50})
('Ada', 201)

>>> max_dico({})
AssertionError: Le dictionnaire est vide !
  1. Compléter la définition de la fonction max_dico(), sans oublier d'ajouter l'assertion signalée dans l'exemple précédent.

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    def max_dico(dico):
        """
        dico - 
        Sortie: 
        >>> max_dico({'Bob': 102, 'Ada': 201, 'Alice': 103, 'Tim': 50})
        ('Ada', 201)
        >>> max_dico({'Alan': 201, 'Ada': 201, 'Alice': 103, 'Tim': 50})
        ('Ada', 201)
        """
        pass
    
    
    if __name__ == '__main__':
        import doctest
        doctest.testmod()
    
  2. Compléter le docstring de cette fonction.

  3. Ajouter au moins deux nouveaux tests avec affichage dans la partie principale du programme (le main).
Une solution possible
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
def max_dico(dico):
    """
    dico - dict, dictionnaire associant à une chaîne de caractères
            (représentant le pseudo) un entier (représentant le nombre
            de "likes")
    Sortie: tuple - Couple constitué du pseudo associé au plus grand
            nombre de like et de ce plus grand nombre de like
    >>> max_dico({'Bob': 102, 'Ada': 201, 'Alice': 103, 'Tim': 50})
    ('Ada', 201)
    >>> max_dico({'Alan': 201, 'Ada': 201, 'Alice': 103, 'Tim': 50})
    ('Ada', 201)
    """
    assert len(dico) !=0, "Le dictionnaire est vide !"
    nb_likes_maxi = 0
    pseudo_maxi = ""
    for pseudo in dico.keys():
        nb_likes = dico[pseudo]
        if nb_likes > nb_likes_maxi:
            pseudo_maxi = pseudo
            nb_likes_maxi = nb_likes
        elif nb_likes == nb_likes_maxi and pseudo < pseudo_maxi:
            pseudo_maxi = pseudo
    return pseudo_maxi, nb_likes_maxi


if __name__ == '__main__':
    import doctest
    doctest.testmod()

    print(max_dico({'Alan': 222, 'Ada': 201, 'Eve': 220, 'Tim': 50}) == ('Alan', 222))
    print(max_dico({'Alan': 222}) == ('Alan', 222))

Plus grande occurrence

Écrire une fonction occurrence_max() prenant en paramètres une chaîne de caractères chaine et qui renvoie le caractère le plus fréquent de la chaîne. La chaine ne contient que des lettres en minuscules sans accent.

On pourra s’aider de la chaîne

alphabet = 'abcdefghijklmnopqrstuvwxyz'
et d'un tableau occurrence de 26 éléments où l’on mettra dans occurrence[i] le nombre d’apparitions de alphabet[i] dans la chaine. Puis on calculera l’indice k d’un maximum du tableau occurrence et on affichera alphabet[k]. Le caractère le « petit » sera renvoyé en cas d'égalité d'occurrence.

Exemple

>>> ch = "je suis en premiere et je souhaite poursuivre des etudes pour devenir expert en informatique"
>>> occurrence_max(ch)
'e'
  1. Compléter la définition de la fonction occurrence_max(), sans oublier d'ajouter l'assertion signalée dans l'exemple précédent.

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    def occurrence_max(chaine):
        """
        chaine - 
        Sortie: 
        >>> ch = "je suis en premiere et je souhaite poursuivre des etudes pour devenir expert en informatique"
        >>> occurrence_max(ch)
        'e'
        """
        alphabet = 'abcdefghijklmnopqrstuvwxyz'
        pass
    
    
    if __name__ == '__main__':
        import doctest
        doctest.testmod()
    
  2. Compléter le docstring de cette fonction.

  3. Ajouter au moins deux nouveaux tests avec affichage dans la partie principale du programme (le main).
Une solution possible avec un dictionnaire
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
def occurrence_max(chaine):
    """
    chaine - str, chaîne de caractères
    Sortie: str - le caractère le plus fréquent de la chaîne
    >>> ch = "je suis en premiere et je souhaite poursuivre des etudes pour devenir expert en informatique"
    >>> occurrence_max(ch)
    'e'
    """
    alphabet = 'abcdefghijklmnopqrstuvwxyz'

    occurrence = {alphabet[i]:0 for i in range(26)}
    for carac in chaine:
        if carac in alphabet :
            occurrence[carac] += 1
    maxi = 0
    for clef in occurrence.keys():
        if occurrence[clef] > maxi:
            maxi = occurrence[clef]
            lettre_maxi = clef
    return lettre_maxi


if __name__ == '__main__':
    import doctest
    doctest.testmod()

    print(occurrence_max('oiseau') == 'a')
    print(occurrence_max('hello world') == 'l')
Une solution possible avec une fonction supplémentaire
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
def indice(carac, alphabet):
    """
    carac - str, un caractère
    alphabet - list, tableau des 26 lettres de l'alphabet
    Sortie: int - indice de carac dans alphabet
    """
    for i in range(26):
        if alphabet[i] == carac:
            return i
    return -1

def occurrence_max(chaine):
    """
    chaine - str, chaîne de caractères
    Sortie: str - le caractère le plus fréquent de la chaîne
    >>> ch = "je suis en premiere et je souhaite poursuivre des etudes pour devenir expert en informatique"
    >>> occurrence_max(ch)
    'e'
    """
    alphabet = 'abcdefghijklmnopqrstuvwxyz'

    occurrence = [0]*26
    for carac in chaine:
        i = indice(carac, alphabet)
        if i != -1:
            occurrence[i] += 1
    maxi = occurrence[0]
    indice_maxi = 0
    for i in range(1, 26):
        if occurrence[i] > maxi:
            maxi = occurrence[i]
            indice_maxi = i
    return alphabet[indice_maxi]


if __name__ == '__main__':
    import doctest
    doctest.testmod()

    print(occurrence_max('oiseau') == 'a')
    print(occurrence_max('hello world') == 'l')
Une solution possible avec les fonctions chr() et ord()

On rappelle que ord('a') vaut 97.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
def occurrence_max(chaine):
    """
    chaine - str, chaîne de caractères
    Sortie: str - le caractère le plus fréquent de la chaîne
    >>> ch = "je suis en premiere et je souhaite poursuivre des etudes pour devenir expert en informatique"
    >>> occurrence_max(ch)
    'e'
    """
    alphabet = 'abcdefghijklmnopqrstuvwxyz'

    occurrence = [0]*26
    for carac in chaine:
        if 'a' <= carac <= 'z':
            occurrence[ord(carac)-97] += 1
    maxi = occurrence[0]
    indice_maxi = 0
    for i in range(1, 26):
        if occurrence[i] > maxi:
            maxi = occurrence[i]
            indice_maxi = i
    return chr(indice_maxi+97)


if __name__ == '__main__':
    import doctest
    doctest.testmod()

    print(occurrence_max('oiseau') == 'a')
    print(occurrence_max('hello world') == 'l')

Sélection dans une table de données

On considère des tables (des tableaux de dictionnaires) qui contiennent des enregistrements relatifs à des animaux hébergés dans un refuge. Les attributs des enregistrements sont 'nom', 'espece', 'age', 'enclos'.

Voici un exemple d'une telle table :

animaux = [ {'nom':'Medor', 'espece':'chien', 'age':5, 'enclos':2},
            {'nom':'Titine', 'espece':'chat', 'age':2, 'enclos':5},
            {'nom':'Tom', 'espece':'chat', 'age':7, 'enclos':4},
            {'nom':'Belle', 'espece':'chien', 'age':6, 'enclos':3},
            {'nom':'Mirza', 'espece':'chat', 'age':6, 'enclos':5}]

Programmer une fonction selection_enclos() qui :

  • prend en paramètres :
    • une table table_animaux contenant des enregistrements relatifs à des animaux (comme dans l'exemple ci-dessus),
    • un numéro d'enclos num_enclos ;
  • renvoie une table contenant les enregistrements de table_animaux dont l'attribut 'enclos' est num_enclos.

Exemples

Avec la table `animaux ci-dessus :

>>> selection_enclos(animaux, 5)
[{'nom': 'Titine', 'espece': 'chat', 'age': 2, 'enclos': 5},
 {'nom': 'Mirza', 'espece': 'chat', 'age': 6, 'enclos': 5}]

>>> selection_enclos(animaux, 2)
[{'nom': 'Medor', 'espece': 'chien', 'age': 5, 'enclos': 2}]

>>> selection_enclos(animaux, 7)
[]
  1. Compléter la définition de la fonction selection_enclos().

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    def selection_enclos(table_animaux, num_enclos):
        """
        table_animaux - 
        num_enclos - 
        Sortie: 
        >>> selection_enclos(animaux, 5)
        [{'nom': 'Titine', 'espece': 'chat', 'age': 2, 'enclos': 5}, {'nom': 'Mirza', 'espece': 'chat', 'age': 6, 'enclos': 5}]
        >>> selection_enclos(animaux, 2)
        [{'nom': 'Medor', 'espece': 'chien', 'age': 5, 'enclos': 2}]
        >>> selection_enclos(animaux, 7)
        []
        """
        pass
    
    
    
    if __name__ == '__main__':
        import doctest
        doctest.testmod()
    
  2. Compléter le docstring de cette fonction.

  3. Ajouter au moins deux nouveaux tests avec affichage dans la partie principale du programme (le main).
Une solution possible
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
def selection_enclos(table_animaux, num_enclos):
    """
    table_animaux - list, tableau de dictionnaires représentant des animaux et
                    ayant au moins la clef 'enclos' associée à une valeur entière
    num_enclos - int, numéro d'enclos
    Sortie: list - table contenant les enregistrements de table_animaux dont
            l'attribut 'enclos' est associé à la valeur num_enclos
    >>> selection_enclos(animaux, 5)
    [{'nom': 'Titine', 'espece': 'chat', 'age': 2, 'enclos': 5}, {'nom': 'Mirza', 'espece': 'chat', 'age': 6, 'enclos': 5}]
    >>> selection_enclos(animaux, 2)
    [{'nom': 'Medor', 'espece': 'chien', 'age': 5, 'enclos': 2}]
    >>> selection_enclos(animaux, 7)
    []
    """
    return [animal for animal in table_animaux if animal['enclos'] == num_enclos]


if __name__ == '__main__':
    animaux = [ {'nom': 'Medor', 'espece': 'chien', 'age': 5, 'enclos': 2},
                {'nom': 'Titine', 'espece': 'chat', 'age': 2, 'enclos': 5},
                {'nom': 'Tom', 'espece': 'chat', 'age': 7, 'enclos': 4},
                {'nom': 'Belle', 'espece': 'chien', 'age': 6, 'enclos': 3},
                {'nom': 'Mirza', 'espece': 'chat', 'age': 6, 'enclos': 5}]
    import doctest
    doctest.testmod()

    print(selection_enclos(animaux, 3) == [{'nom': 'Belle', 'espece': 'chien', 'age': 6, 'enclos': 3}])
    print(selection_enclos(animaux, 1) == [])

Moyennes pondérées

Un professeur de NSI décide de gérer les résultats de sa classe sous la forme d’un dictionnaire :

  • les clefs sont les noms des élèves ;
  • les valeurs sont des dictionnaires dont les clefs sont les types d’épreuves et les valeurs sont les notes obtenues associées à leurs coefficients.

Exemple

Voici un exemple d'un tel dictionnaire, dans lequel L’élève de nom « Durand » a obtenu la note de 8 au DS2 dont le coefficient est 4.

resultats = {'Dupont': {'DS1' : [15.5, 4],
                     'DM1' : [14.5, 1],
                     'DS2' : [13, 4],
                     'PROJET1' : [16, 3],
                     'DS3' : [14, 4] },
             'Durand': {'DS1' : [6 , 4],
                     'DM1' : [14.5, 1],
                     'DS2' : [8, 4],
                     'PROJET1' : [9, 3],
                     'IE1' : [7, 2],
                     'DS3' : [8, 4],
                     'DS4' : [15, 4]} }

Le professeur crée une fonction nommée moyennes() qui prend en paramètre un tel dictionnaire et qui renvoie un dictionnaire qui associe à chaque élève sa moyenne arrondie au dixième.

Exemples

>>> moyennes(resultats)
{'Dupont': 14.5, 'Durand': 9.2}
Aide pour l'arrondi

La fonction pré-programmée round() permet d'arrondir au nombre de décimales suohaité, passé en paramètre :

>>> round(1.873, 1)
1.9

>>> round(1.873, 2)
1.87

  1. Compléter la définition de la fonction moyennes().

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    def moyennes(resultats):
        """
        resultats - 
        Sortie: 
        >>> moyennes(resultats)
        {'Dupont': 14.5, 'Durand': 9.2}
        """
        pass
    
    
    
    if __name__ == '__main__':
        resultats = {'Dupont':{'DS1' : [15.5, 4],
                               'DM1' : [14.5, 1],
                               'DS2' : [13, 4],
                               'PROJET1' : [16, 3],
                               'DS3' : [14, 4] },
                     'Durand':{'DS1' : [6 , 4],
                               'DM1' : [14.5, 1],
                               'DS2' : [8, 4],
                               'PROJET1' : [9, 3],
                               'IE1' : [7, 2],
                               'DS3' : [8, 4],
                               'DS4' : [15, 4]}}
        import doctest
        doctest.testmod()
    
  2. Compléter le docstring de cette fonction.

  3. Ajouter au moins un nouveau test avec affichage dans la partie principale du programme (le main).
Une solution possible
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
def moyennes(resultats):
    """
    resultats - dict, dictionnaire de noms associés à un dictionnaire recensant
                les évaluations passées associées à leur note et au coefficient
                de l'évaluation
    Sortie: dict - dictionnaire associant à chaque nom de resultats sa moyenne
            arrondie au dixième
    >>> moyennes(resultats)
    {'Dupont': 14.5, 'Durand': 9.2}
    """
    result = {}
    for nom in resultats.keys():
        notes = resultats[nom]
        total_points = 0
        total_coefficients = 0
        for valeurs  in notes.values():
            note, coefficient = valeurs
            total_points = total_points + note * coefficient
            total_coefficients = total_coefficients + coefficient
        moy = round( total_points / total_coefficients , 1 )
        result[nom] = moy
    return result



if __name__ == '__main__':
    resultats = {'Dupont':{'DS1' : [15.5, 4],
                           'DM1' : [14.5, 1],
                           'DS2' : [13, 4],
                           'PROJET1' : [16, 3],
                           'DS3' : [14, 4] },
                 'Durand':{'DS1' : [6 , 4],
                           'DM1' : [14.5, 1],
                           'DS2' : [8, 4],
                           'PROJET1' : [9, 3],
                           'IE1' : [7, 2],
                           'DS3' : [8, 4],
                           'DS4' : [15, 4]}}
    import doctest
    doctest.testmod()


    resultats = {'Dupont':{'DS1' : [15.5, 4],
                           'DM1' : [14.5, 1],
                           'DS2' : [13, 4],
                           'PROJET1' : [16, 3],
                           'DS3' : [14, 4] },
                 'Durand':{'DS1' : [6 , 4],
                           'DM1' : [14.5, 1],
                           'DS2' : [8, 4],
                           'PROJET1' : [9, 3],
                           'IE1' : [7, 2],
                           'DS3' : [8, 4],
                           'DS4' : [15, 4]},
                 'Duval': {'DS1' : [20 , 4],
                           'DM1' : [18, 1],
                           'DS2' : [14, 4],
                           'PROJET1' : [12, 3],
                           'IE1' : [10, 2],
                           'DS3' : [8, 4],
                           'DS4' : [6, 4]}}

    print(moyennes(resultats) == {'Dupont': 14.5, 'Durand': 9.2, 'Duval': 12.1})

Code alphabétique d'un mot

On affecte à chaque lettre de l’alphabet un code selon le tableau ci-dessous :

A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26

Pour un mot donné, on détermine d’une part son code alphabétique concaténé, obtenu par la juxtaposition des codes de chacun de ses caractères, et d’autre part, son code additionné, qui est la somme des codes de chacun de ses caractères.
Par ailleurs, on dit que ce mot est « parfait » si le code additionné divise le code concaténé.

Exemples :

  • Pour le mot "PAUL", le code concaténé est la chaîne '1612112', soit l’entier 1 612 112.
    Son code additionné est l’entier 50 car 16 + 1 + 21 + 12 = 50.
    50 ne divise pas l’entier 1 612 112 ; par conséquent, le mot "PAUL" n’est pas parfait.

  • Pour le mot "ALAIN", le code concaténé est la chaîne '1121914', soit l’entier 1 121 914.
    Son code additionné est l’entier 37 car 1 + 12 + 1 + 9 + 14 = 37.
    37 divise l’entier 1 121 914 ; par conséquent, le mot "ALAIN" est parfait.

La fonction est_parfait prend comme argument une chaîne de caractères mot (en lettres majuscules) et renvoie un triplet constitué du code additionné de mot, du code alphabétique concaténé, ainsi qu’un booléen qui indique si mot est parfait ou pas.

Exemples

Attention aux types...

>>> est_parfait("PAUL")
(50, 1612112, False)

>>> est_parfait("ALAIN")
(37, 1121914, True)

  1. Compléter la définition de la fonction est_parfait().

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    def est_parfait(mot) :
        """
        mot - 
        Sortie: 
        >>> est_parfait("PAUL")
        (50, 1612112, False)
        >>> est_parfait("ALAIN")
        (37, 1121914, True)
        """
        pass
    
    
    
    if __name__ == '__main__':
        dico = {"A":1, "B":2, "C":3, "D":4, "E":5, "F":6, "G":7,
                "H":8, "I":9, "J":10, "K":11, "L":12, "M":13,
                "N":14, "O":15, "P":16, "Q":17, "R":18, "S":19,
                "T":20, "U":21,"V":22, "W":23, "X":24, "Y":25, "Z":26}
    
        import doctest
        doctest.testmod()
    
  2. Compléter le docstring de cette fonction.

  3. Ajouter au moins deux nouveaux tests avec affichage dans la partie principale du programme (le main).
Une solution possible
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
def est_parfait(mot) :
    """
    mot - str, chaîne de caractères comportant uniquement des lettres majuscules
    Sortie: tuple, triplet constitué constitué du code additionné de mot (int),
            de son code alphabétique concaténé et d'un booléen indiquant si mot
            est parfait ou pas.
    >>> est_parfait("PAUL")
    (50, 1612112, False)
    >>> est_parfait("ALAIN")
    (37, 1121914, True)
    """
    code_c = ""
    code_a = 0
    for c in mot :
        code_c = code_c + str(dico[c])
        code_a = code_a + dico[c]
    code_c = int(code_c)
    if code_c%code_a == 0 :
        mot_est_parfait = True
    else :
        mot_est_parfait = False
    return code_a, code_c, mot_est_parfait


if __name__ == '__main__':
    dico = {"A":1, "B":2, "C":3, "D":4, "E":5, "F":6, "G":7,
            "H":8, "I":9, "J":10, "K":11, "L":12, "M":13,
            "N":14, "O":15, "P":16, "Q":17, "R":18, "S":19,
            "T":20, "U":21,"V":22, "W":23, "X":24, "Y":25, "Z":26}

    import doctest
    doctest.testmod()

    print(est_parfait("NICOLAS") == (73, 14931512119, False))
    print(est_parfait("ELSA") == (37, 512191, True))