I would recommend a hit and skip approach to ensure an even distribution of the generated sequences that satisfy the constraint. It is easy to understand that the probability of 6 random integers in {0,1,2} with the addition of up to 8 is approximately 12.3%, so there aren’t so many tests before the hit. Here is a Python implementation:
import random
def randNums(n,a,b,s):
hit = False
while not hit:
total, count = 0,0
nums = []
while total < s and count < n:
r = random.randint(a,b)
total += r
count += 1
nums.append(r)
if total == s and count == n: hit = True
return nums
Here is the result of 5 starts:
>>> for i in range(5): print(randNums(6,0,2,8))
[2, 1, 0, 2, 1, 2]
[0, 2, 2, 1, 1, 2]
[2, 2, 0, 2, 0, 2]
[2, 2, 0, 1, 1, 2]
[1, 2, 1, 1, 1, 2]
: , , . 6 {0,1,2} 0 3 ^ 6-1 = 728, 3. -3 . = 8:
def toBase3(n):
digits = []
q,r = divmod(n,3)
while q > 0:
digits.append(r)
q,r = divmod(q,3)
digits.append(r)
return ''.join(str(i) for i in reversed(digits))
def dsum(s):
return sum(int(d) for d in s)
hits = []
for n in range(729):
s = toBase3(n)
if dsum(s) == 8: hits.append(s)
hits = [('0'*(6-len(s)))+s for s in hits]
s = ''.join(hits)
print("%d valid sequences for prob. of %f" % (len(hits),len(hits)/3.0**6))
print("%d zeros in those sequences for a prob. of %f" % (s.count('0'),s.count('0')/540.0))
print("%d ones in those sequences for a prob. of %f" % (s.count('1'),s.count('1')/540.0))
print("%d twos in those sequences for a prob. of %f" % (s.count('2'),s.count('2')/540.0))
:
90 valid sequences for prob. of 0.123457
90 zeros in those sequences for a prob. of 0.166667
180 ones in those sequences for a prob. of 0.333333
270 twos in those sequences for a prob. of 0.500000
, 6 8, ,
90/729 = 0.123456790 (repeating)
, 0.1234567. , 8 7.