Iterating 2 permutation sets - python

Let's say I start with these two hypothetical lists: color and shape.
I have 15 colors and let's say a recursively infinite number of shapes (like number of sides of a regular ngon). At its most basic it starts like
color_list, shape_list = [1], [1]
up to the complexity I mentioned, one example of length 3 might be
color_list, shape_list = [15,9,7], [1,3,7]
These numbers are arbitrary to compare one particular permutation that combines color 15 with shape 1, color 9 with shape 3, color 7 with shape 7.
How would I create an iteration over every possible permutation that returns something from the [1], [1] up to say [15,15,15,15,15], [n,n,n,n,n]?

IIUC, you are trying to do the following -
Create color, shape combinations with some lower and upper limit for each (color = 3, shape = 5), (color = 1, shape = 99) etc.
Then you are trying to permute over these color combinations for each permutation order from 1 to m (in your example m = 5)
Here is a piece of code that should get you something similar. Please do note, this will explode exponentially, so avoid larger limits.
import itertools
color_i = 1
color_n = 5
shape_i = 1
shape_n = 6
permutes = 3
# color, shape combos
combos = list(itertools.product(range(color_i, color_n+1), range(shape_i, shape_n+1)))
# create permutations from the color, shape combos
permutations = []
for p in range(permutes):
for i in itertools.permutations(combos,r=p+1):
permutations.append(list(zip(*i)))
permutations
[[(1,), (1,)],
[(1,), (2,)],
[(1,), (3,)],
[(1,), (4,)],
[(1,), (5,)],
[(1,), (6,)],
[(2,), (1,)],
[(2,), (2,)],
[(2,), (3,)],
[(2,), (4,)],
[(2,), (5,)],
[(2,), (6,)],
[(3,), (1,)],
[(3,), (2,)],
[(3,), (3,)],
[(3,), (4,)],
[(3,), (5,)],
[(3,), (6,)],
[(4,), (1,)],
[(4,), (2,)],
[(4,), (3,)],
[(4,), (4,)],
[(4,), (5,)],
[(4,), (6,)],
[(5,), (1,)],
[(5,), (2,)],
[(5,), (3,)],
[(5,), (4,)],
[(5,), (5,)],
[(5,), (6,)],
[(1, 1), (1, 2)],
[(1, 1), (1, 3)],
...,
[(1, 4), (1, 2)],
[(1, 4), (1, 3)],
[(1, 4), (1, 4)],
[(1, 4), (1, 5)],
[(1, 4), (1, 6)],
[(1, 5), (1, 1)],
[(1, 5), (1, 2)],
[(1, 5), (1, 3)],
[(1, 5), (1, 4)],
[(1, 5), (1, 5)],
[(1, 5), (1, 6)],
[(1, 1), (2, 1)],
[(1, 1), (2, 3)],
[(1, 1), (2, 4)],
[(1, 1), (2, 5)],
[(1, 1), (2, 6)],
[(1, 2), (2, 1)],
[(1, 2), (2, 2)],
...,
[(4, 4), (3, 6)],
[(4, 5), (3, 1)],
[(4, 5), (3, 2)],
[(4, 5), (3, 3)],
[(4, 5), (3, 4)],
[(4, 5), (3, 5)],
[(4, 5), (3, 6)],
[(4, 1), (4, 1)],
[(4, 1), (4, 2)],
[(4, 1), (4, 3)],
[(4, 1), (4, 4)],
[(4, 1), (4, 5)],
...,
[(5, 5), (6, 2)],
[(5, 5), (6, 3)],
[(5, 5), (6, 4)],
[(5, 5), (6, 5)],
[(1, 1, 1), (1, 2, 3)],
[(1, 1, 1), (1, 2, 4)],
[(1, 1, 1), (1, 2, 5)],
[(1, 1, 1), (1, 2, 6)],
[(1, 1, 2), (1, 2, 1)],
[(1, 1, 2), (1, 2, 2)],
[(1, 1, 2), (1, 2, 3)],
...,
[(1, 1, 4), (1, 2, 6)],
[(1, 1, 5), (1, 2, 1)],
[(1, 1, 5), (1, 2, 2)],
[(1, 1, 5), (1, 2, 3)],
[(1, 1, 5), (1, 2, 4)],
[(1, 1, 5), (1, 2, 5)],
[(1, 1, 5), (1, 2, 6)],
[(1, 1, 1), (1, 3, 2)],
[(1, 1, 1), (1, 3, 4)],
[(1, 1, 1), (1, 3, 5)],
[(1, 1, 1), (1, 3, 6)],
[(1, 1, 2), (1, 3, 1)],
[(1, 1, 2), (1, 3, 2)],
[(1, 1, 2), (1, 3, 3)],
[(1, 1, 2), (1, 3, 4)],
[(1, 1, 2), (1, 3, 5)],
[(1, 1, 2), (1, 3, 6)],
[(1, 1, 3), (1, 3, 1)],
[(1, 1, 3), (1, 3, 2)],
[(1, 1, 3), (1, 3, 3)],
[(1, 1, 3), (1, 3, 4)],
[(1, 1, 3), (1, 3, 5)],
[(1, 1, 3), (1, 3, 6)],
[(1, 1, 4), (1, 3, 1)],
[(1, 1, 4), (1, 3, 2)],
[(1, 1, 4), (1, 3, 3)],
[(1, 1, 4), (1, 3, 4)],
[(1, 1, 4), (1, 3, 5)],
[(1, 1, 4), (1, 3, 6)],
[(1, 1, 5), (1, 3, 1)],
[(1, 1, 5), (1, 3, 2)],
[(1, 1, 5), (1, 3, 3)],
[(1, 1, 5), (1, 3, 4)],
[(1, 1, 5), (1, 3, 5)],
[(1, 1, 5), (1, 3, 6)],
[(1, 1, 1), (1, 4, 2)],
[(1, 1, 1), (1, 4, 3)],
[(1, 1, 1), (1, 4, 5)],
[(1, 1, 1), (1, 4, 6)],
[(1, 1, 2), (1, 4, 1)],
[(1, 1, 2), (1, 4, 2)],
[(1, 1, 2), (1, 4, 3)],
[(1, 1, 2), (1, 4, 4)],
[(1, 1, 2), (1, 4, 5)],
[(1, 1, 2), (1, 4, 6)],
[(1, 1, 3), (1, 4, 1)],
[(1, 1, 3), (1, 4, 2)],
[(1, 1, 3), (1, 4, 3)],
[(1, 1, 3), (1, 4, 4)],
[(1, 1, 3), (1, 4, 5)],
[(1, 1, 3), (1, 4, 6)],
...]
How it works -
Create itertools.product using ranges for color and shape. This gives you all possible (color, shape) tuples.
For permutation order 1 to m (1, 2, 3, ..., m) permute over this list of all possible tuples k times where 1>=k>=m
Use list(zip(*i)) on each generated permutation to transpose it from [(color1, shape1), (color2, shape2), (color3, shape3)] to [(color1, color2, color3), (shape1, shape2, shape3)]

You have a number of parameters:
the number of possible colours (for example, 2)
the number of possible shapes (for example, 3)
the number of colour / shape combinations (for example, 4)
In Python:
n_colours = 2
colours = range(1, n_colours+1)
n_shapes = 3
shapes = range(1, n_shapes+1)
# creating a list of all possible combinations of colours and shapes:
all_pairs = list(product(colours, shapes))
You asked to get the combinations in two separate lists of the colours and the corresponding shapes. It seems more sensible to generate them as tuples of pairs instead:
from itertools import product
max_len = 4
tuples = [t for p in [product(all_pairs, repeat=n) for n in range(1, max_len+1)] for t in p]
But if you wanted to generate them as pairs of separate colours and shapes instead, here's an implementation that generates them one after the other:
from itertools import product
def all_colour_shape_pairs(n_colours, n_shapes, max_len):
ps = list(product(range(1, n_colours+1), range(1, n_shapes+1)))
for t in [t for p in [product(ps, repeat=n) for n in range(1, max_len+1)] for t in p]:
yield zip(*t)
result = all_colour_shape_pairs(2, 3, 4)
while input('Press enter for another, or enter "x" to stop:') != 'x':
print(tuple(next(result)))
Output
((1,), (1,))
((1,), (2,))
((1,), (3,))
((2,), (1,))
...
((2,), (3,))
((1, 1), (1, 1))
((1, 1), (1, 2))
...
((2, 2), (3, 3))
((1, 1, 1), (1, 1, 1))
((1, 1, 1), (1, 1, 2))
...
And if you want the generator to keep generating results "inifinitely" (or rather, to stop when the computer runs out of resources and is unable to continue):
from itertools import product
def all_colour_shape_pairs(n_colours, n_shapes, max_len):
ps = list(product(range(1, n_colours+1), range(1, n_shapes+1)))
n = 1
while True:
for t in product(ps, repeat=n):
yield zip(*t)
n += 1
result = all_colour_shape_pairs(2, 3, 4)
while input('Press enter for another, or enter "x" to stop:') != 'x':
print(tuple(next(result)))

Related

How to write this in an eaiser way?

How could I write this in an eaiser way?
product_pairs =
[[(1, 2), (1, 3), (1, 6), (1, 8), (1, 9), (2, 3), (2, 6), (2, 8), (2, 9), (3, 6), (3,
8), (3, 9), (6, 8), (6, 9), (8, 9)],
[(0, 5), (0, 9), (5, 9)],
[(0, 9)],
[(0, 4), (0, 5), (0, 7), (0, 9), (4, 5), (4, 7), (4, 9), (5, 7), (5, 9), (7, 9)],
[(3, 8)],
[(1, 3), (1, 6), (1, 8), (3, 6), (3, 8), (6, 8)],
[(0, 5), (0, 9), (5, 9)],
[(3, 8)],
[(0, 4), (0, 5), (0, 7), (4, 5), (4, 7), (5, 7)],
[(0, 1), (0, 2), (0, 3), (0, 6), (1, 2), (1, 3), (1, 6), (2, 3), (2, 6), (3, 6)]]
cooccurences={}
d={}
pairs=[]
for lists in product_pairs:
for pair in lists:
if pair not in pairs: # If the pair is not in the dictionary
pairs.append(pair) # Storing all the pairs in a list
d[pair]=1 # Adding to the dictionary with value 1
else: # If the pair is already in the dictionary
d[pair]+=1 # Incrementing its value by 1
pairs.sort() # Sorting the pairs list
for pair in pairs: # Iterating through all pairs in sorted order
cooccurences[pair]=d[pair] # Storing their value in a dictionary
print(cooccurences) # Displaying output
Output:
{(0, 1): 1, (0, 2): 1, (0, 3): 1, (0, 4): 2, (0, 5): 4, (0, 6): 1, (0, 7): 2, (0, 9): 4, (1, 2): 2, (1, 3): 3, (1, 6): 3, (1, 8): 2, (1, 9): 1, (2, 3): 2, (2, 6): 2, (2, 8): 1, (2, 9): 1, (3, 6): 3, (3, 8): 4, (3, 9): 1, (4, 5): 2, (4, 7): 2, (4, 9): 1, (5, 7): 2, (5, 9): 3, (6, 8): 2, (6, 9): 1, (7, 9): 1, (8, 9): 1}
Best done using collections.Counter (also take a look at collections.defaultdict for a slightly more "manual" approach):
from collections import Counter
counter = Counter(pair for product_list in product_pairs for pair in product_list)
print(dict(counter.most_common()))

How to I scale a list up in size?

I have a list that looks like this:
[
[(0, 0, 0), (1, 1, 1), (2, 2, 2)],
[(1, 1, 1), (2, 2, 2), (3, 3, 3)],
[(2, 2, 2), (3, 3, 3), (4, 4, 4)]
]
I want to scale it up by 3, so it looks like this:
[
[(0, 0, 0), (0, 0, 0), (0, 0, 0), (1, 1, 1), (1, 1, 1), (1, 1, 1), (2, 2, 2), (2, 2, 2), (2, 2, 2)],
[(0, 0, 0), (0, 0, 0), (0, 0, 0), (1, 1, 1), (1, 1, 1), (1, 1, 1), (2, 2, 2), (2, 2, 2), (2, 2, 2)],
[(0, 0, 0), (0, 0, 0), (0, 0, 0), (1, 1, 1), (1, 1, 1), (1, 1, 1), (2, 2, 2), (2, 2, 2), (2, 2, 2)]
[(1, 1, 1), (1, 1, 1), (1, 1, 1), (2, 2, 2), (2, 2, 2), (2, 2, 2), (3, 3, 3), (3, 3, 3), (3, 3, 3)],
[(1, 1, 1), (1, 1, 1), (1, 1, 1), (2, 2, 2), (2, 2, 2), (2, 2, 2), (3, 3, 3), (3, 3, 3), (3, 3, 3)],
[(1, 1, 1), (1, 1, 1), (1, 1, 1), (2, 2, 2), (2, 2, 2), (2, 2, 2), (3, 3, 3), (3, 3, 3), (3, 3, 3)]
[(2, 2, 2), (2, 2, 2), (2, 2, 2), (3, 3, 3), (3, 3, 3), (3, 3, 3), (4, 4, 4), (4, 4, 4), (4, 4, 4)],
[(2, 2, 2), (2, 2, 2), (2, 2, 2), (3, 3, 3), (3, 3, 3), (3, 3, 3), (4, 4, 4), (4, 4, 4), (4, 4, 4)],
[(2, 2, 2), (2, 2, 2), (2, 2, 2), (3, 3, 3), (3, 3, 3), (3, 3, 3), (4, 4, 4), (4, 4, 4), (4, 4, 4)]
]
Is there any way to do this that will also work for scale factors other than 3?
numpy has a function to repeat elements in a given axis:
import numpy as np
x = [
[(0, 0, 0), (1, 1, 1), (2, 2, 2)],
[(1, 1, 1), (2, 2, 2), (3, 3, 3)],
[(2, 2, 2), (3, 3, 3), (4, 4, 4)]
]
x = np.repeat(x, 3, axis=0)
x = np.repeat(x, 3, axis=1)

Splitting a list into all combinations

I am aware of many posts with the similar questions and have been through many of them. However, I am not able to do what I need.
I have list L=[0,1,2,3,4,5] which I want to split into a pair of tuples. For example:
[(0,1,2),(3,4,5)]
[(0,1,3),(2,4,5)]
[(0,1,4),(2,4,5)]
...
Each tuple needs to contain half of the elements from the original list (in this example 3 of 6). A solution needs to produce every combination of tuples using 3 elements.
I can easily find all the possible tuple within the list using
list(itertools.combinations(L, 3))
[(0, 1, 2),
(0, 1, 3),
(0, 1, 4),
(0, 1, 5),
(0, 2, 3),
(0, 2, 4),
...]
Does itertools offers any workround for this as well?
There may be more performant solutions that avoid a complete extra iteration of the list for the other half, but that should be rather negligible:
l = [[x, tuple(y for y in L if y not in x)] for x in combinations(L, 3)]
[[(0, 1, 2), (3, 4, 5)],
[(0, 1, 3), (2, 4, 5)],
[(0, 1, 4), (2, 3, 5)],
[(0, 1, 5), (2, 3, 4)],
[(0, 2, 3), (1, 4, 5)],
[(0, 2, 4), (1, 3, 5)],
[(0, 2, 5), (1, 3, 4)],
[(0, 3, 4), (1, 2, 5)],
[(0, 3, 5), (1, 2, 4)],
[(0, 4, 5), (1, 2, 3)],
[(1, 2, 3), (0, 4, 5)],
[(1, 2, 4), (0, 3, 5)],
[(1, 2, 5), (0, 3, 4)],
[(1, 3, 4), (0, 2, 5)],
[(1, 3, 5), (0, 2, 4)],
[(1, 4, 5), (0, 2, 3)],
[(2, 3, 4), (0, 1, 5)],
[(2, 3, 5), (0, 1, 4)],
[(2, 4, 5), (0, 1, 3)],
[(3, 4, 5), (0, 1, 2)]]
This depends on the absence of duplicates in the original list. Otherwise you'd have to work with the indexes instead. The following modification uses the same approach, but uses the list indexes for the combinations and can thus handle duplicates in the original list:
indexes = ((x, (y for y in L if y not in x)) for x in combinations(range(len(L)), 3))
l = [[tuple(L[a] for a in A), tuple(L[b] for b in B)] for A, B in indexes]

How to use itertools to output results of only a certain length

Suppose I have a list of bytes (x00 to xFF). How can I use itertools to return only permutations that have length of X.
So for example I want all permutations with length 3, then I'll get
[x00,x00,x00], [x00,x00,x01], ..., [xFF,xFF,xFF]
That way there is no waste of computing resources.
EDIT: Doesn't have to be itertools if there is a better way.
import itertools
for tup in itertools.product(range(0x100), repeat=3):
...
It seems #gnibbler's solution is more correct?
In [162]: >>> l = [1, 2, 3]
In [163]: list(itertools.combinations_with_replacement(l, 3))
Out[163]:
[(1, 1, 1),
(1, 1, 2),
(1, 1, 3),
(1, 2, 2),
(1, 2, 3),
(1, 3, 3),
(2, 2, 2),
(2, 2, 3),
(2, 3, 3),
(3, 3, 3)]
In [164]: list(itertools.product(l, repeat=3))
Out[164]:
[(1, 1, 1),
(1, 1, 2),
(1, 1, 3),
(1, 2, 1),
(1, 2, 2),
(1, 2, 3),
(1, 3, 1),
(1, 3, 2),
(1, 3, 3),
(2, 1, 1),
(2, 1, 2),
(2, 1, 3),
(2, 2, 1),
(2, 2, 2),
(2, 2, 3),
(2, 3, 1),
(2, 3, 2),
(2, 3, 3),
(3, 1, 1),
(3, 1, 2),
(3, 1, 3),
(3, 2, 1),
(3, 2, 2),
(3, 2, 3),
(3, 3, 1),
(3, 3, 2),
(3, 3, 3)]
itertools.combinations_with_replacement:
>>> my_list = [1, 2, 3, 4]
>>> import itertools
>>>
>>> list(itertools.combinations_with_replacement(my_list, 3))
[(1, 1, 1), (1, 1, 2), (1, 1, 3), (1, 1, 4),
(1, 2, 2), (1, 2, 3), (1, 2, 4),
(1, 3, 3), (1, 3, 4),
(1, 4, 4),
(2, 2, 2), (2, 2, 3), (2, 2, 4),
(2, 3, 3), (2, 3, 4),
(2, 4, 4),
(3, 3, 3), (3, 3, 4),
(3, 4, 4),
(4, 4, 4)]
Seems like you want all the permutations, with replacement. In that case, you need: itertools.product as in #gnibbler's answer.

itertools: Cartesian product of permutations [duplicate]

This question already has answers here:
Expanding tuples into arguments
(5 answers)
Closed 8 months ago.
Using pythons itertools, I'd like to create an iterator over the outer product of all permutations of a bunch of lists. An explicit example:
import itertools
A = [1,2,3]
B = [4,5]
C = [6,7]
for x in itertools.product(itertools.permutations(A),itertools.permutations(B),itertools.permutations(C)):
print x
While this works, I'd like to generalize it to an arbitrary list of lists. I tried:
for x in itertools.product(map(itertools.permutations,[A,B,C])):
print x
but it did not do what I intended. The expected output is:
((1, 2, 3), (4, 5), (6, 7))
((1, 2, 3), (4, 5), (7, 6))
((1, 2, 3), (5, 4), (6, 7))
((1, 2, 3), (5, 4), (7, 6))
((1, 3, 2), (4, 5), (6, 7))
((1, 3, 2), (4, 5), (7, 6))
((1, 3, 2), (5, 4), (6, 7))
((1, 3, 2), (5, 4), (7, 6))
((2, 1, 3), (4, 5), (6, 7))
((2, 1, 3), (4, 5), (7, 6))
((2, 1, 3), (5, 4), (6, 7))
((2, 1, 3), (5, 4), (7, 6))
((2, 3, 1), (4, 5), (6, 7))
((2, 3, 1), (4, 5), (7, 6))
((2, 3, 1), (5, 4), (6, 7))
((2, 3, 1), (5, 4), (7, 6))
((3, 1, 2), (4, 5), (6, 7))
((3, 1, 2), (4, 5), (7, 6))
((3, 1, 2), (5, 4), (6, 7))
((3, 1, 2), (5, 4), (7, 6))
((3, 2, 1), (4, 5), (6, 7))
((3, 2, 1), (4, 5), (7, 6))
((3, 2, 1), (5, 4), (6, 7))
((3, 2, 1), (5, 4), (7, 6))
You missed the * to unpack the list into 3 arguments
itertools.product(*map(itertools.permutations,[A,B,C]))

Categories

Resources