I am trying to write a function that takes the number or rows and columns in a grid, simulates a random walk starting in the center of the grid, and computes the number of times each intersection has been visited by the random walk. Then prints the table line by line once the random walk moves outside the grid
So far I have this but i cant get it to work right.
def manhattan(x,y):
'int,int==>nonetype'
import random
res=[]
for i in range(x):
res.append([])
for i in res:
for j in range(y):
i.append(0)
position=(x//2+1,y//2+1)
z=position[0]
v=position[1]
while z!=-1 or z!=x or v!=-1 or v!=y:
direction=random.randrange(1,5)
if direction==1:
v+=1
elif direction==2:
z+=1
elif direction==3:
v-=1
else:
z-=1
for i in range(len(res)):
if i ==z:
res[i]+=1
for j in range(i):
if v==j:
i[j]+=1
for i in res:
print(i)
It should read when done:
manhattan(5,11)
[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,1,1,1,1,2,2]
[0,0,0,0,0,0,0,0,0,0,0]
[0,0,0,0,0,0,0,0,0,0,0]
You were very close, try the following:
def manhattan(x,y):
'int,int==>nonetype'
import random
res=[]
for i in range(x):
res.append([])
for i in res:
for j in range(y):
i.append(0)
position=(x//2+1,y//2+1)
z=position[0]
v=position[1]
while z!=-1 and z!=x and v!=-1 and v!=y:
res[z][v] += 1
direction=random.randrange(1,5)
if direction==1:
v+=1
elif direction==2:
z+=1
elif direction==3:
v-=1
else:
z-=1
for i in res:
print(i)
Nothing is different until the while loop, and there are only a couple of changes. First you need to use and instead of or in the loop condition check since you want to exit if any of those conditions are met.
The other change was to remove the for loop from the bottom of the while loop and replace it by res[z][v] += 1, this works because z and v represent the intersection and you already initialized res to be a two-dimensional list of all the intersections so looping is unnecessary. I also moved this up to the top of the loop because otherwise you might try to modify res after moving past the boundary.
Here is a bit less verbose version that uses random.choice instead of your chained elif statements. I found it helpful when learning python to see the same problem in different ways, so here is a pure python and a numpy + python implementation.
Pure Python
import random
def manhattan(n,m):
grid = [[0,]*m for _ in xrange(n)]
directions = [[-1,0],[1,0],[0,-1],[0,1]]
pt = [n//2, m//2]
while pt[0]>=0 and pt[0]<n and pt[1]>=0 and pt[1]<m:
grid[pt[0]][pt[1]] += 1
d = random.choice(directions)
pt[0] += d[0]
pt[1] += d[1]
return grid
for row in manhattan(5,11):
print row
This gives, for example,
[0, 0, 0, 1, 3, 3, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 1, 3, 3, 2, 0, 0, 0]
[0, 0, 0, 0, 0, 1, 2, 2, 1, 0, 0]
[0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0]
Python + numpy
import numpy as np
import random
def manhattan(n,m):
grid = np.zeros((n,m),dtype=int)
directions = [[-1,0],[1,0],[0,-1],[0,1]]
pt = np.array([n//2, m//2])
while (pt>=0).all() and (pt<grid.shape).all():
grid[pt[0],pt[1]] += 1
pt += random.choice(directions)
return grid
print manhattan(5,11)
Related
I have a simple exam to pass where I have to write a program where I create a binary matrix and a pattern and I have to find the pattern inside the matrix and to highlight it if found. I can't use any external library - specially numpy.
What I have atm are just some highlighted numbers that don't match my pattern. I don't know how to continue. Can someone help me please?
My code is this:
pattern.py:
# to create a matrix from an array of arrays
def create(n, m, data):
matrix = []
for i in range(n): #n=rows number
row = []
for j in range(m): #m=columns number
if data[j] not in matrix:
row.append(data[m * i + j])
matrix.append(row)
return matrix
# to colour the elements in 1 inside the pattern
def colora(element):
if element == 1:
element = '\u001b[36m1'
elif element == 0:
element = '\u001b[00m0'
return element
# my pattern forms an I vertically - I should also find it if horizontal
def patternI():
array = [1, 0, 0, 1, 0, 0, 1, 0, 0]
pattern = create(3, 3, array)
for i in range(3):
for j in range(3):
col_element = colora(pattern[i][j])
print(col_element, end=" ")
# print(pattern[i][j], end=" ")
print()
return pattern
main.py:
import patterns
import ricerca
# to create and print the matrix
def matrix():
m = 5
n = 5
array = [0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0]
matrix = patterns.create(n, m, array)
for i in range(n):
for j in range(m):
print(matrix[i][j], end=" ")
print()
return matrix
def main():
print("pattern:")
pattern = patterns.patternI()
print("\r")
print("matrix:")
matrice = matrix()
print("\r")
print("risult:")
newArray=ricerca.ricerca(pattern, matrice)
main()
ricerca.py:
import patterns
# to search the pattern (m_piccola) inside the (m_grande)
def ricerca(m_piccola, m_grande) :
daricordare = [] #an array to fill with the position of the matrix which combines a little with the pattern
for jR in range(len(m_piccola) - 1) :
for iR in range(len(m_grande)) :
for iC in range(len(m_grande[0])) :
for jC in range(len(m_piccola[jR])) :
if m_piccola[jR][jC] == 0 :
jC += 1
break
if m_piccola[jR][jC] == 1 :
if m_grande[iR][iC] == m_piccola[jR][jC] :
daricordare.append((iR, iC))
else :
iC += 1
data = coloraQuelliDelPattern(daricordare, m_grande)
for i in range(5):
for j in range(5):
print(data[i][j], end = " ")
print()
return data
# to highlight the numbers in the array which are inside "daricordare"
def coloraQuelliDelPattern(daricordare, array) :
for i in range(len(daricordare) - 2) :
a = daricordare[i]
b = daricordare[i + 1]
c = daricordare[i + 2]
if b[1] == a[1] + 1 and c[1]==a[1] + 2:
array[a[0]][a[1]] = "\u001b[36m1"
array[b[0]][b[1]] = "\u001b[36m1"
array[c[0]][c[1]] = "\u001b[36m1"
if b[1] != a[1] + 1 or c[1] != a[1] + 2 :
array[a[0]][a[1]] = "\u001b[00m1"
array[b[0]][b[1]] = "\u001b[00m1"
array[c[0]][c[1]] = "\u001b[00m1"
return array
I need to find the longest path of 0's in a 2d matrix recursively and can't figure out how to do it.( from a given (i , j) it can only move up, down, right or left)
For example this matrix:
mat = [[1, 0, 0, 3, 0],
[0, 0, 2, 3, 0],
[2, 0, 0, 2, 0],
[0, 1, 2, 3, 3]]
print(question3_b(mat))
This should return 6 as there are communities of sizes 1,3,6.
My attempt: I created a few wrapper functions to find the maximum in a list, and a function to find the route at a given (i,j) element and add it to a list, and doing this on every point(i,j) in the matrix.
def question3_b(mat) -> int:
rows: int = len(mat)
cols: int = len(mat[0])
community_lengths = list()
for i in range(rows):
for j in range(cols):
visited = zeros(rows, cols) # create a 2d list of 0's with size rows,cols
a = findcommunity(mat, (i, j), visited)
print("a=", a)
community_lengths.append(a)
print(community_lengths)
return findmax(community_lengths)
def findcommunity(mat: list, indices: tuple, visited: list): # find length of community
#global rec_counter
#rec_counter += 1
i, j = indices
rows = len(mat)
cols = len(mat[0])
if mat[i][j] == 0:
visited[i][j] = 1
if i < rows - 1:
if visited[i + 1][j] == 0:
return 1 + findcommunity(mat, (i + 1, j), visited)
if j < cols - 1:
if visited[i][j + 1] == 0:
return 1 + findcommunity(mat, (i, j + 1), visited)
if i > 0:
if visited[i - 1][j] == 0:
return 1 + findcommunity(mat, (i - 1, j), visited)
if j > 0:
if visited[i][j - 1] == 0:
return 1 + findcommunity(mat, (i, j - 1), visited)
else: # mat[i][j]!=0
return 0
def zeros(rows:int,cols:int)->list: #create a 2d matrix of zeros with size (rows,cols)
if rows==1 and cols==1:return [[0]]
if rows==1 and cols>1:return [[0]*cols]
if rows>1 and cols>1:return zeros(rows-1,cols)+zeros(1,cols)
def findmax(arr:list)->int: # find max in an array using recursion
if len(arr)==2:
if arr[0]>arr[1]:return arr[0]
else:return arr[1]
else:
if arr[0]>arr[1]:
arr[1]=arr[0]
return findmax(arr[1:])
else:
return findmax(arr[1:])
Where did I go wrong? for a matrix of 4X4 zeros, I expect it to run 16*16 times[16 times for each i,j, and there are 16 elements in the matrix]. but it only runs once.
zeros is a recursive function I made that functions like np.zeros, it creates a 2d matrix full of 0's with specified size.
It got really messy but I tried to just change your code instead of writing a new solution. You should have a look at collections deque. Saw this several times where people keep track of visited a lot easier.
I changed visited to outside of the loop and defined it with np.zeros (didn't have your function ;) ). I'm not sure if your recursive function calls at return were wrong but your if-statements were, or at least the logic behind it (or I didn't understand, also possible :) )
I changed that block completly. The first time you come across a 0 in mat the recursive part will dig into the mat as long as it finds another 0 left,right,bottom or top of it (that's the functionality behind dc and dr). That's where the community_counter is increasing. If the function is returning the last time and you jump out to the outerloop in question_3b the counter gets resetted and searchs for the next 0 (next start of another community).
import numpy as np
def question3_b(mat) -> int:
rows: int = len(mat)
cols: int = len(mat[0])
community_lengths = list()
visited = np.zeros((rows, cols)) # create a 2d list of 0's with size rows,cols
community_count = 0
for row in range(rows):
for col in range(cols):
if visited[row][col]==0:
community_count,visited = findcommunity(mat, (row, col), visited, community_count)
if community_count!=0:
community_lengths.append(community_count)
community_count=0
return community_lengths
def findcommunity(mat: list, indices: tuple, visited: list,community_count: int): # find length of community
i, j = indices
rows = len(mat)
cols = len(mat[0])
visited[i][j] = 1
if mat[i][j] == 0:
community_count += 1
dr = [-1, 0, 1, 0]
dc = [0,-1, 0, 1]
for k in range(4):
rr = i + dr[k]
cc = j + dc[k]
if 0<=rr<rows and 0<=cc<cols:
if visited[rr][cc]==0 and mat[rr][cc]==0:
community_count, visited = findcommunity(mat, (rr,cc), visited, community_count)
return community_count,visited
else:
return community_count,visited
mat = [[1, 0, 0, 3, 0],
[0, 0, 2, 3, 0],
[2, 0, 0, 2, 0],
[0, 1, 2, 3, 3]]
all_communities = question3_b(mat)
print(all_communities)
# [6, 3, 1]
print(max(all_communities))
# 6
EDIT
Here is the findcommunity function in your way. Tested it and it works aswell.
def findcommunity(mat: list, indices: tuple, visited: list,community_count: int): # find length of community
i, j = indices
rows = len(mat)
cols = len(mat[0])
visited[i][j] = 1
if mat[i][j] == 0:
community_count += 1
if i < rows - 1:
if visited[i + 1][j] == 0:
community_count, visited = findcommunity(mat, (i + 1, j), visited, community_count)
if j < cols - 1:
if visited[i][j + 1] == 0:
community_count, visited = findcommunity(mat, (i, j + 1), visited, community_count)
if i > 0:
if visited[i - 1][j] == 0:
community_count, visited = findcommunity(mat, (i - 1, j), visited, community_count)
if j > 0:
if visited[i][j - 1] == 0:
community_count, visited = findcommunity(mat, (i, j - 1), visited, community_count)
return community_count,visited
else:
return community_count,visited
Here a completely different approach, in case someone is interested.
import numpy as np
mat = [[1, 0, 0, 3, 0],
[0, 0, 2, 3, 0],
[2, 0, 0, 2, 0],
[0, 1, 2, 3, 3]]
mat = np.array(mat)
# some padding of -1 to prevent index error
mask = np.full(np.array(mat.shape) + 2, -1)
mask[1:-1, 1:-1 ] = mat
# visiteds are set to -2
def trace(f, pt):
mask[tuple(pt)], pts = -2, [pt - 1]
pts += [trace(f, pt + d) for d in
([0, 1], [1, 0], [0, -1], [-1, 0]) if
mask[tuple(pt + d)] == f]
return pts
clusters = lambda f: {tuple(pt-1): trace(f, pt) for pt in np.argwhere(mask==f) if mask[tuple(pt)]==f}
# now call with value your looking for
print(clusters(0))
*I am trying to find code to check if four or more 1's, or 2's are next to each other in the 2d list and then return my win function as true
Here is the code below:
# Connect Four
# 2d list
numRows = 6
numCols = 7
board = [[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, 0, 0, 0, 0, 0, 0], ]
def printBoard():
for rows in range(0, numRows):
for cols in range(0, numCols):
print(board[rows][cols], end=' ')
print(" ")
def fillIn(col, player):
col = col - 1
for rows in range(numRows - 1, -1, -1):
if board[rows][col] == 0:
print("Legal Move")
board[rows][col] = player
break
def win():
if horizWin() or vertWin() or diagWin():
return True
return False
def horizWin():
return False
def vertWin():
return False
def diagWin():
pass
player = 1
while not win():
col = int(input("Please Select A Colum 1-7: "))
fillIn(col, player)
printBoard()
if player == 1:
player = 2
else:
player = 1
I was following a tutorial and it abruptly stopped. So any help would be greatly appreciated :)
You can do something like this.
I added some debug print statements so you understand better what is happening step by step. Dissable the prints when you are comfortable on how the code works
def horizWin():
# loop over each row in the board
for row in board:
print (f"Current row: {row}")
# take a window of size 4 and slide it over the row.
# you need to iterate from 0 to len(row)-windowsize+1
for i in range(len(row)-4+1):
window = row[i:i+4]
print(f" Current window: {window}")
# check if all elements in the row are 1s or 2s
# all elements are the same if the number of elements
# equal to the first one is the size of the window.
# you also need to check that this element is 1 or 2
if window.count(window[0]) == 4 and window[0] in (1,2):
print(f" This window has a winning position for player {window[0]}")
return True
print("No winning positions found in the board")
return False
Okay, so I have an array coin and I want to create a new array which is the same length as array, but with the amount of coins from the array 'coins' needed for input m.
coin = [200,100,50,20,10,5,2,1]
So far, I have the following. What should be in for loop for me to return what I want?
def coinSplitGD2(m):
coin = [200,100,50,20,10,5,2,1]
if m==0:
return 0
for i in range(len(coin)):
if coin...
So if m is 143, it will return [0, 1, 0, 2, 0, 0, 1, 1] meaning no 200-coins, one 100-coin, no
50-coins, two 20-coins, no 10-coins, no 5-coins, one 2-coin and one 1-coin
coin = [200,100,50,20,10,5,2,1]
def coinSplitGD2(m):
a = []
for c in coin:
a.append(m // c)
m %= c
return a
so that:
coinSplitGD2(143)
returns:
[0, 1, 0, 2, 0, 0, 1, 1]
I have to program this puzzle and solve it (I'm using 100 coins instead of 26), and currently all I have are:
def flip():
if (coin == 0):
coin = 1
if (coin == 1):
coin = 0
def move():
table_one.remove(coin)
table_two.append(coin)
def CoinPuzzle():
table_one = [[1]*20 + [0]*80]
table_two = []
#Move 20 coins from table_one to table_two
#Flip all 20 coins in table_two
#Both tables should have an equal number of 1s
I have a hard time linking individual coin objects with items in the list so that I can execute flip and move functions. I'm new to Python, can someone guide me how to do this?
NEW EDIT: How should I modify the code if I have input like this:
L=[0]*100
for i in random.sample(range(100),20):
L[i]=1
[L1,L2]=tables(L)
Here is small python implementation:
import random
heads_count = 20
total_coins = 100
table_one = [True] * heads_count + [False] * (total_coins-heads_count)
table_two = []
def flip(table, coin):
table[coin] = not table[coin]
def move_random():
coin = random.randint(0, len(table_one)-1)
table_two.append(table_one[coin])
del table_one[coin]
for i in range(heads_count):
move_random()
for i in range(heads_count):
flip(table_two, i)
print(sum(table_one))
print(sum(table_two))
Here's an alternative to Stephen's version. To make the output easier to read I'll use the numbers from the original puzzle.
We use the shuffle function to randomize the order of the coins in table_one in a single step, then use slicing to move heads_count coins from table_one to table_two. To flip the coins, we use the fact that 1 - 0 = 1 and 1 - 1 = 0.
from random import seed, shuffle
# seed the randomizer so we get repeatable results
seed(42)
total_coins = 26
heads_count = 10
# Put all the coins in table_one and randomize their order
table_one = [1] * heads_count + [0] * (total_coins - heads_count)
shuffle(table_one)
print('Initial')
print('Table one:', table_one, sum(table_one), len(table_one))
# move heads_count coins to table_two
table_one, table_two = table_one[heads_count:], table_one[:heads_count]
#flip all the coins in table_two
table_two = [1 - coin for coin in table_two]
print('Final')
print('Table one:', table_one, sum(table_one), len(table_one))
print('Table two:', table_two, sum(table_two), len(table_two))
output
Initial
Table one: [0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1] 10 26
Final
Table one: [1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1] 8 16
Table two: [1, 1, 1, 0, 0, 1, 1, 1, 1, 1] 8 10
We could even combine the last two steps into a single statement:
table_one, table_two = table_one[heads_count:], [1 - coin for coin in table_one[:heads_count]]