So I have this code for checking tic tac toe winner in row and in column:
for row in range(rows):
symbols_in_row = 0
for column in range(columns):
if grid[row][column] == player_symbol:
symbols_in_row += 1
if symbols_in_row == winning_line:
return True
else:
symbols_in_row = 0
for column in range(columns):
symbols_in_column = 0
for row in range(rows):
if grid[row][column] == player_symbol:
symbols_in_column += 1
if symbols_in_column == winning_line:
return True
else:
symbols_in_column = 0
How can I do it in one loop?
If you can use NumPy, you can use its sum methods to identify if you have won. Take player1 as 1, player2 as -1, and no entry as 0. If the sum of a row, column, or diagonal is +3 or -3 a player has won.
import numpy as np
matrix = np.zeros([3,3])
row_sum = matrix.sum(axis = 1)
col_sum = matrix.sum(axis = 0)
diag1_sum = np.trace(matrix)
diag2_sum = np.trace(np.flip(matrix, axis=1))
for i in [row_sum, col_sum, diag1_sum, diag2_sum]:
if(3 in i or -3 in i): ## Checking which one has one is upto you
print("victory")
Related
I'm currently learning BackTracking algorithms with Python and the first question everyone typically starts with is NQueens. NQueens is where you take a board of size N x N and you have to determine where to place N queens, in such an order they are not attacked by any other queen.
Example:
N = 5
['Q', 0, 0, 0, 0]
[0, 0, 'Q', 0, 0]
[0, 0, 0, 0, 'Q']
[0, 'Q', 0, 0, 0]
[0, 0, 0, 'Q', 0]
Currently, my algorithm returns ALL Possible Solutions. How do I produce ONE outcome. For instance, when N = 8, there are 92 optimal outcomes, how do I just return One Outcome instead of printing 92 separate Outcomes.
#This is our main recursive function that will determine optimal outcome
def NQueens(row,Current,N):
#this tells us when to stop
if row == N:
print("\n")
return printBoard(Current)
for choice in range(0,N):
if isValid(row,choice,Current,N):
#Place Queen in appropriate spot
Current[row][choice] = "Q"
#Go to next row
NQueens(row+1,Current,N)
Current[row][choice] = 0
return "All Solutions Found"
#This function determines whether we can put a Queen in a certain orientation on the board
def isValid(row,col,Current,N):
#check whether current state of game has queen in row/column
for i in range(0,N):
#checks column/row and sees whether a queen exists already
if Current[row][i] == "Q" or Current[i][col] == "Q":
return False
# Check upper diagonal on right side
i = row-1
j = col + 1
#Do while row is greater than 0 and column is less than N
while i >= 0 and j < N:
if Current[i][j] == "Q":
return False
i -= 1
j += 1
# Check upper diagonal on left side
#Do while row is greater than 0 and column is greater than N
i = row-1
j = col - 1
while i >= 0 and j >= 0:
if Current[i][j] == "Q":
return False
i -= 1
j -= 1
#If we pass the diagonal/row/column tests, we can then determine this is a valid move
return True
###############################################################################################################
#These functions deal with board creation and printing them in a proper format
def generateBoard(N):
#generate board based on User Input N in Main()
Board = [[0 for i in range(0,N)] for j in range(0,N)]
return Board
def printBoard(arr):
#Loop through each row to print an organized board
for row in arr:
print(row)
def main():
#ask number from user
print("What sized board would you like?"
" Please input a number higher that 3: ")
#user input used to determine size of board
N = int(input())
#generate Board that will be used
Board = generateBoard(N)
#this is the current status of the board
printBoard(Board)
print("\n")
#Runs Algorithm
print(NQueens(0,Board,N))
if __name__ == "__main__":
main()
NQueens needs to communicate to its caller that a solution has been found; a simple return True will do if that's the case. I made the following changes to your code (your previous lines are commented):
def NQueens(row,Current,N):
#this tells us when to stop
if row == N:
print("\n")
#return printBoard(Current)
return True # found a solution, say so
for choice in range(0,N):
if isValid(row,choice,Current,N):
#Place Queen in appropriate spot
Current[row][choice] = "Q"
#Go to next row
# NQueens(row+1,Current,N)
if NQueens(row+1,Current,N): # recursive call found a solution, let's stop
return True
Current[row][choice] = 0
#return "All Solutions Found"
And in main():
# ...
#Runs Algorithm
#print(NQueens(0,Board,N))
if NQueens(0,Board,N):
printBoard(Board) # found a solution, print it
I have fixed your code to have well-perfoming:
I merge this code https://www.geeksforgeeks.org/n-queen-problem-backtracking-3/ and yours to get it.
count = 1
def printOut(arrayMap):
global count
print('{}: -'.format(count))
count += 1
for i in range(0, len(arrayMap)):
print(arrayMap[i])
# This is our main recursive function that will determine optimal outcome
def NQueens(currentRow, arrayMap, matrixSize):
# this tells us when to stop
if currentRow == matrixSize:
print()
printOut(arrayMap)
return True # found a solution, say so
res = False
for col in range(0, matrixSize):
if isValid(currentRow, col, arrayMap, matrixSize):
# Place Queen in appropriate spot
arrayMap[currentRow][col] = 0
# Go to next row
# NQueens(row+1,Current,N)
res = NQueens(currentRow + 1, arrayMap, matrixSize) or res # recursive call found a solution, let's stop
arrayMap[currentRow][col] = 1
# return "All Solutions Found"
return res
# This function determines whether we can put a Queen in a certain orientation on the board
def isValid(row, col, arrayMap, matrixSize):
# check whether current state of game has queen in row/column
for i in range(0, matrixSize):
# checks column/row and sees whether a queen exists already
if arrayMap[row][i] == 0 or arrayMap[i][col] == 0:
return False
# Check upper diagonal on right side
i = row - 1
j = col + 1
# Do while row is greater than 0 and column is less than N
while i >= 0 and j < matrixSize:
if arrayMap[i][j] == 0:
return False
i -= 1
j += 1
# Check upper diagonal on left side
# Do while row is greater than 0 and column is greater than N
i = row - 1
j = col - 1
while i >= 0 and j >= 0:
if arrayMap[i][j] == 0:
return False
i -= 1
j -= 1
# If we pass the diagonal/row/column tests, we can then determine this is a valid move
return True
###############################################################################################################
if __name__ == "__main__":
# ask number from user
print("What sized board would you like?")
N = int(input('Choose your size: '))
# generate Board that will be used
Board = [[1 for i in range(0, N)] for j in range(0, N)]
count = 0
NQueens(0, Board, N)
I have an N queen program with backtracking (it generates all the possible solutions) that I want to change it in a way that it places the queens in the half of each column and half of each row(number of columns and rows are even). for example if I have 6 columns and 4 rows it puts 2 queens in each row and 3 queens in each column.
Output example:
[[1 0 1 0 0 1]
[0 1 0 1 1 0]
[1 0 1 0 0 1]
[0 1 0 1 1 0]]
The problem is when I run my script I get this error:
IndexError: index 4 is out of bounds for axis 0 with size 4
I don't know which part I'm doing wrong.
here is my code:
k = 1
global N
t=4
N=t-1
w=(t-1)*2
def printSolution(board):
global k
print(k, "-\n")
k = k + 1
for i in range(N*2):
for j in range(N*2):
print(board[i][j], end = " ")
print("\n")
print("\n")
def isSafe(board, row, col) :
for i in range (row):
for j in range(col):
if np.sum(board[i][j])>N:
return False
for j in range (col):
for i in range(row):
if np.sum(board[i][j])> int(t/2):
return False
return True
def solveNQUtil(board,row, col) :
if col>=w and row<t:
col=0
row+=1
if (col == w and row==t):
printSolution(board)
return True
res = False
for i in range(N):
if (isSafe(board, row, col)):
board[row][col] = 1;
res = solveNQUtil(board, row,col+1 ) or res;
return res
def solveNQ() :
board = np.zeros((t,w))
if (solveNQUtil(board, 0,0) == False):
print("Solution does not exist")
return
return
solveNQ()
If you hit the last element on the board, you will have col = w and row = t-1. So in solveNQUtil you will enter the first block and set col = 0 and row = t. Then, in the next check you don't have col == w but col = 0. So you continue and later attempt to access board[row] which is then of course out of bounds.
I guess the test whether you reached the end should be the first thin in solveNQutil and should read something like if col == w and row == t - 1?
So I'm trying to make a sudoku game and it's coming along fairly well except at the state I'm at the program gives me an error for every move I try to make. isRow checks if a move is possible on the row and so on and isPossible combines the 3 to check if a move is possible or not. Can anyone tell me what is wrong with my verifications?
board = list(range(81)) # Creates a board with 9*9 elements
board2 = board # Duplicates this board for later verfications
def showLine(start, end): # Prints each line of the sudoku puzzle
for i in range(start, end):
if i < end-1:
print(str(board[i]), '|', end =" ")
else:
print(str(board[i]))
def showGroup(start): # Prints each 9*3 group of regions (1/3 of the puzzle)
for i in range(3):
end = start + 9
showLine(start, end)
start += 9
if start != 81:
print('----------+-----------+-----------')
def show(): # Prints whole puzzle
for i in range(0, 55, 27):
showGroup(i)
rows = []
columns = []
groups = []
for i in range(0, 80, 9): # Cretes a list of rows
rows.append(board[i:i+9])
for i in range(9): # Creates a list of columns
columns.append(board[i::9])
temp = 0
for x in range(0, 61, 3): # Creates a list of groups (3*3 regions)
group = []
for i in range(3):
for j in range(3):
temp = x + 9*i + j
group.append(temp)
groups.append(group)
#Duplicating rows columns and groups for verifications
rows2 = rows
columns2 = columns
groups2 = groups
def isRow(cell, number): # Checking if an introduces number isn't repeating in the row
x = 0
for row in rows2:
if cell in row:
x = rows2.index(row)
if number in rows[x]:
return False
else:
return True
def isColumn(cell, number):): # Checking if an introduces number isn't repeating in the column
x = 0
for column in columns2:
if cell in column:
x = columns2.index(column)
if number in columns[x]:
return False
else:
return True
def isGroup(cell, number):): # Checking if an introduces number isn't repeating in the group
x = 0
for group in groups2:
if cell in group:
x = groups2.index(group)
if number in groups[x]:
return False
else:
return True
def isPossible(cell, number): # Combines the last 3 verifications
if isRow(cell, number) and isColumn(cell, number) and isGroup(cell, number):
return True
else:
return False
for i in board: # Fills the board with 0's to not interfere with the game
board[i] = 0
while True:
show()
selected_cell = int(input("Please select an available cell: "))
number = int(input("Please select a number for that cell: "))
if isPossible(selected_cell, number):
board[selected_cell] = number
else:
print("Error, please try again")
I need to write a function def amountofNeighbours(row, column) that prints the amount of neighbours there are to a certain element in the matrix. For example, given the matrix [[2, 3, 4], [5, 6, 7], [8, 9, 10]], there are three neighbours to the element 2 at position [0][0], while there are eight neighbours to the element 6 at position [1][1]. I'm not sure what is the best way to handle a problem like this. I went through all the possibilities, and this gave me the following:
def amountofNeighbours(row, column):
neighbours = 0
for i in range(row):
for j in range(column):
if i == 0 and j == 0 or i == 0 and j == column - 1:
neighbours = 3
elif i == row - 1 and j == 0 or i == row-1 and j == column - 1:
neighbours = 3
elif i > 0 and j == 0 or i == 0 and j > 0:
neighbours = 5
elif i == row - 1 and j > 0:
neighbours = 5
elif j == column - 1 and i > 0:
neighbours = 5
else:
neighbours = 8
return neighbours
When I called this with amountofNeighbours(1, 1) it gave me the correct answer, namely 3, but if I called it with amountofNeighbours(2,2) the answer should be 8 while it gave me 3. Anyone has an idea for improvement?
A straight forward way to do it is to say, "If the cell is at corner, it has three neighbors, otherwise if it is on an edge, it has five, otherwise it has 8."
def numberOfNeighbors(rows, columns, row, column):
topBottom = row in (0, rows-1)
leftRight = column in (0, columns-1)
if topBottom and leftRight:
return 3
if topBottom or leftRight:
return 5
return 8
Your function as it is designed now does not do what you specified. It takes in the number of rows and columns. Then it loops through all elements of your matrix and calculates the number of neighbours. Then it returns the last value calculated, so the bottom right element of your matrix, which has 3 neighbours indeed.
You should get rid of the loops to get it to do what you want. To clarify:
def amountofNeighbours(row, column, n_rows, n_cols):
neighbours = 0
if row == 0 and column == 0 or row == 0 and column == n_cols - 1:
neighbours = 3
elif row == n_rows - 1 and column == 0 or row == n_rows-1 and column == n_cols - 1:
neighbours = 3
elif row > 0 and column == 0 or row == 0 and column > 0:
neighbours = 5
elif row == n_rows - 1 and column > 0:
neighbours = 5
elif column == n_cols - 1 and row > 0:
neighbours = 5
else:
neighbours = 8
return neighbours
One solution to avoid many IFs is to start from the element and compute an "enlarged" box around it (a 3x3 square) possibly placed partially outside the matrix.
Then you clamp the result and return the number of elements minus one:
def neighbors(row, col, rows, cols):
ra, rb = row-1, row+2
ca, cb = col-1, col+2
dx = min(cb, cols) - max(0, ca)
dy = min(rb, rows) - max(0, ra)
return dx*dy - 1
The image shows the selected element and the enlarged box around it. The min/max operation will cut off the extra squares leaving a 2x3 box resulting in 2*3-1=5 neighbors count.
I took a liking to Conway's Game of Life and began to try and write it in python. At this moment I have yet to write any code for the borders of the program so I am just asking for help with what I have right now. I seem to have trouble when initialization a "blinker" formation. Instead of oscillating like it should, it seems to turn itself into a cube.
#File: gameoflife.py
#Description: This is a basic "life" simulation that follows three distinct rules:
#1.Any live cell with fewer than two live neighbours dies
#2.Any live cell with two or three live neighbours lives
#3.Any live cell with more than three live neighbours dies
#4.Any dead cell with exactly three live neighbours becomes a live cell
#A neighbor is deemed as any cell directly horizantal/vertical/diagonal
#meaning there are 9 neighbors to a cell at any time
from graphics import *
import random
from time import sleep
def initial(D,M,win):
#Creates the white board background
for i in range (11):
m = [] # rectangle list
for j in range (11):
rec = Rectangle(Point(6 + 4 * i, 6 + 4 * j), Point(10 + 4 * i, 10 + 4 * j))
D[i][j] = 0
rec.setFill("white")
rec.draw(win)
m.append(rec)
M.append(m)
def check(x,y,D):
#Checks all 9 adjacent neihbors to see if "alive" and checks this number
#means the cell should stay alive(1), die(0), or if already dead come
#back alive(2)
counter = 0
if D[x+1][y] == 1:
counter += 1
if D[x-1][y] == 1:
counter += 1
if D[x][y+1] == 1:
counter += 1
if D[x][y-1] == 1:
counter +=1
if D[x+1][y+1] == 1:
counter+=1
if D[x+1][y-1] == 1:
counter+= 1
if D[x-1][y-1] == 1:
counter += 1
if D[x-1][y+1] == 1:
counter +=1
if counter<2 or counter>3:
return 0
if counter == 2:
return 1
if counter == 3:
return 2
def main():
win = GraphWin("Game of Life", 700, 600)
win. setCoords(0, 0, 70, 60)
#Initialize two dimesion arrays.
#D records color of grids, M records rectangles
D = []
M = []
C = []
#initialize the grids to create all "white"
for i in range(11):
d = []
c = []
for j in range(11):
d.append(0)
c.append(0)
D.append(d)
C.append(c)
initial(D,M,win)
#Initialzes three "alive" units
D[5][5],D[4][5] ,D[6][5]= 1,1,1
C[5][5],C[4][5] ,C[6][5]= 1,1,1
M[5][5].setFill("Black")
M[4][5].setFill("Black")
M[6][5].setFill("Black")
#Contiually checking
while True:
#Purposfully not checking the "Borders" of the array
for i in range (len(D)-1):
for j in range(len(D[i])-1):
#If the cell is alive
if D[i][j] == 1:
#If the cell should die
if check(i,j,D) == 0:
sleep(1)
#Sets a temporary list to white
C[i][j] = 0
#Fills the cell white
M[i][j].setFill("White")
#if the cell is dead
if D[i][j] == 0:
#If the cell should be revived
if check(i,j,D) == 2:
sleep(1)
#Sets a temporary list to black
C[i][j] = 1
#Fills the cell black
M[i][j].setFill("Black")
#Sets the main list = to the temporary list
D = C
main()
You will need to swap D and C, and not just assign C to D. As it stands now, D and C will be referring to the same list after the first iteration.
Here is a simple algorithm to do Conway's Game of Life in python using a numpy array of arbitrary 2D size:
import numpy
# this function does all the work
def play_life(a):
xmax, ymax = a.shape
b = a.copy() # copy grid & Rule 2
for x in range(xmax):
for y in range(ymax):
n = numpy.sum(a[max(x - 1, 0):min(x + 2, xmax), max(y - 1, 0):min(y + 2, ymax)]) - a[x, y]
if a[x, y]:
if n < 2 or n > 3:
b[x, y] = 0 # Rule 1 and 3
elif n == 3:
b[x, y] = 1 # Rule 4
return(b)
# replace (5, 5) with the desired dimensions
life = numpy.zeros((5, 5), dtype=numpy.byte)
# place starting conditions here
life[2, 1:4] = 1 # a simple "spinner"
# now let's play
print(life)
for i in range(3):
life = play_life(life)
print(life)
This is not very efficient, but will certainly get the job done. Replace print(life) with whatever graphical calls you prefer.