I have the following list of tuples:
>>> import itertools
>>> import numpy as np
>>> grid = list(itertools.product((1,2,3),repeat=2))
>>> grid
[(1, 1), (1, 2), (1, 3), (2, 1), (2, 2), (2, 3), (3, 1), (3, 2), (3, 3)]
I'd like to reshape this list in a sensible way (e.g. using numpy if possible) to be 3x3 as follows:
[[(1, 1), (1, 2), (1, 3)],
[(2, 1), (2, 2), (2, 3)],
[(3, 1), (3, 2), (3, 3)]]
When I do np.reshape(grid, (3, 3)) I get the following error: ValueError: cannot reshape array of size 18 into shape (3,3) (size 18??)
I've tried variations of np.reshape(grid, (3, 3, 2)) but these don't return the 3x3 grid given above.
This will do the job:
new_grid = np.empty(len(grid), dtype='object')
new_grid[:] = grid
new_grid = new_grid.reshape(3, 3)
This outputs:
array([[(1, 1), (1, 2), (1, 3)],
[(2, 1), (2, 2), (2, 3)],
[(3, 1), (3, 2), (3, 3)]], dtype=object)
The object type will remain tuple:
type(new_grid[0, 0])
tuple
18 comes from the fact that you have a list of 9 tuples, each containing 2 items; thus, 9 * 2 = 18. numpy automatically converts the tuples to part of the array.
You can either use LeonardoVaz's answer or do it speedily with nested list comprehension:
reshaped_grid = [[grid[i+j] for j in range(3)] for i in range(0, len(grid), 3)]
Output:
>>> reshaped_grid
[
[(1, 1), (1, 2), (1, 3)],
[(2, 1), (2, 2), (2, 3)],
[(3, 1), (3, 2), (3, 3)]
]
It's my understanding that the enumerate() function will loop over each item in an iterable. However, in the example below is does not loop at all when given a non-empty iterable.
import itertools
x = itertools.chain(
itertools.combinations([1, 2, 3], 1),
itertools.combinations([1, 2, 3], 2),
itertools.combinations([1, 2, 3], 3),
)
print(list(x))
print(list(enumerate(x)))
print(list(enumerate(list(x))))
print(list(enumerate([(1, ), (2, ), (3, ), (1, 2), (1, 3), (2, 3), (1, 2, 3)])))
Output:
[(1,), (2,), (3,), (1, 2), (1, 3), (2, 3), (1, 2, 3)]
[]
[]
[(0, (1,)), (1, (2,)), (2, (3,)), (3, (1, 2)), (4, (1, 3)), (5, (2, 3)), (6, (1, 2, 3))]
Expected output:
[(1,), (2,), (3,), (1, 2), (1, 3), (2, 3), (1, 2, 3)]
[(0, (1,)), (1, (2,)), (2, (3,)), (3, (1, 2)), (4, (1, 3)), (5, (2, 3)), (6, (1, 2, 3))]
[(0, (1,)), (1, (2,)), (2, (3,)), (3, (1, 2)), (4, (1, 3)), (5, (2, 3)), (6, (1, 2, 3))]
[(0, (1,)), (1, (2,)), (2, (3,)), (3, (1, 2)), (4, (1, 3)), (5, (2, 3)), (6, (1, 2, 3))]
I'm running this with Python 3.8.2 on Arch Linux.
Can someone explain why enumerate() does not loop with these inputs?
You exhausted your chained iterator with the first print statement. The second and third did receive an empty iterator. If you want to see your expected output, you need to rebuild the chain for each run-through.
This is not specific to chain, nor to enumerate; you can get the same effect with
x = iter(range(10))
I want to find possible paths on a finite grid of points. Say, starting point is (x,y). Then next point (m,n) in the path is given by conditions
(m!=x) and (n!=y) ie. I exclude the row and column I was in previously.
n < y ie. I always hop DOWN.
m,n >= 0 ie. all the points are always in first quadrant
Stopping criteria is when a point lies on x axis.
Hence, generate all possible combinations of such 'paths' possible.
Following is what I've tried.
def lisy(x,y):
return [(i,j) for i in range(4,0,-1) for j in range(4,0,-1) if(i!=x and j<y)]
def recurse(x,y):
if (not lisy(x,y)):
return (x,y)
else:
return [(x,y), [recurse(i,j) for i,j in lisy(x,y)]]
OUTPUT:
In [89]: recurse(1,4)
Out[89]:
[(1, 4),
[[(4, 3),
[[(3, 2), [(4, 1), (2, 1), (1, 1)]],
(3, 1),
[(2, 2), [(4, 1), (3, 1), (1, 1)]],
(2, 1),
[(1, 2), [(4, 1), (3, 1), (2, 1)]],
(1, 1)]],
[(4, 2), [(3, 1), (2, 1), (1, 1)]],
(4, 1),
[(3, 3),
[[(4, 2), [(3, 1), (2, 1), (1, 1)]],
(4, 1),
[(2, 2), [(4, 1), (3, 1), (1, 1)]],
(2, 1),
[(1, 2), [(4, 1), (3, 1), (2, 1)]],
(1, 1)]],
[(3, 2), [(4, 1), (2, 1), (1, 1)]],
(3, 1),
[(2, 3),
[[(4, 2), [(3, 1), (2, 1), (1, 1)]],
(4, 1),
[(3, 2), [(4, 1), (2, 1), (1, 1)]],
(3, 1),
[(1, 2), [(4, 1), (3, 1), (2, 1)]],
(1, 1)]],
[(2, 2), [(4, 1), (3, 1), (1, 1)]],
(2, 1)]]
This gives me a nested lists of possible new points from each point.
Can anyone tell me how to process my list obtained from recurse(1,4)?
edit1:
Effectively I hop from a given starting point (in a 4x4 grid [finite]), satisfying the three conditions mentioned until stopping criteria is met, ie. m,n > 0
I clarify the requirements I am working under in the docstring of my generator gridpaths(). Note that I have the horizontal size of the grid as a global variable and the vertical size of the grid is irrelevant, the x-coordinates of path points can be up to but not exceed that global value, and x-coordinates of non-consecutive path points can be equal (though consecutive path points must have different x-coordinates). I changed the name of the routine but kept the arguments as you had them. This version of my code adds the requirement that the y-coordinate of the final point on the path must be 1, and it also is safer in accepting arguments.
This is a generator of lists, so my test code shows how large the generator is then prints all the lists.
def gridpaths(x, y):
"""Generate all paths starting at (x,y) [x and y must be positive
integers] where, if (m,n) is the next point in the path after
(x,y), then m and n are positive integers, m <= xsize [xsize is a
global variable], m != x, and n < y, and so on for all consecutive
path points. The final point in the path must have a y-coordinate
of 1. Paths are yielded in lexicographic order."""
def allgridpaths(x, y, pathsofar):
"""Generate all such paths continuing from pathssofar without
the y == 1 requirement for the final path point."""
newpath = pathsofar + [(x, y)]
yield newpath
for m in range(1, xsize+1):
if m != x:
for n in range(1, y):
for path in allgridpaths(m, n, newpath):
yield path
x, y = max(int(x), 1), max(int(y), 1) # force positive integers
for path in allgridpaths(x, y, []):
# Only yield paths that end at y == 1
if path[-1][1] == 1:
yield path
# global variable: horizontal size of grid
xsize = 4
print(sum(1 for p in gridpaths(1, 4)), 'paths total.')
for p in gridpaths(1, 4):
print(p)
The printout shows that the point (1,4) in a 4x4 grid yields 48 paths. In fact, gridpaths(x, y) will return (xsize - 1) * xsize ** (y - 2) paths, which can grow very quickly. That is why I programmed a generator of lists rather than a list of lists. Let me know if your requirements are different from what I suppose. The printout from that code above is:
48 paths total.
[(1, 4), (2, 1)]
[(1, 4), (2, 2), (1, 1)]
[(1, 4), (2, 2), (3, 1)]
[(1, 4), (2, 2), (4, 1)]
[(1, 4), (2, 3), (1, 1)]
[(1, 4), (2, 3), (1, 2), (2, 1)]
[(1, 4), (2, 3), (1, 2), (3, 1)]
[(1, 4), (2, 3), (1, 2), (4, 1)]
[(1, 4), (2, 3), (3, 1)]
[(1, 4), (2, 3), (3, 2), (1, 1)]
[(1, 4), (2, 3), (3, 2), (2, 1)]
[(1, 4), (2, 3), (3, 2), (4, 1)]
[(1, 4), (2, 3), (4, 1)]
[(1, 4), (2, 3), (4, 2), (1, 1)]
[(1, 4), (2, 3), (4, 2), (2, 1)]
[(1, 4), (2, 3), (4, 2), (3, 1)]
[(1, 4), (3, 1)]
[(1, 4), (3, 2), (1, 1)]
[(1, 4), (3, 2), (2, 1)]
[(1, 4), (3, 2), (4, 1)]
[(1, 4), (3, 3), (1, 1)]
[(1, 4), (3, 3), (1, 2), (2, 1)]
[(1, 4), (3, 3), (1, 2), (3, 1)]
[(1, 4), (3, 3), (1, 2), (4, 1)]
[(1, 4), (3, 3), (2, 1)]
[(1, 4), (3, 3), (2, 2), (1, 1)]
[(1, 4), (3, 3), (2, 2), (3, 1)]
[(1, 4), (3, 3), (2, 2), (4, 1)]
[(1, 4), (3, 3), (4, 1)]
[(1, 4), (3, 3), (4, 2), (1, 1)]
[(1, 4), (3, 3), (4, 2), (2, 1)]
[(1, 4), (3, 3), (4, 2), (3, 1)]
[(1, 4), (4, 1)]
[(1, 4), (4, 2), (1, 1)]
[(1, 4), (4, 2), (2, 1)]
[(1, 4), (4, 2), (3, 1)]
[(1, 4), (4, 3), (1, 1)]
[(1, 4), (4, 3), (1, 2), (2, 1)]
[(1, 4), (4, 3), (1, 2), (3, 1)]
[(1, 4), (4, 3), (1, 2), (4, 1)]
[(1, 4), (4, 3), (2, 1)]
[(1, 4), (4, 3), (2, 2), (1, 1)]
[(1, 4), (4, 3), (2, 2), (3, 1)]
[(1, 4), (4, 3), (2, 2), (4, 1)]
[(1, 4), (4, 3), (3, 1)]
[(1, 4), (4, 3), (3, 2), (1, 1)]
[(1, 4), (4, 3), (3, 2), (2, 1)]
[(1, 4), (4, 3), (3, 2), (4, 1)]