]> Git — Sourcephile - reloto-libreoffice.git/blob - tirages.py
Ajout début de macro pour tirages au sort publiquement vérifiables.
[reloto-libreoffice.git] / tirages.py
1 # -*- coding: utf-8 -*-
2 # Author: Julien Moutinho <julm@autogeree.net>
3 # License: GNU GPLv3 (or later, at your choice)
4
5 from __future__ import unicode_literals
6 from functools import reduce
7 import datetime
8 import os
9 import random
10 import shutil
11 import uno
12 from com.sun.star.awt.MessageBoxType import MESSAGEBOX, INFOBOX, WARNINGBOX, ERRORBOX, QUERYBOX
13 from com.sun.star.awt.MessageBoxButtons import BUTTONS_OK, BUTTONS_OK_CANCEL, BUTTONS_YES_NO, BUTTONS_YES_NO_CANCEL, BUTTONS_RETRY_CANCEL, BUTTONS_ABORT_IGNORE_RETRY
14 from com.sun.star.awt.MessageBoxResults import OK, YES, NO, CANCEL
15 from com.sun.star.beans import PropertyValue
16 from com.sun.star.sheet import CellFlags
17
18 if 'XSCRIPTCONTEXT' in globals():
19 def getModel():
20 return (XSCRIPTCONTEXT.getDocument(), XSCRIPTCONTEXT)
21 def debug(msg):
22 return
23 else:
24 from connect_to_libre_office import getModel
25 def debug(msg):
26 print(msg)
27
28 def MakeDraw(*args):
29 return
30
31 def nCk(n,k):
32 """
33 nCk(n,k) retourne le nombre de combinaisons
34 de longueur k d’un ensemble de longueur n.
35 """
36 if n<0 or k<0 or n<k:
37 raise ZeroDivisionError
38 if k > n // 2:
39 k = n - k # more efficient and safe with smaller numbers
40 c = 1
41 for j in range(1,k+1):
42 c = c * (n-j+1) // j
43 return c
44
45 def combinOfRank(n,k,rank):
46 """
47 combinOfRank(n, k, r) retourne les indices de permutation
48 de la combinaison de k entiers parmi [1..n]
49 au rang lexicographique r dans [0 .. nCk(n,k)-1].
50
51 Construit chaque choix de la combinaison en prenant le prochain plus grand
52 dont le successeur engendre un nombre de combinaisons
53 qui dépasse le rang restant à atteindre.
54
55 DOC: <http://www.site.uottawa.ca/~lucia/courses/5165-09/GenCombObj.pdf>, p.26
56 """
57 if rank<0 or nCk(n,k)<rank:
58 raise ZeroDivisionError
59 i = 1
60 j = 1
61 c = []
62 while True: # for1K
63 if i < k:
64 while True: # uptoRank
65 nbCombins = nCk(n-j, k-i)
66 if nbCombins > rank:
67 c.append(j)
68 i += 1
69 j += 1
70 break
71 else:
72 j += 1
73 rank -= nbCombins
74 elif i == k:
75 c.append(j+rank) # because when i == k, nbCombins is always 1
76 break
77 else:
78 break
79 return c
80
81 def rankOfCombin(n,ns):
82 """
83 rankOfCombin(n, ns) retourne le rang lexicographique dans [0 .. nCk(n, length ns)-1]
84 de la combinaison ns d’entiers parmi [1..n].
85
86 WARNING: ns doit être triée de manière ascendante.
87
88 Compte le nombre de combinaisons précédant celle de rang r.
89
90 DOC: <http://www.site.uottawa.ca/~lucia/courses/5165-09/GenCombObj.pdf>, pp.24-25
91
92 rankOfCombin(n, combinOfRank(n, k, r)) == r
93 combinOfRank(n, len(ns), rankOfCombin(n, ns)) == ns
94 """
95 if not all(1<=x or x<=n for x in ns):
96 raise ZeroDivisionError
97 k = len(ns)
98 if n<k:
99 raise ZeroDivisionError
100 i = 1
101 rank = 0
102 x1 = 0
103 for x in ns:
104 for j in range(x1+1,x-1 +1):
105 rank += nCk(n-j, k-i)
106 i += 1
107 x1 = x
108 return rank
109
110 def nbBits(n):
111 """
112 nbBits(n) retourne le nombre de bits servant à encoder n.
113 """
114 if n<0:
115 raise ZeroDivisionError
116 r = 0
117 while n > 0:
118 r += 1
119 n //= 2
120 return r
121
122 def equiprobableBits(n):
123 """
124 equiprobableBits(n) retourne le nombre maximal de bits de i
125 équiprobables quand i parcourt [0 .. n-1].
126
127 Ce nombre est le plus grand 'b' dans [0 .. ] tel que 2**b-1 <= n.
128
129 map(equiprobableBits, range(0, 17+1)) == [0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4]
130 """
131 b = nbBits(n)
132 return (b if n == 2**b-1 else b-1)
133
134 def bitsOfInteger(m, n):
135 """
136 bitsOfInteger(m, n) retourne les m premiers bits de poids faible
137 encodant le nombre n.
138 """
139 if not(0<=m and 0<=n):
140 raise ZeroDivisionError
141 bs = []
142 while m > 0:
143 (q,r) = (n//2, n%2)
144 bs.append(r==1)
145 m -= 1
146 n = q
147 return bs
148
149 def randomOfCombin(n, k, ns):
150 """
151 randomOfCombin(n, k, ns) retourne des bits équiprobables donnés
152 par la combinaison ns obtenue par tirage équiprobable
153 d’une combinaison de k entiers parmi [1 .. n].
154
155 WARNING: aucun bit n’est extrait du tirage ns
156 dans le cas où ns a un rang lexicographique encodé par
157 un nombre de bits strictement supérieur à equiprobableBits(nCk(n, k)).
158 """
159 if not(0<=n and 0<=k and k<=n and all(1<=x and x<=n for x in ns)):
160 raise ZeroDivisionError
161 ns.sort()
162 rank = rankOfCombin(n, ns)
163 epBits = equiprobableBits(nCk(n,k))
164 return bitsOfInteger(epBits, rank) \
165 if nbBits(rank) <= epBits else []
166
167 def randomOfFrenchLoto (n1,n2,n3,n4,n5, nc):
168 """
169 randomOfFrenchLoto(n1,n2,n3,n4,n5, numComplementaire) retourne les bits équiprobables donnés
170 par un tirage du Lo to Français : https://www.fdj.fr/jeux/jeux-de-tirage/loto/resultats/.
171
172 Il peut produire @23@ bits équiprobables :
173 sum(map(equiprobableBits, [nCk(49, 5), nCk(10, 1)]))
174
175 randomOfFrenchLoto(1,2,3,4,5, 1) == [False] * (20+3)
176 randomOfFrenchLoto(7,27,36,40,46, 8) == [True] * (20+3)
177
178 combinOfRank(49, 5, 2 ** equiprobableBits(nCk(49,5)) - 1) == [7,27,36,40,46]
179 combinOfRank(49, 5, 2 ** equiprobableBits(nCk(49,5))) == [7,27,36,40,47]
180 randomOfFrenchLoto(7,27,36,40,46, 1) == [True] * 20 + [False] * 3
181 randomOfFrenchLoto(7,27,36,40,47, 1) == [False,False,False]
182
183 combinOfRank(10, 1, 2 ** equiprobableBits(nCk(10, 1)) - 1) == [8]
184 combinOfRank(10, 1, 2 ** equiprobableBits(nCk(10, 1))) == [9]
185 randomOfFrenchLoto(7,27,36,40,47, 8) == [True,True,True]
186 randomOfFrenchLoto(7,27,36,40,47, 9) == []
187 """
188 return \
189 randomOfCombin(49, 5, [n1,n2,n3,n4,n5]) + \
190 randomOfCombin(10, 1, [nc])
191
192
193 def randomOfEuroMillions (n1,n2,n3,n4,n5, nc1,nc2):
194 """
195 https://www.fdj.fr/jeux/jeux-de-tirage/euromillions/resultats
196 """
197 return \
198 randomOfCombin(50, 5, [n1,n2,n3,n4,n5]) + \
199 randomOfCombin(11, 2, [nc1,nc2])
200
201 g_exportedScripts = MakeDraw,