-2

I have equations with multiple unknowns, and a number range:

eq1 = (x + 5 + y) #
ans = 15
no_range = [1..5]

I know that I can solve the equation by checking all possible combinations:

solved = False
for i in range(1, 5+1)  # for x
    for j in range(1, 5+1)  # for y
        if i + 5 + j == ans:
            solved = True

So, the problem is that I want a function to deal with unknown_count amount of unknowns. So that both the following equations, or any, can be solved in the same manner above:

eq1 = (x + 5 + y) 
ans = 15

eq2 = (x + 5 + y + z * a + 5 * b / c) 
ans = 20

I just cannot think of a way, since for each unknown you need a for loop.

Wizard
  • 1,533
  • 4
  • 19
  • 32
  • You can do the equivalent of multiple nested `for` loops quite neatly by using [`itertools.product`](https://docs.python.org/3/library/itertools.html#itertools.product), but you do need to know how many loops you want. BTW, this brute force method of solving equations gets inefficient if there are lots of unknowns and the `no_range` gets large, because you may have to check *lots* of combinations before you hit a solution. – PM 2Ring Apr 30 '18 at 07:57

1 Answers1

2

You could use itertools.product to generate the Cartesian product for an arbitrary number of variables:

In [4]: import itertools
In [5]: list(itertools.product(range(1, 5+1), repeat=2))
Out[5]: 
[(1, 1),
 (1, 2),
 (1, 3),
 ...
 (5, 3),
 (5, 4),
 (5, 5)]

So you could modify your code like this:

import itertools as IT
unknown_count = 6
ans = 20
solved = False
def func(*args):
    x, y, z, a, b, c = args
    return x + 5 + y + z * a + 5 * b / c
for args in IT.product(range(1, 5+1), repeat=unknown_count):
    if func(*args) == ans:
        solved = True
        print('{} + 5 + {} + {} * {} + 5 * {} / {} = {}'.format(*(args+(ans,))))

which yields a lot of solutions, such as

1 + 5 + 1 + 1 * 3 + 5 * 2 / 1 = 20
1 + 5 + 1 + 1 * 3 + 5 * 4 / 2 = 20
1 + 5 + 1 + 2 * 4 + 5 * 1 / 1 = 20
...
5 + 5 + 5 + 2 * 2 + 5 * 1 / 5 = 20
5 + 5 + 5 + 3 * 1 + 5 * 2 / 5 = 20
5 + 5 + 5 + 4 * 1 + 5 * 1 / 5 = 20

The * unpacking operator was used to create a function, func, which accepts an arbitrary number of arguments (i.e. def func(*args)), and also to pass an arbitrary number of arguments to func (i.e. func(*args)).

unutbu
  • 842,883
  • 184
  • 1,785
  • 1,677