Jeu de la ronde (2)

Des enfants jouent dans une cour de récréation : ils se placent en rond et choisissent au hasard l'un d'entre eux.

A partir de là, la règle est simple :

  • Le premier enfant tape sur l'épaule de son voisin de gauche : celui-ci est éliminé. Au début l'enfant \(1\) élimine donc l'enfant \(2\) ;

  • On passe à l'enfant restant suivant et l'on recommence : il élimine celui situé à sa gauche. Dans l'exemple, l'enfant \(3\) élimine le \(4\) ;

  • On continue encore et encore jusqu'à ce qu'il ne reste plus qu'un seul enfant : c'est le gagnant !

Le jeu de la ronde

Dans le cas où \(13\) enfants jouent comme sur la figure, le gagnant est l'enfant \(11\).

La question est simple : qui va gagner ?

On représente la ronde des joueurs à l'aide d'une liste chaînée circulaire. Pour ce faire on fournit la classe Joueur possédant deux attributs :

  • le nom du joueur (la chaîne de caractères nom) ;

  • le successeur de ce joueur (attribut successeur du type Joueur).

La fonction nouvelle_ronde prend en paramètre la liste des noms des joueurs triée du premier joueur au dernier et crée la liste chaînée circulaire les représentant. Cette fonction renvoie l'objet représentant le premier joueur.

La fonction affiche_ronde prend en paramètre un objet de type Joueur et renvoie la chaîne de caractères illustrant la ronde débutant par le joueur représenté par cet objet.

🐍 Console Python
>>> noms = ["Riri", "Fifi", "Loulou"]
>>> premier = nouvelle_ronde(noms)
>>> premier.nom
'Riri'
>>> premier.successeur.nom
'Fifi'
>>> affiche_ronde(premier)
╭→ Riri → Fifi → Loulou ╮
╰───────────────────────╯
>>> premier.successeur.successeur.successeur == premier
True

La classe Joueur, la fonction nouvelle_ronde et la fonction affiche_ronde sont déjà chargées dans l'éditeur. Il est inutile de les importer.

La classe Joueur

On fournit pour information la classe Joueur et les fonctions nouvelle_ronde et affiche_ronde :

🐍 Script Python
class Joueur:
    def __init__(self, nom, successeur=None):
        self.nom = nom
        self.successeur = successeur


def nouvelle_ronde(noms):
    assert len(noms) > 0, f"La liste noms doit contenir au moins un élément"
    premier = Joueur(noms[0])
    actuel = premier
    for i in range(1, len(noms)):
        prochain = Joueur(noms[i])
        actuel.successeur = prochain
        actuel = prochain
    prochain.successeur = premier
    return premier


def affiche_ronde(joueur):
    noms = [joueur.nom]
    actuel = joueur.successeur
    while actuel.nom != joueur.nom:
        noms.append(actuel.nom)
        actuel = actuel.successeur
    total = "╭→ " + " → ".join(noms)
    return total + " ╮\n╰" + "─" * (len(total)) + "╯"

Écrire la fonction gagnant qui prend en paramètre la liste contenant les noms des joueurs et renvoie le nom du joueur gagnant.

On garantit que la liste est non vide et que les noms des joueurs sont tous distincts.

Exemples
>>> noms = ["Riri", "Fifi", "Loulou"]
>>> gagnant(noms)
'Loulou'
>>> noms = ["Paul", "John", "Ringo", "Georges"]
>>> gagnant(noms)
'Paul'
>>> noms = ["Brian", "Ian", "Mick", "Keith", "Dick"]
>>> gagnant(noms)
'Mick'

###(Dés-)Active le code après la ligne # Tests (insensible à la casse)
(Ctrl+I)
Entrer ou sortir du mode "deux colonnes"
(Alt+: ; Ctrl pour inverser les colonnes)
Entrer ou sortir du mode "plein écran"
(Esc)
Tronquer ou non le feedback dans les terminaux (sortie standard & stacktrace / relancer le code pour appliquer)
Si activé, le texte copié dans le terminal est joint sur une seule ligne avant d'être copié dans le presse-papier
Évaluations restantes : 10/10

.1280135tf4)2rj3sa!o iugm1P6pnl7h.e=cy:v(wS/b_dk050O0C0c0l0p0y0k0o0E0y0l0k0k0D010c0p0w010406050k0q0s0s0l0h0F040K0n0y0q0*0n0x050L0;0?0^0`0/0w04131a051d0L1d1f1a0/0O0p0H0Y0!0$0(0A0p0r0A0y1t0A0c0-050T0M0y0C1o0#0%011s1u1w1u0c1C1E1A0c0M0n0O0`1B0h1b0c0A0Y0}0k0w0l0x0(0g011G1q010d0V0C0x0l0s0C1A1(1*1/1I1=1E1^1`0-0a0o0u0h0n0w0n0k0p100x0o0R1$0h0h0C0E2f131}0x1b0L1!2s0c1Y1X1Z0O1 0(1w0x1@2c1A1l1n0Z1H2C0p2E0x1U1m1A0w2l1b2q2s2W0:1)2g2K1:2P0h0@0y0-0t2p2!0.2Z1~2$1I2(2*0-0g2.1*2:2q2B012^0l2+040j2|2r0/2 2?0(32340e372~2!303d0-0b3g393i3b310n2)330-0v3n2;2#1p2@3s2_040z3g1c2U132I2v0O2z300E1U1{1b3K1e3I2Y142/053P0R2V3p3A0(0P0-0R0d3G3a3(010J0-0o3.3%2L310d0-0r0l0r1^0x0c3^2=3:0,040I443z3`0x0-2P0s0k4a30470f0G3n0o4o3@3/4c0-0i0n0q0C0q0h3g4q3_1:0n0-0D4A3y3j4e4v0H0C0y1E0N290x0R4i3q47493X2}4I3q4d044f4h4Y2r4!460-0f4n4p4,3`3*040J1s1E4H4r2%4t4v4x4z4*3$453`4E040B4U3:4$0;0E0E0C0$514|4C1I570m4G534B554~044u4w4y5a3`474m53064p5D5q4b5s5u5i534=4D0-595K4}2@0-5d5f5h5w5p5L5l4F5j5r5R5t505W2Y5Q0(575O5+5k3c5S0q5e5g0k5J5:5$5-5N5x5s5T5_5{2/5C5E4o5Y5=5(5v522W5F30575o6e69314 6c605Z586o6a625V6d6566685,014@2l0c4y125X6z4$5I5*3Y6z5.6r6l4%0n0s3x0L3!0C2s2T6W3J1m3L2v2x2t1T1V2v0l1D6Z0L3K0/6:0S0U0W04.

###(Dés-)Active le code après la ligne # Tests (insensible à la casse)
(Ctrl+I)
Entrer ou sortir du mode "deux colonnes"
(Alt+: ; Ctrl pour inverser les colonnes)
Entrer ou sortir du mode "plein écran"
(Esc)
Tronquer ou non le feedback dans les terminaux (sortie standard & stacktrace / relancer le code pour appliquer)
Si activé, le texte copié dans le terminal est joint sur une seule ligne avant d'être copié dans le presse-papier
Évaluations restantes : 10/10

.1280135tf4)2rj3sa!o iugm1P6pnl7h.e=cy:v(wS/b_dk050O0C0c0l0p0y0k0o0E0y0l0k0k0D010c0p0w010406050k0q0s0s0l0h0F040K0n0y0q0*0n0x050L0;0?0^0`0/0w04131a051d0L1d1f1a0/0O0p0H0Y0!0$0(0A0p0r0A0y1t0A0c0-050T0M0y0C1o0#0%011s1u1w1u0c1C1E1A0c0M0n0O0`1B0h1b0c0A0Y0}0k0w0l0x0(0g011G1q010d0V0C0x0l0s0C1A1(1*1/1I1=1E1^1`0-0a0o0u0h0n0w0n0k0p100x0o0R1$0h0h0C0E2f131}0x1b0L1!2s0c1Y1X1Z0O1 0(1w0x1@2c1A1l1n0Z1H2C0p2E0x1U1m1A0w2l1b2q2s2W0:1)2g2K1:2P0h0@0y0-0t2p2!0.2Z1~2$1I2(2*0-0g2.1*2:2q2B012^0l2+040j2|2r0/2 2?0(32340e372~2!303d0-0b3g393i3b310n2)330-0v3n2;2#1p2@3s2_040z3g1c2U132I2v0O2z300E1U1{1b3K1e3I2Y142/053P0R2V3p3A0(0P0-0R0d3G3a3(010J0-0o3.3%2L310d0-0r0l0r1^0x0c3^2=3:0,040I443z3`0x0-2P0s0k4a30470f0G3n0o4o3@3/4c0-0i0n0q0C0q0h3g4q3_1:0n0-0D4A3y3j4e4v0H0C0y1E0N290x0R4i3q47493X2}4I3q4d044f4h4Y2r4!460-0f4n4p4,3`3*040J1s1E4H4r2%4t4v4x4z4*3$453`4E040B4U3:4$0;0E0E0C0$514|4C1I570m4G534B554~044u4w4y5a3`474m53064p5D5q4b5s5u5i534=4D0-595K4}2@0-5d5f5h5w5p5L5l4F5j5r5R5t505W2Y5Q0(575O5+5k3c5S0q5e5g0k5J5:5$5-5N5x5s5T5_5{2/5C5E4o5Y5=5(5v522W5F30575o6e69314 6c605Z586o6a625V6d6566685,014@2l0c4y125X6z4$5I5*3Y6z5.6r6l4%0n0s3x0L3!0C2s2T6W3J1m3L2v2x2t1T1V2v0l1D6Z0L3K0/6:0S0U0W04.