Reputation: 157
I am trying to print out all the possible combinations of two lists, so for example if list1 has values {1,2,3} and list two has values {A,B,C} I should get the following:
A=1 B=1 C=1
A=1 B=1 C=2
A=1 B=1 C=3
A=1 B=2 C=1
A=1 B=2 C=2
A=1 B=2 C=3
A=1 B=3 C=1
A=1 B=3 C=2
A=1 B=3 C=3
etc
For all of the possible values in the list. So the last line should be
A=3 B=3 C=3
Now this should work for abititary sized arrays. So if I have list1 = {1,2,3,4,5,6} list2 = {A,B,C,D,E,F}
I should get
A=1 B=1 C=1 D=1 E=1 F=1
A=1 B=1 C=1 D=1 E=1 F=2
A=1 B=1 C=1 D=1 E=1 F=3
A=1 B=1 C=1 D=1 E=1 F=4
A=1 B=1 C=1 D=1 E=1 F=5
A=1 B=1 C=1 D=1 E=1 F=6
A=1 B=1 C=1 D=1 E=2 F=1
A=1 B=1 C=1 D=1 E=2 F=2
A=1 B=1 C=1 D=1 E=2 F=3
A=1 B=1 C=1 D=1 E=2 F=4
A=1 B=1 C=1 D=1 E=2 F=5
A=1 B=1 C=1 D=1 E=2 F=6
etc
So in the first example there would be 3^3 = 27 combinations and I attempted to solve the problem like:
def printArrays():
letters = {'A', 'B', 'C', 'D', 'E', 'F'}
domain = {1, 2, 3, 4, 5, 6}
myStr = ""
for value in domain:
for letter in letters:
myStr += letter + "=" + str(value) + " "
myStr += "\n"
print(myStr)
Obviously it gives the wrong output since it gives me:
F=1 D=1 C=1 B=1 E=1 A=1
F=2 D=2 C=2 B=2 E=2 A=2
F=3 D=3 C=3 B=3 E=3 A=3
F=4 D=4 C=4 B=4 E=4 A=4
F=5 D=5 C=5 B=5 E=5 A=5
F=6 D=6 C=6 B=6 E=6 A=6
What would be the correct way to solve this problem?
Note: That I would also want a solution that does not involve any libraries as I am trying to learn recursion so a recursive solution would be appreciated.
Upvotes: 2
Views: 116
Reputation: 15432
what you're doing is iterating through letters * domain
. What you want is to iterate though letters ^ len(domain)
.
I'll use itertools.product
for this since it's built explicitly for combinatorial products:
import itertools
def printArrays():
letters = {'A', 'B', 'C', 'D', 'E', 'F'}
domain = {1, 2, 3, 4, 5, 6}
myStr = ""
for current in itertools.product(domain, repeat=len(letters)):
for k, v in zip(letters, current):
myStr += k + "=" + str(v) + " "
myStr += "\n"
print(myStr)
This prints what you're looking for:
E=1 D=1 F=1 B=1 A=1 C=1
E=1 D=1 F=1 B=1 A=1 C=2
E=1 D=1 F=1 B=1 A=1 C=3
E=1 D=1 F=1 B=1 A=1 C=4
E=1 D=1 F=1 B=1 A=1 C=5
E=1 D=1 F=1 B=1 A=1 C=6
E=1 D=1 F=1 B=1 A=2 C=1
E=1 D=1 F=1 B=1 A=2 C=2
E=1 D=1 F=1 B=1 A=2 C=3
E=1 D=1 F=1 B=1 A=2 C=4
E=1 D=1 F=1 B=1 A=2 C=5
E=1 D=1 F=1 B=1 A=2 C=6
E=1 D=1 F=1 B=1 A=3 C=1
...
E=6 D=6 F=6 B=6 A=6 C=2
E=6 D=6 F=6 B=6 A=6 C=3
E=6 D=6 F=6 B=6 A=6 C=4
E=6 D=6 F=6 B=6 A=6 C=5
E=6 D=6 F=6 B=6 A=6 C=6
Upvotes: 4
Reputation: 92430
Notice that A=
, B=
, C=
is the same for every row. As others have pointed out the numbers are just the cartesian product of the set of numbers. With that in mind, you could make a simple recursive function to handle the product, and then zip in the letters. Python generators allow you to do this in a memory efficient way — you don't need to store all the combinations in memory:
n = [1,2,3]
keys = ['A','B','C']
# Generate product
def rec_product(l, r):
if r > 1:
yield from ((*t, n) for t in rec_product(l, r-1) for n in l)
else:
yield from ((n,) for n in l)
# add the letters and print
for p in rec_product(n, len(n)):
print(*(f'{k}={v}' for k, v in zip(keys, p)))
This will print:
A=1 B=1 C=1
A=1 B=1 C=2
A=1 B=1 C=3
…
A=3 B=3 C=2
A=3 B=3 C=3
Upvotes: 1
Reputation: 15432
This addresses the problem with a recursive approach:
def add_domain_for_remaining_letters(letters, domain, prefix=""):
# termination condition:
# if no remaining letters, just return the prefix
if len(letters) == 0:
return prefix + "\n"
# otherwise, loop over each i in the domain
# and recurse for each remaining letter
result = ""
for i in domain:
result += add_domain_for_remaining_letters(
letters=letters[1:], domain=domain, prefix=f"{prefix}{letters[0]}={i} "
)
return result
This gives the desired output as a string:
In [20]: print(add_domain_for_remaining_letters(letters=["A", "B"], domain=[1, 2]))
A=1 B=1
A=1 B=2
A=2 B=1
A=2 B=2
In [21]: print(add_domain_for_remaining_letters(letters=["A", "B", "C", "D"], domain=[1, 2, 3]))
A=1 B=1 C=1 D=1
A=1 B=1 C=1 D=2
A=1 B=1 C=1 D=3
A=1 B=1 C=2 D=1
...
A=3 B=3 C=2 D=1
A=3 B=3 C=2 D=2
A=3 B=3 C=2 D=3
A=3 B=3 C=3 D=1
A=3 B=3 C=3 D=2
A=3 B=3 C=3 D=3
Upvotes: 1
Reputation: 1380
The value assignment is like Cartesian product of list1, so using itertools.product
.
import itertools
list1 = [1, 2, 3]
list2 = ['A', 'B', 'C']
assignment_list = itertools.product(list1, repeat=len(list2))
buffer = ""
for assignment in assignment_list:
for var, val in zip(list2, assignment):
buffer += f"{var}={val} "
buffer += "\n"
print(buffer)
Upvotes: 2