Aller au contenu

I. Modulo⚓

Distribuer des costumes pour un spectacle⚓

Question

La mairie d'une ville a décidé d'organiser un spectacle en plein air pour le 14 juillet. Pour cela, elle va faire appel à de nombreux figurants et distribuer à chacun d'eux un costume bleu, ou blanc, ou rouge. Ne sachant pas à l'avance combien de personnes vont se présenter, l'organisateur du spectacle a décidé, afin d'équilibrer à peu prÚs les couleurs, de procéder de la façon suivante : le premier figurant arrivé recevra un costume bleu, le second un blanc, le troisiÚme un rouge, le quatriÚme un bleu, le cinquiÚme un blanc, etc.

couleurs costumes

Constatant le succĂšs de la fĂȘte du 14 juillet, la mairie a dĂ©cidĂ© d'organiser d'autres spectacles de ce genre, avec distribution de costumes sur le mĂȘme principe. Chaque spectacle a des costumes spĂ©cifiques.

Nicolas fait la queue pour recevoir son maillot. Curieux et impatient, il se demande de quelle couleur il sera. Il sait juste oĂč il se trouve dans la queue (son rang) et les couleurs des maillots distribuĂ©s (la liste couleurs).

Pouvez-vous l’aider Ă  dĂ©terminer la couleur de son maillot ?

Compléter la fonction costume ci-dessous. Elle prend en paramÚtre rang qui est le rang d'arrivée du figurant, et couleurs qui est la liste des couleurs des costumes. Elle doit renvoyer la couleur du costume donné au figurant correspondant.

On garantit que la liste couleurs n'est pas vide, que rang est un entier supérieur ou égal à 1, et qu'on dispose de suffisemment de costumes pour tout le monde.

Par exemple :

Python Console Session
>>> costume(2, ["bleu", "blanc", "rouge"])
'blanc'
>>> costume(8, ["rose", "vert", "orange", "bleu"])
'bleu'

👉 Vous pouvez tester les ### en haut Ă  droite de la fenĂȘtre.

###(DĂ©s-)Active le code aprĂšs la ligne # Tests (insensible Ă  la casse)
(Ctrl+I)
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 : 4/4

ENCRYPTION_TOKEN

Solution & Remarques

🐍 Proposition de correction
1
2
3
4
def costume(rang, couleurs):
    n = len(couleurs)
    indice = (rang - 1) % n
    return couleurs[indice]

Remarques :

La premiĂšre chose Ă  noter dans cet exercice est la diffĂ©rence entre le rang d’un figurant et l’indice d’un Ă©lĂ©ment dans une liste : le premier commence Ă  1, le second Ă  0.

Ainsi, avec la liste de couleurs ["bleu", "blanc", "rouge"], s’il n’y avait que 3 figurants avec les rangs 1, 2 et 3 les indices correspondants seraient 0, 1 et 2 soit la valeur du rang moins 1. On pourrait donc penser que la rĂ©ponse Ă  la question est simplement :

Python
def costume(rang, couleurs):
    return couleurs[rang - 1]

😱 Mais bien sĂ»r cela ne fonctionne pas dĂšs que le nombre de figurants est plus grand que le nombre de couleurs. Ainsi, si on reprend nos trois couleurs ['bleu', 'blanc', 'rouge'] mais que le rang du figurant est 8, alors l’indice serait 7 mais couleurs[7] provoquera une erreur Index out of range. On sent bien qu’il faut recommencer au dĂ©but lorsqu’on dĂ©passe le rang 3 (l’indice 2) pour cet exemple Ă  3 couleurs. Il y a deux façons de voir cela :

I. Une premiĂšre approche

đŸ€” On fait comme si la liste des couleurs Ă©taient suffisamment longue, avec les couleurs qui se rĂ©pĂštent :

Longue liste : ["bleu", "blanc", "rouge", "bleu", "blanc", "rouge", "bleu", "blanc", "rouge"]
Indices 0 1 2 3 4 5 6 7 8

Ainsi pour notre exemple de 3 couleurs et le rang 8 (indice 7), on constate qu’il faudrait 3 fois la liste des couleurs mise bout Ă  bout pour former une liste suffisamment longue pour avoir un Ă©lĂ©ment Ă  l’indice 7.

😱 Cette mĂ©thode est inefficace : on est amenĂ© Ă  crĂ©er une liste potentiellement trĂšs grande (imaginez si vous avez plusieurs milliers de figurants)

II. MĂ©thode plus efficace

Dans l'exemple prĂ©cĂ©dent, il suffit de trouver que l'indice 7 correspond Ă  la mĂȘme couleur que l'indice 1. Pour comprendre ce qui se passe, nous allons construire le tableau suivant :

Liste normale de couleurs : ['bleu', 'blanc', 'rouge']
Les indices : 0 1 2
2e tour : 3 4 5
3e tour : 6 7 8

Cela revient Ă  boucler sur les indices 0, 1, 2 autant de fois que nĂ©cessaire, c’est-Ă -dire jusqu’à atteindre la valeur de notre indice (ici 7). Ce qui donne ce code dans un premier temps :

Python
def costume(rang, couleurs):
    indice = rang - 1
    indice_couleur = 0
    for _ in range(indice):
        indice_couleur += 1
        if indice_couleur >= len(couleurs):
            indice_couleur = 0
    return couleurs[indice_couleur]

III. 💡 Une approche beaucoup plus efficace, en utilisant modulo

Mais en rĂ©alitĂ©, on n’a pas besoin de rĂ©aliser explicitement cette boucle pour trouver le bon indice. On remarque, toujours avec l’exemple des 3 couleurs que tous les indices 0, 3, 6, 9, etc. seront associĂ©s Ă  l’indice 0, tous les indices 1, 4, 7, 10 ce sera 1 et enfin tous les indices 2, 5, 8 etc. seront associĂ©s Ă  2. C’est l’opĂ©ration modulo (% en Python) qui permet d’obtenir le rĂ©sultat et donne le code proposĂ© dans la solution.

On peut encore optimiser la solution, car si on utilise le "modulo" on évite la boucle. C'est la solution qui est proposée.

\(7=2 \times 3 + 1\). La réponse sera donc l'élément d'indice 1 : "blanc".
Le reste de la division euclidienne de 7 par 3 est 1. Il s'Ă©crit \(7 \% 3\). On dit que "7 modulo 3" renvoie \(1\).

Bilan

👉 D'une maniĂšre gĂ©nĂ©rale, lorsqu'on est amenĂ© Ă  lire une liste de façon circulaire, c'est-Ă -dire en reprenant la lecture au dĂ©but de la liste aprĂšs l'avoir terminĂ©e, il faut penser Ă  utiliser un "modulo longueur de la liste".

ENCRYPTION_TOKEN