Python: use item in the list as function arguments - python

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]]

Related

Python - highlight pattern inside a matrix

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

How to check connect 4 for horizontal wins

*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

Greedy Algorithms and append function - how to create a new array?

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]

Programming Maze Solution recursively

This function is intended to recursively navigate a maze and find the length of the shortest path. The path itself is not necessary, only the length. The maze is represented by a 2d list with values such as
0 1 0 0 0
0 0 0 1 0
0 0 0 1 0
The user starts at (0,0) and must end up at the end of the maze as defined (in my case it is the bottom right cell). 1's represent walls.
def maze(x,y,array,length):
m = len(array)
n = len(array[0])
if x < 0 or y < 0 or x == m or y == n or array[x][y] == 1:
return float("inf")
elif x == m - 1 and y == n - 1:
return length
else:
array[x][y] = 1
up = maze(x - 1,y,array,length + 1)
right = maze(x,y + 1,array,length + 1)
down = maze(x + 1,y,array,length + 1)
left = maze(x,y - 1,array,length + 1)
return min(up,down,left,right)
array = [[0,1,0,0,0],[0,0,0,1,0],[0,0,0,1,0]]
minLength = maze(0,0,array,1)
print(minLength)
I designed it so that it recursively finds all possible paths from each direction (up, down, left and right), and returns the lowest value from all these paths with each step of the way. It returns inf for any path that is not valid.
For this specific array, it returns 11, which is false, it should be 9. I do not believe it is merely a mathematical error, as I tried printing each step of the way and it is not recognizing certain paths (it returns inf for paths that most definitely have options).
I can't seem to find where my code is going wrong, it seems like it should properly return the value, but in practice it does not.
array is a reference to the original array, not a local copy. See any of the on-line tutorials on how Python passes function arguments, or how it handles lists. You can see the effect by printing array in your main program after the call to maze:
Final Maze [
[1, 1, 1, 1, 1],
[1, 1, 1, 1, 1],
[1, 1, 1, 1, 0]
]
Fixing this is relatively easy: copy the nested list and use that copy locally.
from copy import deepcopy
def maze(x,y,array,length):
m = len(array)
n = len(array[0])
if x < 0 or y < 0 or x == m or y == n or array[x][y] == 1:
return float("inf")
elif x == m - 1 and y == n - 1:
return length
else:
new_maze = deepcopy(array)
new_maze[x][y] = 1
up = maze(x - 1,y,new_maze,length + 1)
right = maze(x,y + 1,new_maze,length + 1)
down = maze(x + 1,y,new_maze,length + 1)
left = maze(x,y - 1,new_maze,length + 1)
return min(up,down,left,right)
array = [[0,1,0,0,0],[0,0,0,1,0],[0,0,0,1,0]]
minLength = maze(0,0,array,1)
print("Final Maze", array)
print(minLength)
The output from this is (edited for readability again)
Final Maze [
[0, 1, 0, 0, 0],
[0, 0, 0, 1, 0],
[0, 0, 0, 1, 0]
]
9

Manhattan grid directions with random walk

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)

Categories