Le module pygal de Python permet de faire de très jolis diagrammes au format svg visualisables dans son
navigateur libre préféré.
Pour illustrer notre propos, occupons-nous du célèbre problème du duc de Toscane.
On utilisera python3 via ipython en le lançant avec pylab :
$ ipython --pylab
randint(1,7,size = 3) renvoie une liste de trois entiers aléatoirement choisis entre 1 et 6 = 7-1 selon la loi uniforme discrète (c'est le randint de pylab).
Counter(s) renvoie les effectifs de chaque élément de s.
from collections import Counter s = [sum( randint(1,7,size = 3) ) for k in range(100000)] c = Counter(s)
On obtient le dictionnaire des effectifs:
Counter({11: 12651, 10: 12288, 9: 11582, 12: 11455, 8: 9750, 13: 9662, 7: 7134, 14: 6940, 15: 4643, 6: 4638, 16: 2827, 5: 2681, 17: 1460, 4: 1366, 3: 480, 18: 443})
Pour un rendu graphique d'une grande qualité, on utilise le module pygal de Python:
from pygal import * toscane = HorizontalBar() for v in c: toscane.add(str(v),c[v]) toscane.render_to_file("toscane.svg") toscane.title = "Effectifs des sorties du problème du duc de Toscane"
Ensuite, depuis ipython on peut visualiser sur firefox par exemple avec la commande:
!firefox ./toscane.svg
Voici le magnifique rendu SVG : n'hésitez pas à survoler les différentes parties de la page avec votre souris.
Sucre : lancers consécutifs égaux
La fonction groupby de Python (inspirée du groupBy de Haskell) permet de découper une liste en sous-listes uniformes.
Par exemple [1,1,1,1,2,2,3,3,1,1,1,2,2] --> [1,1,1,1],[2,2],[3,3],[1,1,1],[2,2]
En fait, Python renvoie deux itérateurs, l'un énumérant les valeurs, l'autre les sous-listes:
In [45]: [valeur for valeur,groupe in groupby([1,1,1,1,2,2,3,3,1,1,1,2,2])] Out[45]: [1, 2, 3, 1, 2] In [46]: [list(groupe) for valeur,groupe in groupby([1,1,1,1,2,2,3,3,1,1,1,2,2])] Out[46]: [[1, 1, 1, 1], [2, 2], [3, 3], [1, 1, 1], [2, 2]]
Cela va nous servir à résoudre le problème suivant: on lance 10 fois de suite une pièce de monnaie et on voudrait observer la moyenne du nombre maximal de résultats consécutifs égaux.
from collections import Counter from itertools import groupby def plus_gd_paquet(liste): return max([len(list(groupe)) for cle, groupe in groupby(liste)]) def dic_paquet(n): s = [plus_gd_paquet(randint(0,2,size = 10) ) for k in range(n)] return Counter(s) def moyenne_paquet(n): c = dic_paquet(n) return sum([k * c[k] for k in c]) / n
Alors:
In [50]: dic_paquet(100000) Out[50]: Counter({3: 36124, 4: 24972, 2: 17065, 5: 12364, 6: 5422, 7: 2304, 8: 988, 9: 404, 10: 179, 1: 178}) In [51]: moyenne_paquet(100000) Out[51]: 3.6552500000000001