Two dimensional matrix using for loop in Python - python

I want to make the following matrix using loops:
matrix = [[x - 3 , y - 3], [ x - 2 , y - 3], [x - 1, y - 3], [ x , y - 3],
[x - 3, y - 2], [x - 2, y - 2], [x - 1, y - 2], [x, y - 2],
[x - 3, y - 1], [x - 2, y - 1], [x - 1, y - 1], [x, y - 1],
[x - 3, y], [x - 2, y ], [x - 1, y ], [x, y],
[x - 3, y + 1], [x - 2, y + 1], [x - 1, y + 1], [x, y + 1],
[x - 3, y + 2], [x - 2, y + 2], [x - 1, y + 2], [x, y + 2],
[x - 3, y + 3], [x - 2, y + 3], [x - 1, y + 3], [x, y + 3]]
such that when if I want to increase constant from 3 to 5 or any number it automatically creates this matrix accordingly. It is 7x4 matrix. Any suggestions ? Thanks

Here's an approach with np.meshgrid -
r,c = np.ogrid[x-3:x+1, y-3:y+4]
out = np.dstack(np.meshgrid(r,c))
Sample input, output -
In [114]: x,y = 0,0
In [115]: out.tolist() # Showing as list
Out[115]:
[[[-3, -3], [-2, -3], [-1, -3], [0, -3]],
[[-3, -2], [-2, -2], [-1, -2], [0, -2]],
[[-3, -1], [-2, -1], [-1, -1], [0, -1]],
[[-3, 0], [-2, 0], [-1, 0], [0, 0]],
[[-3, 1], [-2, 1], [-1, 1], [0, 1]],
[[-3, 2], [-2, 2], [-1, 2], [0, 2]],
[[-3, 3], [-2, 3], [-1, 3], [0, 3]]]
You can also use np.mgrid that would produce X's and Y's swapped -
np.dstack(np.mgrid[y-3:y+4, x-3:x+1])

Here is another way to do it:
>>> def compute(x,y):
... return [[x+j, y+i] for i in range(-3,4) for j in range(-3,1)]
...
>>> print compute(0,0)
[[-3, -3], [-2, -3], [-1, -3], [0, -3], [-3, -2], [-2, -2], [-1, -2], [0, -2], [-3, -1], [-2, -1], [-1, -1], [0, -1], [-3, 0], [-2, 0], [-1, 0], [0, 0], [-3, 1], [-2, 1], [-1, 1], [0, 1], [-3, 2], [-2, 2], [-1, 2], [0, 2], [-3, 3], [-2, 3], [-1, 3], [0, 3]]

Related

How to create all possible integer binning combinations given a budget in Python?

I have a budget N, which I would like to split into K bins, with the restriction being that each bin can only contain integers and the sum of each bin must equal to the budget. As such, I want to have (N+K-1)C(K-1) possible combinations, using nCr notation.
For example, for N = 5, K = 3, I have the following code:
def generateStrategies():
s = 5
strats = []
for x1 in range(s + 1):
current_strat = []
for x2 in range((s + 1) - x1):
for x3 in range((s + 1) - (x1 + x2)):
if (x1 + x2 + x3) == s:
current_strat = [x1,x2,x3]
strats.append(current_strat)
return strats
which returns
[[0, 0, 5],
[0, 1, 4],
[0, 2, 3],
[0, 3, 2],
[0, 4, 1],
[0, 5, 0],
[1, 0, 4],
[1, 1, 3],
[1, 2, 2],
[1, 3, 1],
[1, 4, 0],
[2, 0, 3],
[2, 1, 2],
[2, 2, 1],
[2, 3, 0],
[3, 0, 2],
[3, 1, 1],
[3, 2, 0],
[4, 0, 1],
[4, 1, 0],
[5, 0, 0]]
Is there an inbuilt function that does this for any N and K? I feel like there probably is, but so far I can't find it.
It isn't builtin, but I think this is what you are asking for:
def budgetSplit(n,k,sofar=[]):
if k==1:
yield sofar + [n]
else:
for n2 in range(0,n+1):
for b in budgetSplit(n-n2,k-1,sofar+[n2]):
yield b
print(list(budgetSplit(5,4)))

Using _scatter() to replace values in matrix

Given the following two tensors:
x = torch.tensor([[[1, 2],
[2, 0],
[0, 0]],
[[2, 2],
[2, 0],
[3, 3]]]) # [batch_size x sequence_length x subseq_length]
y = torch.tensor([[2, 1, 0],
[2, 1, 2]]) # [batch_size x sequence_length]
I would like to sort the sequences in x based on their sub-sequence lengths (0 corresponds to padding in the sequence). y corresponds to the lengths of the sub-sequences in x. I have tried the following:
y_sorted, y_sort_idx = y.sort(dim=1, descending=True)
print(x.scatter_(dim=1, index=y_sort_idx.unsqueeze(2), src=x))
This results in:
tensor([[[1, 2],
[2, 0],
[0, 0]],
[[2, 2],
[2, 0],
[2, 3]]])
However what I would like to achieve is:
tensor([[[1, 2],
[2, 0],
[0, 0]],
[[2, 2],
[3, 3],
[2, 0]]])
This should do it
y_sorted, y_sort_idx = y.sort(dim=1, descending=True)
index = y_sort_idx.unsqueeze(2).expand_as(x)
x = x.gather(dim=1, index=index)

Why is this function being applied to a variable which is not called as a parameter?

I am having trouble with some code I am attempting to write.
I am attempting to take a list of lists of coordinates (representing possible positions of a shape in 3D) and form a list which consists of all the elements in the original list and additionally the elements in the original list rotated so that the [x, y, z] coordinates are shifted to include [z, x, y] and [y, z, x] also.
I think this is better illustrated with an example:
Taking the list (representing the possible positions of a 2x2x1 block, hence "two_by_two"):
two_by_two = [
[[-1, -1, 1], [-1, -1, 0], [-1, 0, 0], [-1, 0, 1]],
[[-1, -1, 0], [-1, -1, -1], [-1, 0, -1], [-1, 0, 0]]
...
]
(the ellipses representing more similar lists of coordinates) I am attempting to form the complete list:
two_by_two_comp = [
[[-1, -1, 1], [-1, -1, 0], [-1, 0, 0], [-1, 0, 1]],
[[-1, -1, 0], [-1, -1, -1], [-1, 0, -1], [-1, 0, 0]]
...
[[1, -1, -1], [0, -1, -1], [0, -1, 0], [1, -1, 0]],
[[0, -1, -1], [-1, -1, -1], [-1, -1, 0], [0, -1, 0]]
...
[[-1, 1, -1], [-1, 0, -1], [0, 0, -1], [0, 1, -1]],
[[-1, 0, -1], [-1, -1, -1], [0, -1, -1], [0, 0, -1]]
...
]
I hope that this is clear.
I am attempting to achieve this by using a function which shifts all of the coordinates in two_by_two:
# function to change [x, y, z] to [z, x, y]
def rotate_coordinates(parameter):
coord_list = parameter[len(parameter) - 1]
coordinates = coord_list[len(coord_list) - 1]
z_coordinate = coordinates[2]
coordinates.pop()
coordinates.insert(0, z_coordinate)
# function to change list[x, y, z] to list[z, x, y]
def rotate_coord_list(parameter):
coord_list = parameter[len(parameter) - 1]
a = len(coord_list)
while a > 0:
coordinates = coord_list[len(coord_list) - 1]
rotate_coordinates(parameter)
coord_list.pop()
coord_list.insert(0, coordinates)
a = a - 1
# function to change list[list[x, y, z]] to list[list[z, x, y]]
def rotate_positions_list(parameter):
b = len(parameter)
while b > 0:
coord_list = parameter[len(parameter) - 1]
rotate_coord_list(parameter)
parameter.pop()
parameter.insert(0, coord_list)
b = b - 1
This seems to me to be successful in that when I run:
print(two_by_two)
rotate_positions_list(two_by_two)
print(two_by_two)
It outputs:
[[[-1, -1, 1], [-1, -1, 0], [-1, 0, 0], [-1, 0, 1]],
[[-1, -1, 0], [-1, -1, -1], [-1, 0, -1], [-1, 0, 0]]
...]
[[[1, -1, -1], [0, -1, -1], [0, -1, 0], [1, -1, 0]],
[[0, -1, -1], [-1, -1, -1], [-1, -1, 0], [0, -1, 0]]
...]
And so it shifts all of the coordinates as I intended, the issue arises when I try to begin creating two_by_two_comp as so:
two_by_two_comp = []
two_by_two_comp.extend(two_by_two)
print(two_by_two_comp)
rotate_positions_list(two_by_two)
two_by_two_comp.extend(two_by_two)
print(two_by_two_comp)
Which returns:
[[[-1, -1, 1], [-1, -1, 0], [-1, 0, 0], [-1, 0, 1]],
[[-1, -1, 0], [-1, -1, -1], [-1, 0, -1], [-1, 0, 0]]
...]
[[[1, -1, -1], [0, -1, -1], [0, -1, 0], [1, -1, 0]],
[[0, -1, -1], [-1, -1, -1], [-1, -1, 0], [0, -1, 0]],
...
[[1, -1, -1], [0, -1, -1], [0, -1, 0], [1, -1, 0]],
[[0, -1, -1], [-1, -1, -1], [-1, -1, 0], [0, -1, 0]]
...]
So I end up with the same "version" of two_by_two copied as opposed to the shifted and original version, and I have no idea why the section of two_by_two_comp which I print out first gets affected by the rotate_positons_list(two_by_two) function.
If anyone could clear up my confusion, I would be very grateful. I will include the full script in one piece below.
Thank you,
Dan
two_by_two = [
[[-1, -1, 1], [-1, -1, 0], [-1, 0, 0], [-1, 0, 1]],
[[-1, -1, 0], [-1, -1, -1], [-1, 0, -1], [-1, 0, 0]],
[[-1, 0, 0], [-1, 0, -1], [-1, 1, -1], [-1, 1, 0]],
[[-1, 0, 1], [-1, 0, 0], [-1, 1, 0], [-1, 1, 1]],
[[0, -1, 1], [0, -1, 0], [0, 0, 0], [0, 0, 1]],
[[0, -1, 0], [0, -1, -1], [0, 0, -1], [0, 0, 0]],
[[0, 0, 0], [0, 0, -1], [0, 1, -1], [0, 1, 0]],
[[0, 0, 1], [0, 0, 0], [0, 1, 0], [0, 1, 1]],
[[1, -1, 1], [1, -1, 0], [1, 0, 0], [1, 0, 1]],
[[1, -1, 0], [1, -1, -1], [1, 0, -1], [1, 0, 0]],
[[1, 0, 0], [1, 0, -1], [1, 1, -1], [1, 1, 0]],
[[1, 0, 1], [1, 0, 0], [1, 1, 0], [1, 1, 1]],
]
# function to change [x, y, z] to [z, x, y]
def rotate_coordinates(parameter):
coord_list = parameter[len(parameter) - 1]
coordinates = coord_list[len(coord_list) - 1]
z_coordinate = coordinates[2]
coordinates.pop()
coordinates.insert(0, z_coordinate)
# function to change list[x, y, z] to list[z, x, y]
def rotate_coord_list(parameter):
coord_list = parameter[len(parameter) - 1]
a = len(coord_list)
while a > 0:
coordinates = coord_list[len(coord_list) - 1]
rotate_coordinates(parameter)
coord_list.pop()
coord_list.insert(0, coordinates)
a = a - 1
# function to change list[list[x, y, z]] to list[list[z, x, y]]
def rotate_positions_list(parameter):
b = len(parameter)
while b > 0:
coord_list = parameter[len(parameter) - 1]
rotate_coord_list(parameter)
parameter.pop()
parameter.insert(0, coord_list)
b = b - 1
two_by_two_comp = []
two_by_two_comp.extend(two_by_two)
print(two_by_two_comp)
rotate_positions_list(two_by_two)
two_by_two_comp.extend(two_by_two)
print(two_by_two_comp)
Your problem lies in the difference between deep copy and shallow copy. As per the docs
Assignment statements in Python do not copy objects, they create bindings between a target and an object. For collections that are mutable or contain mutable items, a copy is sometimes needed so one can change one copy without changing the other.
The problematic line is thus:
two_by_two_comp.extend(two_by_two)
Let me illustrate with an example using two lists a and b:
a = [[2, 3, 4], [1, 2, 3]]
b = []
b.extend(a)
Now let's say I modify something inside a:
a[0].append(3)
print(a) # [[2, 3, 4, 3], [1, 2, 3]]
Everything is fine, but have a look at what happened to b in the meantime:
print(b) # [[2, 3, 4, 3], [1, 2, 3]]
It was also modified.
To achieve what you want, you need to create a deep copy of two_by_two otherwise you will just be referencing the same memory address. Long story short, instead of:
two_by_two_comp.extend(two_by_two)
You must do:
two_by_two_comp.extend(copy.deepcopy(two_by_two))
Don't forget to import the copy module at the top of your script:
import copy

How to remove duplicates in nested lists?

I want to remove both duplicates and permutations from my nested list.
Input:
[[-1, 0, 1], [-1, 1, 0], [-1, 2, -1], [-1, 2, -1], [-1, -1, 2]]
Expected Output:
[[-1, 0, 1], [-1, 2, -1]]
I tried using a list comprehension but I end up with the output as
[[-1, 1, 0], [-1, 2, -1], [-1, 0, 1], [-1, -1, 2]]
Here is what I attempted.
a = [[-1, 0, 1], [-1, 1, 0], [-1, 2, -1], [-1, 2, -1], [-1, -1, 2]]
b_set = set(tuple(x) for x in a)
b = [ list(x) for x in b_set ]
print(b)
The result is expected because [-1, 0, 1] != [-1, 1, 0]. You can sort the inner tuples if you want to make sure that they are considered equal:
b_set = set(tuple(sorted(x)) for x in a)
Or with map:
b_set = set(map(lambda x: tuple(sorted(x)),a))

Using function with entries from two 3D arrays (Python)

So let's say I have two arrays (numpy arrays that is):
array1 =
[[[1, 0, 0], [0, 6, 0], [3, 0, 0]],
[[0, 2, 4], [0, 4, 0], [0, 4, 0]],
[[0, 0, 2], [1, 3, 2], [3, 4, 0]]]
and
array2 =
[[[2, 4, 0], [0, 4, 0], [3, 0, 0]],
[[0, 0, 3], [1, 4, 3], [2, 4, 3]],
[[0, 0, 1], [0, 2, 1], [1, 0, 2]]]
I then make a function like:
def array_calc(x,y,z):
x*y+z
What I would like to do now is have the x-values come from array1 and y-values from array2, and z-values just a constant I choose (let's say z = 0), and then do the calculation on each entry of the arrays, and ultimately end up with a new array, where the calculation has been done, and I get something like:
array_result =
[[[2, 0, 0], [0, 24, 0], [9, 0, 0]],
[[0, 0, 12], [0, 16, 0], [0, 16, 0]],
[[0, 0, 2], [0, 6, 2], [3, 0, 0]]]
But, I'm not quite sure how that is done.
If your arrays are numpy arrays, it is as simple as:
import numpy as np
x = np.array([[1,0],[0,1]])
y = np.array([[4,1],[0,2]])
z = 1
result = x*y + z
# result = array([[5, 1], [1, 3]])
Using simple for loops:
import numpy as np
def array_calc(x, y, z):
"""Returns x * y + z with x and y 3D Numpy arrays and z a number"""
new_arr = x.copy()
for i in np.arange(x.shape[0]):
for k in np.arange(x.shape[1]):
for j in np.arange(x.shape[2]):
new_arr[i, k, j] = x[i, k, j] * y[i, k, j] + z
return new_arr
With:
array1 = np.array([[[1, 0, 0], [0, 6, 0], [3, 0, 0]],
[[0, 2, 4], [0, 4, 0], [0, 4, 0]],
[[0, 0, 2], [1, 3, 2], [3, 4, 0]]])
array2 = np.array([[[2, 4, 0], [0, 4, 0], [3, 0, 0]],
[[0, 0, 3], [1, 4, 3], [2, 4, 3]],
[[0, 0, 1], [0, 2, 1], [1, 0, 2]]])
Returns:
array([[[ 3, 1, 1],
[ 1, 25, 1],
[10, 1, 1]],
[[ 1, 1, 13],
[ 1, 17, 1],
[ 1, 17, 1]],
[[ 1, 1, 3],
[ 1, 7, 3],
[ 4, 1, 1]]])
A way I can think of is to iterate through them and perform your calculations.
This can be done with 3 dimensional arrays too but I just found it easier to do it with 2 dimensional arrays. I am sure there are other ways to reduce the complexity further down because 3 for loops is not the best solution but it gets the work done.
The code is here:
array1 = [[[1, 0, 0], [0, 6, 0], [3, 0, 0]],[[0, 2, 4], [0, 4, 0], [0, 4, 0]],[[0, 0, 2], [1, 3, 2], [3, 4, 0]]]
array2 = [[[2, 4, 0], [0, 4, 0], [3, 0, 0]], [[0, 0, 3], [1, 4, 3], [2, 4, 3]], [[0, 0, 1], [0, 2, 1], [1, 0, 2]]]
z=0
array_1 = reduce(list.__add__, array1)
array_2 = reduce(list.__add__, array2)
array_3 = [[0,0,0] for _ in xrange(9)]
len_array=9
for i in range(len_array):
for l in range(3):
array_3[i][l] = array_1[i][l]*array_2[i][l]+z
print array_3

Categories

Resources