I am desperately trying to get all the permutations of a list while enforcing position assignment constraints.
I have a list [1,2,3,4,5,6] (6 is just an example, I would like to find something that could work with every lenght) and I want to find all the lists of lenght 3 (also an example) with the following constraints :
position 1 can be occupied by numbers 1 and 2
position 2 can be occupied by numbers 1,2 and 3
position 3 can be occupied by numbers 2,3 and 4
repetions of a same number are not allowed
That would give these lists : [1,2,3],[1,2,4],[1,3,2],[1,3,4],[2,1,3],[2,3,4],[2,1,4]
For those interested, what I am trying to implement is what is explained pages 5 and 6 of this paper
Filter the product() of those subsets:
from itertools import product
for combo in product([1, 2], [1, 2, 3], [2, 3, 4]):
if len(set(combo)) == 3:
print(combo)
or as a list comprehension:
[combo for combo in product([1, 2], [1, 2, 3], [2, 3, 4]) if len(set(combo)) == 3]
Output:
>>> from itertools import product
>>> [combo for combo in product([1, 2], [1, 2, 3], [2, 3, 4]) if len(set(combo)) == 3]
[(1, 2, 3), (1, 2, 4), (1, 3, 2), (1, 3, 4), (2, 1, 3), (2, 1, 4), (2, 3, 4)]
Related
I have originally two lists of numbers, but for this case, let's say I have a list of tuples and I would like to get all the possible combinations such that the output has a member of the first pair in index 0, one of the second pair in index 1, etc.
For example, let the list be: [(1, 2), (3, 4), (5,6)]
And I want to get:
1, 3, 5
1, 3, 6
1, 4, 5
1, 4, 6
2, 3, 5
2, 3, 6
2, 4, 5
2, 4, 6
The list can be of any length. I tried using itertools.permutations over the two original lists like this:
[list(zip(permutation, list2)) for permutation in itertools.permutations(list1, len(list2))]
but it would return all the possible permutations which is not what I need.
This can be done with a vanilla breadth-first search/depth-first search:
a = [(1, 2), (3, 4), (5,6)]
def search(points):
points = list(points)
paths = []
if points:
first_points = points.pop(0)
else:
return [[]]
for point in first_points:
for path in bfs(points):
paths.append([point] + path)
return paths
print(search(a))
Returns:
[1, 3, 5], [1, 3, 6], [1, 4, 5], [1, 4, 6], [2, 3, 5], [2, 3, 6], [2, 4, 5], [2, 4, 6]]
Now, I wrote this hastily and it's not the most efficient code, but it'll do the job
I'm trying to make a general way to generate all the combinations of multiple ranges or lists, for example,
[range(0, 2), range(2, 5), range(4, 6), range(2, 3)],
which should return a 2x3x2x1 = 12 element list.
[[0, 2, 4, 2],
[0, 2, 5, 2],
[0, 3, 4, 2],
[0, 3, 5, 2],
[0, 4, 4, 2],
[0, 4, 5, 2],
[1, 2, 4, 2],
[1, 2, 5, 2],
[1, 3, 4, 2],
[1, 3, 5, 2],
[1, 4, 4, 2],
[1, 4, 5, 2]]
So far, everything is fine here. When I hardcode it, by doing
x = [ ( [a,b] for a in rgs[0] for b in rgs[1] ) ]
x.append( ( a + [b] for a in x[-1] for b in rgs[2]) )
x.append( ( a + [b] for a in x[-1] for b in rgs[3]) )
I get the good result. However, when I attempt to generalize it, by doing
x = [ ( [a,b] for a in rgs[0] for b in rgs[1] ) ]
for i in range(1,len(rgs)-1):
x.append( ( a + [b] for a in x[-1] for b in rgs[i+1]) )
I obtain a 6-element list:
[[0, 2, 2, 2],
[0, 3, 2, 2],
[0, 4, 2, 2],
[1, 2, 2, 2],
[1, 3, 2, 2],
[1, 4, 2, 2]]
Also, what I notice is that all the ranges generated after the first two use the range in rgs[-1] instead of the correct ones. I struggle to understand why this happens, as I beleive that those two code example are identical, except the latter is the more general form for arbitrary large number of ranges.
You can use itertools.product to output a list of tuples
Input:
import itertools
a= [range(0, 2), range(2, 5), range(4, 6), range(2, 3)]
list(itertools.product(*a))
Output:
[(0, 2, 4, 2),
(0, 2, 5, 2),
(0, 3, 4, 2),
(0, 3, 5, 2),
(0, 4, 4, 2),
(0, 4, 5, 2),
(1, 2, 4, 2),
(1, 2, 5, 2),
(1, 3, 4, 2),
(1, 3, 5, 2),
(1, 4, 4, 2),
(1, 4, 5, 2)]
I did not get the same result when running your first code. I had to change it up a bit:
x = [ ( [a,b] for a in rgs[0] for b in rgs[1] ) ]
x.append( ( a + [b] for a in x[-1] for b in rgs[2]) )
x = list( a + [b] for a in x[-1] for b in rgs[3])
Most people that don't know about itertools would have done it this way:
x=[]
for i0 in rgs[0]:
for i1 in rgs[1]:
for i2 in rgs[2]:
for i3 in rgs[3]:
x.append([i0,i1,i2,i3])
Or using a list comprehension (DON'T DO THIS, it is VERY messy looking):
[[i0,i1,i2,i3] for i3 in rgs[3] for i2 in rgs[2] for i1 in rgs[1] for i0 in rgs[0]]
Your issue has to do with creating generator expressions in a loop. Generator expressions are implemented as functions, and like functions, they can have "free" variables that they look up in the containing namespaces. Your generator expressions are accessing the i from outside their definition, and because of this, they end up seeing a different i value you expect.
Here's an example that might be easier to understand:
def gen()
print(i)
yield 10
x = []
for i in range(3):
x.append(gen()) # add several generators while `i` has several different values
for g in x:
list(g) # consume the generators, so they can print `i`
Here, rather than using the i value for something useful, I've written a generator function that just prints it out. If you run this code, you'll see that all the generators print out 2, since that's the value of i when they finally run (after the first loop ended).
Your situation is a little more subtle, as you're consuming the previous generator as you create the next one, but the general idea is the same. The generator expression loop that you expect to be over rgs[2] is actually over rgs[3] because it's actually being looked up with rgs[i+1] and i increased between the time the generator expression was declared and when it was consumed.
This question already has answers here:
How to merge lists into a list of tuples?
(10 answers)
Closed 4 years ago.
I am struggling to combine the values of two arrays in Python. I want to get the values of two arrays as pairs.
EXAMPLE: Suppose we have two arrays a and b as below:
a = [[1, 2, 3], [4, 5, 6], [0, 3, 1]]
for i in range(len(a)):
for j in range(len(a[i])):
print(a[i][j], end=' ')
print()
b = [[4, 0, 3], [6, 3, 6], [1, 4, 1]]
for i in range(len(b)):
for j in range(len(b[i])):
print(b[i][j], end=' ')
print()
How can I combine the values of two arrays as pairs similar to:
array([[(1,4), (2,0), (3,3)],
[(4,6), (5,3), (6,6)],
[(0,1), (3,4), (1,1)]])
I am not sure if it can be done as an array or a list.
You can combine list comprehension and zip() to do that:
a = [[1, 2, 3], [4, 5, 6], [0, 3, 1]]
b = [[4, 0, 3], [6, 3, 6], [1, 4, 1]]
c = [ list(zip(a[x],b[x])) for x in range(len(a))] # works b/c len(a) = len(b)
print(c)
Output
[[(1, 4), (2, 0), (3, 3)], [(4, 6), (5, 3), (6, 6)], [(0, 1), (3, 4), (1, 1)]]
This works correctly as a and b have the same amount of inner lists and the inner lists have the same length. zip() does only create tuples for 2 lists up to the shorter length of both. For inequeal length lists you can use itertools.zip_longest(...) which uses None or a specified default to fill up the shorter list.
I have a list with several sublists (unknown number), e.g.
[[1, 2, 3], [4, 5, 6]]
I want to print the content of sublists, without brackets, in parentheses, separated with commas and gaps like this
(1, 2, 3)
(4, 5, 6)
I have tried using
for i in range(0, len(l)):
print('(',*l[i],')')
but it does not work. It just gives me:
( 1 2 3 )
( 4 5 6 )
which is not what I want
Any idea how I can get the result I need?
This will work:
for i in l:
print('('+",".join(map(str, i))+')')
a=[[1, 2, 3],[4, 5, 6]]
for l in a:
print(tuple(l))
Here are couple of ways to do it:
>>> l = [[1, 2, 3], [4, 5, 6]]
>>> print(*map(tuple, l), sep='\n')
(1, 2, 3)
(4, 5, 6)
>>>
>>> for sub_l in l:
print(tuple(sub_l))
(1, 2, 3)
(4, 5, 6)
I have a list [2,3,4]. How do I find all possible sequence of elements in the list?
So the output should be:
[2,3,4]
[2,4,3]
[3,2,4]
[3,4,2]
[4,2,3]
[4,3,2]
You can do this easily using itertools.permutations():
>>> from itertools import permutations
>>> list(permutations([2, 3, 4]))
[(2, 3, 4), (2, 4, 3), (3, 2, 4), (3, 4, 2), (4, 2, 3), (4, 3, 2)]
And if for some reason you need lists instead of tuples:
>>> map(list, permutations([2, 3, 4]))
[[2, 3, 4], [2, 4, 3], [3, 2, 4], [3, 4, 2], [4, 2, 3], [4, 3, 2]]
You are looking for permutations, something like this should work:
import itertools
itertools.permutations([2,3,4])
a start of a great lottery program except data would be formated as such
ist(permutations([2, 3, 4],[7,2,5],[8,1,4,9]))
the problem is that the first group is used to create numbers in first column only
the secound is for 2 column and 3rd is for 3rd
the output will be a set of 3 numbers just that the permutation is different
Just so you know:
def unique_perms(elems):
"""returns non-duplicate permutations
if duplicate elements exist in `elems`
"""
from itertools import permutations
return list(set(permutations(elems)))
But if you're doing something like this:
print len(unique_perms(elems))
Then try this:
def fac(n):
"""n!"""
if n == 1: return n
return n * fac(n -1)
def unique_perm_count(elems)
n = len(elems)
return fac(2 * n) / fac(n) ** 2