Exo bac C7.EB2

Cet exercice porte sur la programmation Python, la programmation orientée objet, les tests et la structure de données pile.

Le mélange faro consiste à partager un jeu de cartes en deux moitiés et intercaler les cartes de ces deux moitiés.

Pour tout l’exercice on notera n le nombre de cartes et on considérera qu’il est pair.

Pour modéliser le jeu de cartes, on décide d’utiliser une pile qui sera une instance de la classe Pile dont on donne ici l’interface.

Le jeu de cartes est alors modélisé par une pile appelée jeu de sommet 1, puis 2 en dessous, et cætera jusqu’au bas de la pile qui contient \(n\), comme illustré sur la figure ci-dessous.

Figure 1. Pile représentant un jeu de cartes

Le mélange faro est réalisé ainsi :

Dans l’exemple suivant les contenus initiaux de jeu, moitie1 et moitie2 sont représentés ci-dessous :

Figure 2. Contenus initiaux des 3 piles

1. Représenter sur votre copie les contenus de ces trois piles à la fin de chaque étape du mélange faro.

Voici le code de la fonction produire_jeu qui prend en paramètre un entier n supposé pair et qui renvoie une instance de la classe Pile qui représente le jeu de cartes.

def produire_jeu(n):
    resultat = Pile()
    for i in range(...):
        resultat.empile(...)
    return resultat

2. Recopier et compléter sur votre copie le code de la fonction produire_jeu.

Ci-après figure le code de la fonction scinder_jeu qui prend en paramètres une instance de taille paire de la classe Pile qui est le jeu que l’on veut partager en 2 moitiés, un entier n qui est la taille de la pile et qui renvoie deux piles qui sont les deux moitiés du jeu.

def scinder_jeu(p, n):
    m1 = Pile()
    m2 = Pile
    for i in range(n):
        m1.empile(p.depile())
    for i in range(n):
        m2.empile(p.depile())
    return m1, m2

3. Ce code comporte des erreurs. Indiquer les numéros de lignes à rectifier ainsi que les rectifications à apporter.

4. Écrire une fonction recombiner qui prend en paramètres deux instances m1 et m2 de la classe Pile qui sont respectivement la première et la deuxième moitié d’un jeu de cartes et qui renvoie une instance de la classe Pile qui est le jeu obtenu en y empilant alternativement et dans cet ordre les éléments de m1 et de m2.

5. Écrire une fonction faro qui prend en paramètres une instance de la classe Pile qui est le jeu que l’on veut mélanger, un entier n qui est la taille de la pile et qui renvoie une instance de la classe Pile qui contient le jeu obtenu en appliquant le mélange faro.

Une propriété mathématique assure qu’étant donné un jeu de n cartes (n pair), en répétant suffisamment de fois le mélange faro, on finira par remettre le jeu dans l’ordre initial. On aimerait trouver, pour un entier n donné, ce nombre minimal de répétitions nécessaires. Pour cela, on considère une fonction identiques qui prend en arguments deux instances de la classe Pile et qui renvoie un booléen indiquant si ces deux piles ont les mêmes éléments, en même nombre et dans le même ordre.

La fonction identiques ne modifie pas les piles données en entrée.

Pour s’assurer que la fonction identiques fonctionne correctement, on a commencé à produire un jeu de tests :

p1 = Pile()
p1.empile(1)
p2 = Pile()
assert not identiques(p1, p2)

6. Compléter ce jeu de tests pour s’assurer que l’on couvre les cas suivants : les piles sont différentes, mais de même taille ; les piles sont identiques.

7. Écrire une fonction ordre_faro qui prend en paramètres un entier n pair et qui renvoie le plus petit nombre de répétitions du mélange faro pour qu’un jeu de n cartes soit remis dans son ordre initial.

Afficher la correction

1)

2)

def produire_jeu(n:int):
    resultat = Pile()
    for i in range(n,0,-1):
        resultat.empile(i)
    return resultat

Autre version possible :

def produire_jeu(n:int):
    resultat = Pile()
    for i in range(n):
        resultat.empile(n - i)
    return resultat

3)

Ligne 3 : Pour créer une instance d'un objet Pile, la syntaxe est m2 = Pile.

Lignes 4 et 6 : On souhaite avoir la moitié des cartes dans la pile m1 et l'autre moitié dans la pile m2, donc le nombre d'itératin à faire est n//2. Il faut donc écrire : for i in range(n // 2)

4)

def recombiner(m1:Pile, m2:Pile)->Pile:
    jeu = Pile()
    while not m1.est_vide() and not m2.est_vide():
        jeu.empile(m1.depile())
        jeu.empile(m2.depile())
    return jeu

5)

def faro(p:Pile, n:int)->Pile:
    m1, m2 = scinder_jeu(p, n)
    return recombiner(m1, m2)

6)

p1 = Pile()
p1.empile(1)
p2 = Pile()
assert not identiques(p1, p2)
p3 = Pile()
p3.empile(5)
p4 = Pile()
p4.empile(8)
assert not identiques(p3, p4)
p5 = Pile()
p5.empile(5)
p6 = Pile()
p6.empile(5)
assert identiques(p5, p6)

7)

def ordre_faro(n:int):
    jeu_initial = produire_jeu(n)
    jeu_melange = faro(produire_jeu(n), n)
    ordre = 1
    while not identiques(jeu_initial, jeu_melange):
        jeu_melange = faro(jeu_melange, n)
        ordre += 1
    return ordre