Symbolic:
This is a linear Diophantine equation of n=3
variables. To solve it analytically in python you can use sympy
, as in this answer:
from random import randint
from sympy.solvers.diophantine import diop_linear
from sympy.abc import x, y, z
# Our original equation is 2 * x + 4 * y + 3 * z = 20
# Re-arrange to 2 * x + 4 * y + 3 * z - 20 = 0, and input the left side to sympy
general_solution = diop_linear(2 * x + 4 * y + 3 * z - 20)
def get_random_valid_triple():
t0,t1 = general_solution[2].free_symbols
# You can pick whatever bounds you want here
a = randint(-100, 100)
b = randint(-100, 100)
solution = [s.subs({t0: a, t1:b}) for s in general_solution]
print(solution)
# Get a random solution
get_random_valid_triple()
Brute Force:
Alternately, at least for small n
and tight bounds on each variable, you can just precompute all possible solutions and use random.choice
to choose one each time. For example, we restrict all of the variables to be positive, then they're forced to be in [0, 20 / coefficient]
, and there are only 14 solutions. We can generate these in python as follows:
import random
import itertools
n = 20
coefficients = [2, 4, 3]
valid_solutions = []
ranges = [range(0, n // k + 1) for k in coefficients]
for value in itertools.product(*ranges):
if sum(value[j] * i for j, i in enumerate(coefficients)) == n:
valid_solutions.append(value)
print("All solutions:")
print("\n".join(str(i) for i in valid_solutions))
print("Random solution:")
print(random.choice(valid_solutions))
This yields:
All solutions:
(0, 2, 4)
(0, 5, 0)
(1, 0, 6)
(1, 3, 2)
(2, 1, 4)
(2, 4, 0)
(3, 2, 2)
(4, 0, 4)
(4, 3, 0)
(5, 1, 2)
(6, 2, 0)
(7, 0, 2)
(8, 1, 0)
(10, 0, 0)
Random solution:
(10, 0, 0)