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

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.

Related

Iterating 2 permutation sets

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)))

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)

Get all combination of list with repeated values

How can i get a list of all possible values of a list with also repeated ones?
I've tried itertools.combination_with_replacement and itertools.permutation but the first exclude the inverted order (such as [3, 2, 1]) and the second exclude multiple values (such as [3, 3, 1]).
I need something like this:
Example:
list = [1, 2, 3]
results =
[1, 1, 1]
[1, 1, 2]
[1, 1, 3]
...
[3, 1, 1]
[3, 1, 2]
[3, 1, 3]
...
What can I do in Python to achieve this?
Thanks in advance.
You're looking for itertools.product, setting the repetition to 3:
>>> from itertools import product
>>> lst = [1, 2, 3]
>>> list(product(lst, repeat=3))
[(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)]

Python- How to use csv.writer with out quotation

I have a list which whose contents have to be written to a csv file, with out quotation.
The contents of the list is as shown below:
list=[(1, 2, 1), (1, 3, 1), (1, 4, 1), (1, 5, 1), (2, 1, 1), (2, 3, 1), (2, 4, 1), (2, 5, 1), (3, 1, 1), (3, 2, 1), (3, 4, 1), (3, 5, 1), (4, 1, 1), (4, 2, 1), (4, 3, 1), (4, 5, 1), (5, 1, 1), (5, 2, 1), (5, 3, 1), (5, 4, 1)]
Now i have the below two code snippet which tries to write this list to a csv file:
Method 1:
def method1():
list=[(1, 2, 1), (1, 3, 1), (1, 4, 1), (1, 5, 1), (2, 1, 1), (2, 3, 1), (2, 4, 1), (2, 5, 1), (3, 1, 1), (3, 2, 1), (3, 4, 1), (3, 5, 1), (4, 1, 1), (4, 2, 1), (4, 3, 1), (4, 5, 1), (5, 1, 1), (5, 2, 1), (5, 3, 1), (5, 4, 1)]
myfile = open('output.csv', 'w')
wr = csv.writer(myfile, quoting = csv.QUOTE_NONE, delimiter=',', escapechar=',')
wr.writerow(list)
The contents of the csv file are as shown below:
(1,, 2,, 1),(1,, 3,, 1),(1,, 4,, 1),(1,, 5,, 1),(2,, 1,, 1),(2,, 3,, 1),(2,, 4,, 1),(2,, 5,, 1),(3,, 1,, 1),(3,, 2,, 1),(3,, 4,, 1),(3,, 5,, 1),(4,, 1,, 1),(4,, 2,, 1),(4,, 3,, 1),(4,, 5,, 1),(5,, 1,, 1),(5,, 2,, 1),(5,, 3,, 1),(5,, 4,, 1)
I do not want the "," in between the elements of the list. If i remove the escapechar form the above code, it throws me an error.
The error is:
_csv.Error: need to escape, but no escapechar set
Method 2:
def method2():
list=[(1, 2, 1), (1, 3, 1), (1, 4, 1), (1, 5, 1), (2, 1, 1), (2, 3, 1), (2, 4, 1), (2, 5, 1), (3, 1, 1), (3, 2, 1), (3, 4, 1), (3, 5, 1), (4, 1, 1), (4, 2, 1), (4, 3, 1), (4, 5, 1), (5, 1, 1), (5, 2, 1), (5, 3, 1), (5, 4, 1)]
myfile = open('output.csv', 'wb')
wr = csv.writer(myfile)
wr.writerow(list)
The output of method 2 is as shown below:
"(1, 2, 1)","(1, 3, 1)","(1, 4, 1)","(1, 5, 1)","(2, 1, 1)","(2, 3, 1)","(2, 4, 1)","(2, 5, 1)","(3, 1, 1)","(3, 2, 1)","(3, 4, 1)","(3, 5, 1)","(4, 1, 1)","(4, 2, 1)","(4, 3, 1)","(4, 5, 1)","(5, 1, 1)","(5, 2, 1)","(5, 3, 1)","(5, 4, 1)"
Could anybody help me out with the issue?
The contents of my output file must look like this:
(1, 2, 1),
(1, 3, 1),
(1, 4, 1),
(1, 5, 1),
...
...
You don't need csv at all, look at this:
>>> list=[(1, 2, 1), (1, 3, 1), (1, 4, 1), (1, 5, 1), (2, 1, 1), (2, 3, 1), (2, 4, 1), (2, 5, 1), (3, 1, 1), (3, 2, 1), (3, 4, 1), (3, 5, 1), (4, 1, 1), (4, 2, 1), (4, 3, 1), (4, 5, 1), (5, 1, 1), (5, 2, 1), (5, 3, 1), (5, 4, 1)]
>>> with open('out.txt', 'w') as out:
... for t in list:
... out.write(str(t)+",\n")
...
>>>
host:~$ head out.txt
(1, 2, 1),
(1, 3, 1),
(1, 4, 1),
(1, 5, 1),
(2, 1, 1),
(2, 3, 1),
(2, 4, 1),
(2, 5, 1),
(3, 1, 1),
(3, 2, 1),
The format you describe doesn't seem to require the csv module. You can just write out the format using something like this:
list=[(1, 2, 1), (1, 3, 1), (1, 4, 1), (1, 5, 1), (2, 1, 1), (2, 3, 1), (2, 4, 1), (2, 5, 1), (3, 1, 1), (3, 2, 1), (3, 4, 1), (3, 5, 1), (4, 1, 1), (4, 2, 1), (4, 3, 1), (4, 5, 1), (5, 1, 1), (5, 2, 1), (5, 3, 1), (5, 4, 1)]
with open("output.csv", "w") as out_f:
for item in list:
output_str = "{},\n".format(item)
out_f.write(output_str)

get adjacent matrix of point in python

If in 2D, p(x,y), I'd like to have a adjacent matrix of 3*3:
(x-1,y-1), (x,y-1), (x+1,y-1),
...
(x-1,y+1), (x,y+1), (x+1,y+1),
What if in 3D(3*3*3), 4D(3*3*3*3),...?
Is there better function?
You might also be able to use itertools.product, depending on exactly what output format you prefer. It'll be slower than a numpy approach but I find it easier to understand:
from itertools import product
def adjacent_grid(centre):
steps = product([-1, 0, 1], repeat=len(centre))
return (tuple(c+d for c,d in zip(centre, delta)) for delta in steps)
which gives
>>> list(adjacent_grid((3,)))
[(2,), (3,), (4,)]
>>> list(adjacent_grid((3,3)))
[(2, 2), (2, 3), (2, 4), (3, 2), (3, 3), (3, 4), (4, 2), (4, 3), (4, 4)]
>>> list(adjacent_grid((3,3,3)))
[(2, 2, 2), (2, 2, 3), (2, 2, 4), (2, 3, 2), (2, 3, 3), (2, 3, 4), (2, 4, 2), (2, 4, 3), (2, 4, 4), (3, 2, 2), (3, 2, 3), (3, 2, 4), (3, 3, 2), (3, 3, 3), (3, 3, 4), (3, 4, 2), (3, 4, 3), (3, 4, 4), (4, 2, 2), (4, 2, 3), (4, 2, 4), (4, 3, 2), (4, 3, 3), (4, 3, 4), (4, 4, 2), (4, 4, 3), (4, 4, 4)]
You can get the result by using broadcasting in numpy:
import numpy as np
def p(*args):
args = np.array(args)
idx = np.array([-1, 0, 1])
a = np.broadcast_arrays(*np.ix_(*(args[:,None] + idx)))
return np.concatenate([x[..., None] for x in a], axis=-1)
The result shape is (3,3,2) in 2D, (3,3,3,3) in 3D, (3,3,3,3,4) in 4D:
>>> p(3, 8)
array([[[2, 7],
[2, 8],
[2, 9]],
[[3, 7],
[3, 8],
[3, 9]],
[[4, 7],
[4, 8],
[4, 9]]])

Categories

Resources