Finding a sequence of numbers in a multi dimensional list - search

How do I find if a sequence of numbers exists in a two-dimensional list? i.e.
matrix: [[1, 1, 1, 0, 0, 0], [0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0], [0,
0, 0, 1, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0]]
if [1,1,1] in matrix:
print("It's in there")
else: print("It's not there")
I guess I could turn every int into a string but is there a slicker way?

Using an iterator over each cell of the matrix, I've managed to get a basic idea of what you wanted to achieve in Python script.
matrix = [[1, 1, 1, 0, 0, 0], [0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0]]
matchCount = 0
lastNumber = None
for cell in matrix:
for number in cell:
if number == 1 and lastNumber == 1 or lastNumber == None:
matchCount += 1
if matchCount >= 3:
print("MATCH in cell " + str(cell))
lastNumber = number
matchCount = 0
lastNumber = None
What happens is, it steps into the cell. It it's the first iteration then allow entry into our iterator. We don't know if it's a match list yet, so push it back in our little list.
Stepping over and over, if we get enough matches in a row, then wonderful! Print we found a match in our matrix's cell!

Related

How to make a checkerboard in Pytorch?

I see that a simple checkerboard pattern can be created fairly concisely with numpy Does anyone know if a checkerboard where each square may contain multiple values could be created? E.g.:
1 1 0 0 1 1
1 1 0 0 1 1
0 0 1 1 0 0
0 0 1 1 0 0
Although there is no equivalent of np.indices in PyTorch, you can still find a workaround using a combination of torch.arange, torch.meshgrid, and torch.stack:
def indices(h,w):
return torch.stack(torch.meshgrid(torch.arange(h), torch.arange(w)))
This allows you to define a base tensor with a checkboard pattern following your linked post:
>>> base = indices(2,3).sum(axis=0) % 2
tensor([[0, 1, 0],
[1, 0, 1]])
Then you can repeat the row end columns with torch.repeat_interleave:
>>> base.repeat_interleave(2, dim=0).repeat_interleave(2, dim=1)
tensor([[0, 0, 1, 1, 0, 0],
[0, 0, 1, 1, 0, 0],
[1, 1, 0, 0, 1, 1],
[1, 1, 0, 0, 1, 1]])
And you can take the opposite of a given checkboard x by computing 1-x.
So you could define a function like this:
def checkerboard(shape, k):
"""
shape: dimensions of output tensor
k: edge size of square
"""
h, w = shape
base = indices(h//k, w//k).sum(dim=0) % 2
x = base.repeat_interleave(k, 0).repeat_interleave(k, 1)
return 1-x
And try with:
>>> checkerboard((4,6), 2)
tensor([[1, 1, 0, 0, 1, 1],
[1, 1, 0, 0, 1, 1],
[0, 0, 1, 1, 0, 0],
[0, 0, 1, 1, 0, 0]])

Hermitian Adjacency Matrix of Digraph

I am trying to find a pythonic way to calculate the Hermitian adjacency matrix in Python and I'm really struggling. The definition of a Hermitian Adjacency matrix is shown in this image:
It works as follows. Lets say we have two nodes named i and j. If there is an directed edge going from both i to j and j to i, then the corresponding matrix value at location [ i, j ] should be set to 1. If there is only a directed edge from i to j, then the matrix element at location [i, j] should be set to +i. And if there is only a directed edge from j to i then the matrix element at location [i, j] should be set to -i. All other matrix values are set to 0.
I cannot figure out a smart way to make this Hermitian Adjacency Matrix that doesn't involve iterating through my nodes one by one. Any advice?
I don't think there's a built-in for this, so I've cobbled together my own vectorised solution:
import numpy as np
import networkx as nx
# Create standard adjacency matrix
A = nx.linalg.graphmatrix.adjacency_matrix(G).toarray()
# Add to its transpose and convert from sparse array
B = A + A.T
# Get row index matrix
I = np.indices(B.shape)[0] + 1
# Apply vectorised formula to get Hermitian adjacency matrix
H = np.multiply(B/2 * (2*I)**(B%2), 2*A-1).astype(int)
Explanation
Let's start with a directed graph:
We start by creating the normal adjacency matrix using nx.linalg.graphmatrix.adjacency_matrix(), giving us the following matrix:
>>> A = nx.linalg.graphmatrix.adjacency_matrix(G).toarray()
[[1, 1, 0, 1, 0, 1, 0, 0],
[1, 0, 0, 1, 0, 0, 1, 0],
[1, 1, 1, 1, 0, 1, 0, 0],
[0, 1, 0, 0, 0, 0, 0, 0],
[1, 0, 0, 1, 0, 0, 0, 0],
[1, 1, 0, 0, 1, 0, 1, 1],
[0, 1, 0, 0, 1, 0, 0, 1],
[0, 0, 0, 0, 1, 0, 0, 0]]
We can then add this matrix to its transpose, giving us 2 in every location where there is a directed edge going from i to j and vice-versa, a 1 in every location where only one of these edges exists, and a 0 in every location where no edge exists:
>>> B = A + A.T
>>> B
[[2, 2, 1, 1, 1, 2, 0, 0],
[2, 0, 1, 2, 0, 1, 2, 0],
[1, 1, 2, 1, 0, 1, 0, 0],
[1, 2, 1, 0, 1, 0, 0, 0],
[1, 0, 0, 1, 0, 1, 1, 1],
[2, 1, 1, 0, 1, 0, 1, 1],
[0, 2, 0, 0, 1, 1, 0, 1],
[0, 0, 0, 0, 1, 1, 1, 0]]
Now, we want to apply a function to the matrix so that 0 maps to 0, 2 maps to 1, and 1 maps to the row number i. We can use np.indices() to get the row number, and the following equation: x/2 * (2*i)**(x%2), where i is the row number and x is the element. Finally, we need to multiply elements in positions where no edge ij exists by -1. This can be vectorised as follows:
>>> I = np.indices(B.shape)[0] + 1
>>> H = np.multiply(B/2 * (2*I)**(B%2), 2*A-1).astype(int)
>>> H
[[ 1, 1, -1, 1, -1, 1, 0, 0],
[ 1, 0, -2, 1, 0, -2, 1, 0],
[ 3, 3, 1, 3, 0, 3, 0, 0],
[-4, 1, -4, 0, -4, 0, 0, 0],
[ 5, 0, 0, 5, 0, -5, -5, -5],
[ 1, 6, -6, 0, 6, 0, 6, 6],
[ 0, 1, 0, 0, 7, -7, 0, 7],
[ 0, 0, 0, 0, 8, -8, -8, 0]]
As required.
We can check that this is correct by using a naïve iterate-through-nodes approach:
>>> check = np.zeros([8,8])
>>> for i in G.nodes:
for j in G.nodes:
if (i, j) in G.edges:
if (j, i) in G.edges:
check[i-1, j-1] = 1
else:
check[i-1, j-1] = i
else:
if (j, i) in G.edges:
check[i-1, j-1] = -i
else:
check[i-1, j-1] = 0
>>> (check == H).all()
True

How to change only the diagonal elements of a 2D list?

So I am trying to create an NxN 2D array and then change its diagonal elemets to 1. Here is my code:
arr=[1,1,1,2,2,2]
table=[[0]*len(arr)]*len(arr)
for i in range(0,len(arr)):
table[i][i]=1
print(table)
However, whenever I run this code, I get this output:
[[1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1]]
I am looking to get this:
[[1, 0, 0, 0, 0, 0],
[0, 1, 0, 0, 0, 0],
[0, 0, 1, 0, 0, 0],
[0, 0, 0, 1, 0, 0],
[0, 0, 0, 0, 1, 0],
[0, 0, 0, 0, 0, 1]]
I have been staring at my code for hours and I cannot figure out what's wrong
The interesting thing about this is that you are really only editing one list in the for loop, but there are just five pointers to that list. (In this case, the list would be [0, 0, 0, 0, 0, 0].) You can see this by printing the id of each list in table by using id():
>>> for t in table:
print(id(t))
2236544254464
2236544254464
2236544254464
2236544254464
2236544254464
2236544254464
Your numbers are likely different than mine, but they are all the same number, nevertheless. You also can see that the edits to one list are applied to the others in table by putting a print(table) statement after each index assignment statement.
So in order to 'fix' this, I would recommend using list comprehension instead. For example:
table = [[0]*len(arr) for _ in range(len(arr))]
If you checkout the ids of each list:
>>> for t in table:
print(id(t))
2236544617664
2236544616064
2236544616320
2236544615872
2236544618368
2236544622720
Since they are different, you can now use the method for changing only the diagonals:
>>> for i in range(0,len(arr)):
table[i][i]=1
>>> table
[[1, 0, 0, 0, 0, 0],
[0, 1, 0, 0, 0, 0],
[0, 0, 1, 0, 0, 0],
[0, 0, 0, 1, 0, 0],
[0, 0, 0, 0, 1, 0],
[0, 0, 0, 0, 0, 1]]
Your 2D "array" contains 6 lists which are the same list. Changes to any of those lists will also be reflected in the other lists. Consider this:
>>> l = [0] * 6
>>> x = [l]
>>> l[0] = 1
>>> l
[1, 0, 0, 0, 0, 0]
>>> x
[[1, 0, 0, 0, 0, 0]]
>>> x = [l, l, l]
>>> x
[[1, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0]]
>>> x[-1][-1] = 100
>>> x
[[1, 0, 0, 0, 0, 100], [1, 0, 0, 0, 0, 100], [1, 0, 0, 0, 0, 100]]
This is because the list x contains the list l, so any changes to l are also seen through the reference to the same list in x.
The problem is when multiplying mutable objects because it creates multiple references to the same mutable object.
You should initialise your table like this:
table = [[0 for j in range(len(arr))] for i in range(len(arr))]
or
table = [[0] * len(arr) for i in range(len(arr))]
which, despite the use of multiplication, works because each list is different.
You can create your table and populate it simultaneously in nested loops:
arr=[1,1,1,2,2,2]
table = []
for i in range(len(arr)):
table.append([0]*len(arr))
for j in range(len(arr)):
if i == j:
table[i][j] = 1
print(table)
#[[1, 0, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0], [0, 0, 0, 1, 0, 0], [0, 0, 0, 0, 1, 0], [0, 0, 0, 0, 0, 1]]
Interesting.
Try to use numpy to avoid list trap:
import numpy as np
org_row = [0]*5
l = [org_row]*5
x = np.array(l, np.int32)
for i in range(len(x)):
x[i][i]=1
print(x)
output>:
output>
[[1 0 0 0 0]
[0 1 0 0 0]
[0 0 1 0 0]
[0 0 0 1 0]
[0 0 0 0 1]]

Why does recursion not continue?

I have two list. first list is a maze. It start 'O' and must be finished 'X'.
maze_list=[[0, 1, 1, 0, 0, 0],
[0, 0, 1, 0, 1, 'O'],
[0, 0, 1, 0, 1, 0],
[0, 1, 1, 1, 1, 0],
['X', 1, 0, 1, 0, 0],
[0, 1, 0, 1, 1, 1]]
path_list=[[0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0]]
This part is finding start position.
column_size=len(maze_list)
row_size=len(maze_list[0])
def find_SF_position(X):
liste=[]
for i in range(column_size):
for j in range(column_size):
if maze_list[i][j]==X:
liste.append(i)
liste.append(j)
return liste
s_p=find_SF_position('O') #[1,5]
f_p=find_SF_position('X') #[4,0]
This part is main algorithm. x is for horizontal position. y is for vertical position
def solve_maze(maze,road,x,y):
global column_size
global row_size
road[y][x]=1
print(y,x)
#left
if x>0 and maze[y][x-1]==1 and road[y][x-1]==0:
return solve_maze(maze,road,x-1,y)
#up
if y>0 and maze[y-1][x]==1 and road[y][x-1]==0:
return solve_maze(maze,road,x,y-1)
#right
if x>row_size and maze[y][x+1]==1 and road[y][x-1]==0:
return solve_maze(maze,road,x+1,y)
#down
if y>column_size and maze[y+1][x]==1 and road[y][x-1]==0:
return solve_maze(maze,road,x,y+1)
if maze[x][y]=='X':
return path_list
solve_maze(maze_list,path_list,s_p[1],s_p[0])
print(path_list)
I can't understand why it isn't working. It's start 'O'(maze_list[1,5]), it fill maze_list[1,4] then stop.
Finally path_list must be like this
path_list=[[0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 1, 1],
[0, 0, 0, 0, 1, 0],
[0, 1, 1, 1, 1, 0],
[1, 1, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0]]
You have a few problems in your code:
First your right and down conditions are reversed: x can never be greater than row_size. What you want to check is that x is not on the right border, meaning: x < row_size - 1. Same logic goes for the down case
Seems like you have a little copy-paste issue there: for example the road condition for up should be: road[y-1][x]==0. Same logic goes to all other cases.
Your condition to finding the end has a problematic logic: You check if the current cell is the 'X', but each step is only taken if there is 1 in the next cell, so how will you get to the 'X'? For example, after fixing above errors, the output I got was:
[0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 1, 1]
[0, 0, 0, 0, 1, 0]
[0, 1, 1, 1, 1, 0]
[0, 1, 0, 0, 0, 0]
[0, 1, 0, 0, 0, 0]
As you can see, the 'X' was missed as the condition for down was taken at (4, 1) and a dead-end was reached
Lastly, what happens if you reach a dead-end? Your algorithm always takes the first step with conditions met, but what happens when you encounter an intersection? You need to check all possible paths. That's the point of recursion. The way you did it now doesn't add much over a loop.

How to rotate the results in a board made of lists?

I'm trying to learn how to code with Python and I have tried this exercise in which I have to rotate this board by 90° degrees but I dont get how. Thanks for the help.
numlist = [1,3,0,2]
board = [[0, 0, 0, 0],
[1, 0, 0, 0],
[0, 0, 0, 2],
[0, 3, 0, 0]]
I use this to print a table when it is given a numlist:
def ctcb(numlist): # Create The Chess Board
n = 0
board = []
the_len = len(numlist)
for i in range(the_len): # create a list with nested lists
board.append([])
for n in range(the_len):
board[i].append(0) # fills nested lists with data
while n < len(board):
for x,y in enumerate(numlist):
board[y][x] = y
n += 1
# print(board)
for e in board:
print(e)
the result should be this one:
board = [[0, 0, 2, 0],
[0, 0, 0, 0],
[0, 0, 0, 3],
[0, 1, 0, 0]]
We can use zip(*board) to transpose the board, and then use reversed to get the reverse of that transpose.
board = [[0, 0, 0, 0],
[1, 0, 0, 0],
[0, 0, 0, 2],
[0, 3, 0, 0]]
print([list(x) for x in reversed(list(zip(*board)))])
# [[0, 0, 2, 0], [0, 0, 0, 0], [0, 0, 0, 3], [0, 1, 0, 0]]

Resources