Tickets gagnants

Épreuve blanche

Cet exercice est rédigé comme une épreuve pratique de NSI. À ce titre et afin de coller au maximum aux conditions d'examen, le corrigé n'est pas proposé.

Si vous réalisez cet exercice en classe, n'hésitez pas à contacter l'enseignant :

  • si vous avez des questions
  • ou afin de faire vérifier votre code à chaque question.
Bornes incluses

Dans tout cet exercice les bornes des intervalles étudiés seront incluses. Ainsi l'intervalle de nombres entiers allant de 5 à 9 contient les valeurs 5, 6, 7, 8 et 9.

Une plateforme de jeu en ligne lance un nouveau jeu de hasard. Ce jeu se déroule en deux temps :

  • durant la semaine, le joueur achète tout d'abord un ticket virtuel sur la plateforme. Ce ticket contient deux nombres entiers a et b (tous les deux compris entre \(0\) et \(10^9\)) qui constituent un intervalle. On garantit que a <= b ;
  • en fin de semaine a lieu le tirage au sort du numéro gagnant c (un nombre entier compris entre \(0\) et \(10^9\)).

Un ticket est considéré gagnant si le numéro tiré au sort est compris dans l'intervalle désigné par le ticket. Les valeurs de début et de fin de chaque intervalle sont incluses dans ce dernier. Par exemple :

  • le numéro 7 est compris dans l'intervalle (5, 9) ;
  • le numéro 7 est compris dans l'intervalle (5, 7) ;
  • le numéro 7 est compris dans l'intervalle (7, 9) ;
  • le numéro 7 n'est pas compris dans l'intervalle (8, 9).

Un ticket n'est valable qu'une semaine.

1. Ticket gagnant ?

Écrire la fonction est_gagnant qui prend trois paramètres :

  • a : la valeur de début de l'intervalle d'un ticket ;
  • b : la valeur de fin de l'intervalle d'un ticket ;
  • c : la valeur du numéro choisi au hasard le vendredi soir.

Cette fonction renvoie le booléen indiquant si le ticket comprenant l'intervalle (a, b) « contient » le numéro gagnant c.

Exemples
>>> est_gagnant(5, 9, 7)
True
>>> est_gagnant(5, 7, 7)
True
>>> est_gagnant(7, 9, 7)
True
>>> est_gagnant(8, 9, 7)
False

###(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 : /

.128013,:)ag1ikn/S=vmsubh;ye2odt c(wr_Pplf050y0v0z0e0h0I0p0A0B0I0e0p0p0m010z0h0H010406050p0q0o0o0e0E0u040l0x0I0q0!0x0j050k0+0-0/0;0)0H040}1405170k1719140)0y0h0n0S0U0W0Y0s0h0f0s0I1n0s0z0%050N0r0I0v1i0V0X011m1o1q1o0z1w1y1u0z0r0x0y0;1v0E150z0s0S0@0p0H0e0j0Y0w011A1k010J0P0v0j0e0o0v1u1Y1!1)1C1,1y1/1;0%0a0A0G0E0x0H0x0p0h0`0j0A0L1W0E0E0v0B290}1@0j150k1U2m0z1S1R1T0y1_0Y1q0j1.261u1f1h0T1B2w0h2y0j1O1g1u0H2f152k2m2Q0*1Z2a2E1*2J0E0.0I0%0g2j2U0(2T1^2W1C2Y2!0%0w2(1!2m2N0v2m2C2p0y2t2v010B1O1=152|182O2+2l2?3a320L2P2U300i0%0L0J3b3f2,1j1C0D0%0A3m39300j0J0%0v0p0z0F0f0e0f1/0j0z3u2k300$040C3K3g2-0Y0j0%0e3Q3o2F013N0b3m3t3L3S013U040r3X2V3p0Y3#3%3v3*3,0B3/3M0%0d0c3m060A433(3R3;013i042f0z0q0E0|0~2)453Y1*3N3P4g2@3^473,3W4n2l4i3:3Z0x0%020I0z0t0m3@3)4q0%3{4t3n4w4k3~4F464x3r041!0y4P4j1C4l3|3_4I4W4M1C4y044A4C4E4K4v3w0%3.4K4p3Z3N0d410}3d2`16380k362n2~0}2q2p1N1P2p0e1x4 521g2*520M0O0Q04.
2. Combien de tickets gagnants ?

Un joueur achète plusieurs tickets. Le numéro gagnant tiré au sort en fin de semaine est utilisé pour tous ses tickets. Il souhaite savoir combien de tickets gagnants il a achetés.

Un intervalle est représenté sous la forme d'un couple (a, b) dans lequel a est la valeur de début et b celle de fin.

Les différents intervalles correspondants aux tickets achetés par le joueur sont donnés dans une liste. Par exemple [(5, 10), (8, 17)] représente deux tickets : le premier avec l'intervalle (5, 10) et le second l'intervalle (8, 17).

Écrire la fonction nombre_gagnants qui prend deux paramètres :

  • tickets : une liste de couples d'entiers donnant les intervalles de chacun des tickets ;
  • c : la valeur du numéro gagnant.

Cette fonction renvoie le nombre de tickets gagnants parmi ceux listés dans tickets.

Aide

La fonction est_gagnant de la question précédente est déjà importée dans cet éditeur. Vous pouvez directement l'utiliser.

Exemples
>>> tickets = [(5, 10), (8, 17)]
>>> nombre_gagnants(tickets, 4)
0
>>> nombre_gagnants(tickets, 9)
2
>>> nombre_gagnants(tickets, 12)
1

###(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 : /

.128013,:ag)1ikn/S=vmsuhb4ye6+2odt c0(wr5_P3plf050A0v0B0d0h0N0p0C0D0N0d0p0p0m010B0h0M010406050p0q0o0o0d0H0u040l0z0N0q0)0z0j050k0:0=0@0_0.0M041219051c0k1c1e190.0A0h0n0X0Z0#0%0r0h0e0r0N1s0r0B0,050S0s0N0v1n0!0$011r1t1v1t0B1B1D1z0B0s0z0A0_1A0H1a0B0r0X0|0p0M0d0j0%0y011F1p010O0U0v0j0d0o0v1z1%1)1.1H1;1D1@1_0,0a0C0K0H0z0M0z0p0h0 0j0C0Q1#0H0H0v0D2e121|0j1a0k1Z2r0B1X1W1Y0A1~0%1v0j1?2b1z1k1m0Y1G2B0h2D0j1T1l1z0M2k1a2p2r2V0/1(2f2J1/2O0H0?0N0,0g2o2Z0-2Y1}2#1H2%2)0,0y2-1)2/2p2A012@0d2*040L2{2q0.2~2=0%31330t362}2Z2 3c0,0I3f383h3a300z2(320,0w3f1b2T122H2u0A2y2 0D1T1`1a3A1d3y2X132.053F0Q2U3o1o1H0i0,0Q0O3w393U0%0G0,0C3!3T2K300O0,2O0o0s2k0J0e0d0e1@0j0B0p3+2;3$010+040F402!420j0,0)0D0i0R3 3N2|2:483-440b3f3*3#3-4a040D472 440f0c3m0C4B4p3,2$4b0z0S0N4o4j2 0z0,0m4K4q1/0o0h0,0E4A4C4L3p3W040O3r4Q4E2?0,0d4v3p4m4)414r0,0s4;4k1/0z3(042M4_3i4b0h4d4f4.42444z4h374C5c4D4=1/4#0h3Z5a045e4`4+040v0p0B3^3`3|0B564l0,465k4Z494,5x1/4:5k5m51044^5B4R1H5H2V5J3p4s4u5N4*0%4x592V065d5%5S5D040B4H32503p4N040x4P5I5C3-4T2+4X4B5_5g0,2k0B0q0H115^5O3b4G4I3m123Q0v2r2S6f3z1l3B2u2w2s1S1U2u0d1C6i0k3A0.6v0R0T0V04.
3. Réduction des intervalles

La plateforme de jeu en ligne assure que, chaque semaine, au moins un des tickets achetés est gagnant.

Pour ce faire, elle effectue le tirage au sort parmi l'ensemble des valeurs contenues dans les intervalles des ticket vendus.

Si par exemple les tickets vendus sont décrits par la liste [(5, 10), (8, 17), (20, 22)], le numéro gagnant doit être choisi dans les intervalles de la liste [(5, 17), (20, 22)]. En effet, les deux premiers intervalles (5, 10) et (8, 17) se « chevauchent ». Ils peuvent être regroupés en un unique intervalle « isolé » (5, 17). Le dernier intervalle est déjà « isolé » et reste inchangé.

Réduction des tickets

La plateforme doit donc, connaissant l'ensemble des tickets vendus, déterminer les intervalles « isolés » correspondants.

Pour ce faire, elle utilise la démarche suivante (on garantit qu'au moins un ticket a été vendu) :

  • on trie la liste des tickets. Cette action a pour effet de classer les tickets par ordre de valeurs de début croissantes. Si deux valeurs de début sont égales, le ticket dont la valeur de fin est la plus petite sera placé en avant l'autre ;
  • on crée une liste vide resultat ;
  • on initialise deux variables mini et maxi aux valeurs de début et de fin du premier intervalle ;
  • on parcourt l'ensemble des intervalles (a, b) :
  • si la valeur de début de l'intervalle lu est inférieure ou égale à la valeur maxi :
    • on met à jour cette dernière en lui affectant la valeur la plus grande parmi la valeur de fin de l'intervalle lu et maxi;
  • sinon :
    • on ajoute à la liste resultat le couple (mini, maxi) ;
  • en fin de boucle, on ajoute le dernier intervalle (mini, maxi) à la liste resultat.

La fonction reduction prend en paramètres une liste de couples d'entiers intervalles contenant au moins un intervalle.

Cette fonction renvoie la liste des intervalles « isolés » triés dans l'ordre des valeurs de début croissantes.

La fonction proposée ne passe pas les tests et comporte des erreurs...

Corriger cette fonction. Les lignes à modifier sont indiquées par le commentaire # !.

Exemples
>>> intervalles = [(5, 10), (8, 17), (20, 22)]
>>> reduction(intervalles)
[(5, 17), (20, 22)]
>>> intervalles = [(5, 17), (20, 22)]
>>> reduction(intervalles)
[(5, 17), (20, 22)]
>>> intervalles = [(2, 30), (1, 2), (2, 2) ]
>>> reduction(intervalles)
[(1, 30)]
>>> tickets = [(1, 10), (2, 9)]
>>> reduction(intervalles)
[(1, 10)]

###(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 : /

.128013:,ag)1ikn9/S=vmsuhb.84;y7e[x62odt c0(w]r5P3plf050G0A0H0d0h0T0q0I0J0T0d0q0q0n010H0h0S010406050q0r0p0p0d0O0y040m0F0T0r0/0F0j050l0_0{0}0 0@0S04181f051i0l1i1k1f0@0G0h0o0%0)0+0-0s0h0e0s0T1y0s0H0=050Y0t0T0A1t0*0,011x1z1B1z0H1H1J1F0H0t0F0G0 1G0O1g0H0s0%120q0S0d0j0-0E011L1v010U0!0A0j0d0p0A1F1-1/1@1N1`1J1}1 0=0a0I0Q0O0F0S0F0q0h150j0I0W1+0O0O0A0J2k18220j1g0l1)2x0H1%1$1(0G240-1B0j1|2h1F1q1s0(1M2H0h2J0j1Z1r1F0S2q1g2v2x2#0^1.2l2P1^2U0O0|0T0=0I0g2u2)0?2(232+1N2-2/2;0E2@1/2_2v2G012~0d2:040I0R322w0@352|0-383a0I0w3e342)363k2;0P3o3g3q3i370F2.392;0D3v2`2*1u2}3A2 3b0z3F3h3I3j3K3C3b0v3O3x3Q3z3B3l0k3W2{3Y3s040g0K3%3H2Q3Z3L0g2?192^3w3(3:3*0g313^331h2Z182N2A0G2E360J1Z201g451j432%402w054a0W2!3X3:0i0=0W0U3o3G360M2;4u3P3|0U0=2q0G0r2s0h164z4o1^0;040L4K3{2,0=2S0H0A0O0o391J0q4Q3/4M0=0f0b3v0I4-0I4v3y0j4T0j4V4X4Z0A4#4i4n4R1N0F0=0u4$3r0=0q3A0H543y4N0L0f3o4-4:3Y0J0g0=030I2B0h0$0W0$0/0J0i0X4|2#064.4/4A4S042q0_0T0Y594}5B4L500=0n5f5h3:4N0B0N4,4.5R5D0p2S0h5a3Y4N0c5Q5C2}0=0|0C5$5K5Y5N045P5=5,3j4?4^4Y0T4!5%5S0=0B621^5!0=3-4}5?0-4N5V4}5z5X5{014q040U3A5+5M5|040W0t14661N5)6p4 6r1`175`6q010F4x042S6z4%5-6J4@4W5 616b6j4N4+6g5A5A6c6k4T4t6E6A374r0A6u5J2#5L6)5104025H0x5_6/6!4=045/5;2%6U0=6W5y6Y766:6M6r6 6L366=6`2^783r0t5.0d0C6w6d0=4P6T6F6}7b7r6)6y6(796*6m6K7v7z4N5e6X776!6l0A0#0A7n016V5W776i7s4D4{0r5H0d6.2^6!6=537D55040d0S0S1|0G7O5c7q717U6~5#7;0=5*7y7*7u7@7w4)7G757S7T6)7t7`7)5b7|7c4;7k5:8e3Y7e8i3|6+6-7{047}6{6j6}6C7R7h8f5E7W7Y7!416j7%7O6}7,7.0j7:8b5(7p7?7#8t5.8a817E8d7~8y808Q6F7F843_6Z6j6l2q0H0r0O6D8s7^5F7X5I3F0l4l0A2x2Y8|441r462A2C2y1Y1!2A0d1I8 0l450@9c0X0Z0#04.
4. Tirage au sort de la valeur gagnante

La plateforme de jeu souhaite pour finir tirer au sort la valeur gagnante parmi les valeurs des intervalles isolés déterminés à la question précédente.

Pour ce faire elle procède en trois temps :

  1. elle dénombre le nombre de valeurs possibles sur l'ensemble des intervalles. On note nb_valeurs ce total ;
  2. elle choisit aléatoirement un rang compris entre 0 (inclus) et nb_valeurs (exclu) ;
  3. elle parcourt l'ensemble des intervalles jusqu'à ce que le rang choisi soit celui d'une des valeur de cet intervalle.

Considérons par exemple les intervalles [(5, 17), (20, 22)] :

  • le nombre total de valeurs vaut 13 + 3 = 16 ;
  • on choisit un rang aléatoire entre 0 (inclus) et 16 (exclu). On suppose que cette valeur est k = 14 ;
  • le premier intervalle ne contient pas la 14-ième valeur. En effet 5 + 14 > 17. On passe à l'intervalle suivant et on considère que le rang vaut désormais k = 14 - 13 = 1 (le premier intervalle compte 13 valeurs) ;
  • le second intervalle contient la valeur cherchée. En effet 20 + 1 <= 22. Cette valeur vaut 20 + 1 = 21.

Tirage au sort

Le choix du rang aléatoire est fait à l'aide de la fonction randrange du module random. Cette fonction prend en paramètres deux entiers a et b (a <= b) et renvoie un entier aléatoire c tel que a <= c < b.

La fonction k_ieme, qu'il est demandé d'écrire, prend en paramètres une liste d'intervalles isolés ainsi que l'indice d'une valeur et renvoie la valeur d'indice k obtenue en parcourant successivement les différents intervalles. Ainsi k_ieme([(5, 17), (20, 22)], 14) renvoie 21.

Compléter les fonctions k_ieme et tirage_au_sort. Cette seconde fonction prend en paramètre une liste d'intervalle isolée et renvoie une valeur au hasard parmi ceux-ci en respectant la démarche expliquée plus haut.

Exemples
🐍 Console Python
>>> k_ieme([(5, 17), (20, 22)], 0)
5
>>> k_ieme([(5, 17), (20, 22)], 1)
6
>>> k_ieme([(5, 17), (20, 22)], 12)
17
>>> k_ieme([(5, 17), (20, 22)], 13)
20
>>> k_ieme([(5, 17), (20, 22)], 14)
21
>>> k_ieme([(5, 17), (20, 22)], 15)
22
>>> tirage_au_sort([(5, 5)])  # une seule valeur possible -> résultat prévisible
5

###(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 : /

.128013,:ag)1ikn9/S=vmsuhb84;y7e[6+2o-dt c0(w]r5_P3plf050G0z0H0d0h0U0q0I0J0U0d0q0q0n010H0h0T010406050q0r0p0p0d0O0x040m0E0U0r0:0E0j050l0`0|0~100^0T04191g051j0l1j1l1g0^0G0h0o0(0*0,0.0s0h0e0s0U1z0s0H0?050Z0t0U0z1u0+0-011y1A1C1A0H1I1K1G0H0t0E0G101H0O1h0H0s0(130q0T0d0j0.0D011M1w010V0#0z0j0d0p0z1G1.1:1^1O1{1K1~200?0a0I0R0O0E0T0E0q0h160j0I0X1,0O0O0z0J2l19230j1h0l1*2y0H1(1%1)0G250.1C0j1}2i1G1r1t0)1N2I0h2K0j1!1s1G0T2r1h2w2y2$0_1/2m2Q1_2V0O0}0U0?0I0g2v2*0@2)242,1O2.2:2=0D2^1:2`2w2H012 0d2;040I0S332x0^362}0.393b0I0v3f352*373l2=0P3p3h3r3j380E2/3a2=0B3w2{2+1v2~3B303c0y3G3i3J3k3L3D3c0u3P3y3R3A3C3m0k3X2|3Z3t040g0K3(3I2R3!3M0g2@1a2_3x3)3;3+0g323_343{3:2-3T3b0g3e413g3H3s460?0g3o4a3q3|453#4f3v4i434d4m3,3F4p4c3z3~3O4v3Q3}4e3,3W4i1i2!192O2B0G2F370J1!211h4K1k4I2(4G4P0X2#3Y3;0i0j0?0V2f0p3p4w3Z0M2=4-4B2-4(040O1:0G0E4,4G4?1O4:3c4=4#1_4%0?0h0p2h0O0H3p0I4.3}0?4`0j0G5j0e0z3w064q3z0i0?0X0V544k514;4 552~0V0?0i0Q0h0z205x441O0=040L5L3s580j0H0z0O0o3a1K0q5R3z5O0b5e5g2-5F5$3Z5O0f0c3w0I5@5f500.5t040V3B5*5`3858605C0.0E522T645y3k0t5i1:5n5.3;5O5Q5B6b386d04286h1_6j6r2~5T5V5X5Z0z5#6l5M0.5:5;5?5^6I5+6v040X0t156u6E0?5)4i5_65625}696U6K660?0n6a6D6X2T6x5Y0U5!6Q015O0A6;4^0h6;5O0N6H6I5@6#015|0h5w6!614^6N6P766W0E0?0C6)5S040i7g3z7d04020U0H0w6(7b6m4^1{186C375O5=4p6 7D6V6m5|2r0H0r0O7x2$7F6*780z6O5d7t6*7m7f7U7h7j7C7E715|0z0$5o7y5%0?7B2$067E6 714^7!7N717m7s7`775-7Y7l0?0F7k5/0?6k2(7 6Y7M2_7O377m84813*5u7R7a7~7c7e853;0p0h4f6{0?0f5p5r3Z5|5v6;525f7,3*5E040:4`5n0Q0d0r0Q0q3B7T896W6t8G5h046,5W6.6:8X6s8w7/3`6J8a0j0t0Q6.0z7K6B8n6m7|8q1_8s0?3.7#70615|5~0O8|6L798T2_715(973k4)6Z8_7V688c348e4x6w8#6z8^9b617A6~7?8.8:8=8@9e017W7}8d7@9g9l2x9n3Z8g9C7Q7S9C7W9C8~3,9w9H7i9R6%9O6e5k5m7+8U6m8W9*6*9U909-7z6S9#048/8;3a8?0O9s349c8w9W935i0Y7K9J538a5G5I5K8(5N876^9p6y6/6A8v046T9i7Zal8x4v0l4Y0z2y2Zav4J1s4L2B2D2z1Z1#2B0d1Jay0l4K0^aL0Y0!0$04.