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]]])
Related
a = []
def make_squares(arr, length, nums):
if not nums:
print(arr)
a.append(arr)
return
r = 0
while r < len(arr) and len(arr[r]) == length:
r += 1
for i in nums:
nums.remove(i)
arr[r].append(i)
make_squares(arr, length, nums)
nums.append(i)
arr[r] = arr[r][:-1]
make_squares([[] for i in range(3)], 3, [i+1 for i in range(3**2)])
print(a)
I'm trying to use the above code to create nxn matrices each with a permutation of the numbers i+1...n^2. I have printed every matrix that gets appended to a and they appear correct, but when I print a in the end, I get [[[], [], []], [[], [], []], ...]. It doesn't make any sense to me.
The expected result would be
[[[1, 2, 3], [4, 5, 6], [7, 8, 9]], [[1, 2, 3], [4, 5, 6], [7, 9, 8]], ...]
The order may not be the same as in your expected result, but this does the trick with the standard library itertools module:
import itertools
def make_squares(w):
size = w * w
for perm in itertools.permutations(range(1, size + 1)):
# "grouper" from the itertools recipe list
yield list(itertools.zip_longest(*[iter(perm)] * w))
for square in make_squares(3):
print(square)
prints
[(1, 2, 3), (4, 5, 6), (7, 8, 9)]
[(1, 2, 3), (4, 5, 6), (7, 9, 8)]
[(1, 2, 3), (4, 5, 6), (8, 7, 9)]
[(1, 2, 3), (4, 5, 6), (8, 9, 7)]
[(1, 2, 3), (4, 5, 6), (9, 7, 8)]
[(1, 2, 3), (4, 5, 6), (9, 8, 7)]
[(1, 2, 3), (4, 5, 7), (6, 8, 9)]
[(1, 2, 3), (4, 5, 7), (6, 9, 8)]
[(1, 2, 3), (4, 5, 7), (8, 6, 9)]
[(1, 2, 3), (4, 5, 7), (8, 9, 6)]
[(1, 2, 3), (4, 5, 7), (9, 6, 8)]
[(1, 2, 3), (4, 5, 7), (9, 8, 6)]
[(1, 2, 3), (4, 5, 8), (6, 7, 9)]
[(1, 2, 3), (4, 5, 8), (6, 9, 7)]
[(1, 2, 3), (4, 5, 8), (7, 6, 9)]
...
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)]
For example I have a list of objects like this:
[[{1},{2},{3}],[{4},{5}],[{6},{7},{8}]]
I need to iterate through them all to get on each iteration objects like:
1,4,6
1,4,7
1,4,8
1,5,6
1,5,7
1,5,8
2,4,6
2,4,7
2,4,8
2,5,6
2,5,7
2,5,8
Basically each result is like a sub array of the input lists.
You can easily use itertools.product
>>> import itertools
>>> x = list(itertools.product([1,2,3],[4,5],[6,7,8]))
[(1, 4, 6), (1, 4, 7), (1, 4, 8), (1, 5, 6), (1, 5, 7), (1, 5, 8), (2, 4, 6), (2, 4, 7), (2, 4, 8), (2, 5, 6), (2, 5, 7), (2, 5, 8), (3, 4, 6), (3, 4, 7), (3, 4, 8), (3, 5, 6), (3, 5, 7), (3, 5, 8)]
Note that the output of every combination you are looking for is called the Cartesian product of your input lists.
How can I use itertools.product function if I don't know the number of the lists? I have list and it has lists inside of it.
Like,
lis = [[1,2,3],[6,7,8],[2,4,5]]
Normally I need to do,
product([1,2,3],[6,7,8],[2,4,5])
How do I do that if the input is a list like in the example?
Try the following:
product(*lis)
It's called argument unpacking.
Short note: you can use argument unpacking with named parameters also, with double star:
def simpleSum(a=1,b=2):
return a + b
simpleSum(**{'a':1,'b':2}) # returns 3
Use argument unpacking:
>>> lis = [[1,2,3],[6,7,8],[2,4,5]]
>>> list(itertools.product(*lis))
[(1, 6, 2), (1, 6, 4), (1, 6, 5), (1, 7, 2), (1, 7, 4), (1, 7, 5), (1, 8, 2),
(1, 8, 4), (1, 8, 5), (2, 6, 2), (2, 6, 4), (2, 6, 5), (2, 7, 2), (2, 7, 4),
(2, 7, 5), (2, 8, 2), (2, 8, 4), (2, 8, 5), (3, 6, 2), (3, 6, 4), (3, 6, 5),
(3, 7, 2), (3, 7, 4), (3, 7, 5), (3, 8, 2), (3, 8, 4), (3, 8, 5)]
>>>
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.