I want to select some random numbers but their addition should always be even in Python

Viewed 83
import random


for i in range(100):
    a = random.randint(1, 20)
    b = random.randint(1, 20)
    c = random.randint(1, 20)
    if ((a + b + c) % 2) == 0:
        print(str(a) + "," + str(b) + "," + str(c))

I tried this but I am not getting the desired output. I want it in a way that three random numbers are chosen between 1 and 20 such that their sum is always even. Here the programme prints only the outputs that are even it does not select the numbers in such a way. Hope you help me. Thanks!

3 Answers

How about checking if the sum first two (a, b) is even or odd, and then accordingly set c?

import random


for i in range(100):
    a = random.randint(1, 20)
    b = random.randint(1, 20)
    if (a + b) % 2 == 0:
      c = random.randint(1, 10) * 2
    else:
      c = random.randint(1, 10) * 2 - 1
    if ((a + b + c) % 2) == 0:
        print(str(a) + "," + str(b) + "," + str(c))

You could do this:

import random
from itertools import product

# Prepare a list of triplets that add up to an even number
even_triplets = [x for x in product(range(1,21), range(1,21),range(1,21))
                 if (sum(x)%2)==0]

# Now select 100 of those triplets randomly, allowing
# duplicates (allowing same triplet to appear multiple times)

result = random.choices(even_triplets, k=100)
# If you don't want repetitions, un-comment below line instead of above:
# result = random.sample(even_triplets, 100)

# Print the first and last of the selected 100 triplets, just to verify
print(result[0])
print(result[-1])

Note: The way the question is phrased currently is a self-contradiction: it says that a, b, and c are to be selected randomly, and it also says that they should add up to an even number. If the selection of a, b, and c is truly random, then it cannot be subject to the additional constraint of adding up to an even number.

for completeness, a less efficient way of generating samples with this distribution would be to use rejection sampling. this works by rejecting values that aren't wanted, in this case where the sum isn't even

from random import randint

def fn():
  while True:
    x = tuple(randint(1, 20) for _ in range(3))
    if sum(x) & 1 == 0:
      return x

which can be used as:

for i in range(100):
    a, b, c = fn()
    print(f'{a}, {b}, {c}')

rejection sampling can be wasteful, but on average we'd only expect to reject one sample for every one we accept so it's not too bad here

Related