Recursive Path finding error - python

I'm working on an exercise where given a set of connections between two points (ie. 12 is a connection between 1 and 2 ect.). I decided to tackle the approach recursively in order to have it systematically check every path and return when it finds one that hits every node and starts and ends with one.
However upon debugging this it seems that as I pass down the adjMatrix further into the recursion it's also editing the upper levels and causing it not to search any further as it goes back up the tree. I think it has something to when I set newMatrix = adjMatrix, but I'm not exactly sure.
def checkio(teleports_string):
#return any route from 1 to 1 over all points
firstnode, secondnode, size = 0, 0, 8
#Makes the adjacency matrix
adjMatrix = [[0 for i in range(size)] for j in range(size)]
for x in teleports_string:
#Assigns Variables
if firstnode == 0 and x != ",":
#print("Node1:" + x)
firstnode = x
elif secondnode == 0 and x != ",":
#print("Node2:" + x)
secondnode = x
#Marks connections
if firstnode != 0 and secondnode != 0:
adjMatrix[int(firstnode) - 1][int(secondnode) - 1] = 1
adjMatrix[int(secondnode) - 1][int(firstnode) - 1] = 1
firstnode, secondnode = 0, 0
print(adjMatrix)
return findPath(adjMatrix, 1, "1")
def findPath(adjMatrix, currentnode, currentpath):
if isFinished(currentpath):
return currentpath
for x in range(0, 8):
if adjMatrix[currentnode - 1][x] == 1:
print(currentpath + "+" + str(x+1))
newMatrix = adjMatrix
newMatrix[currentnode - 1][x] = 0
newMatrix[x][currentnode - 1] = 0
temp = currentpath
temp += str(x+1)
newpath = findPath(newMatrix, x+1,temp)
print(newpath)
if isFinished(newpath):
print ("Returning: " + newpath)
return newpath
return ""
def isFinished(currentpath):
#Checks if node 1 is hit at least twice and each other node is hit at least once
if currentpath == "":
return False
for i in range(1, 9):
if i == 1 and currentpath.count(str(i)) < 2:
return False
elif currentpath.count(str(i)) < 1:
return False
#Checks if it starts and ends with 1
if not currentpath.startswith(str(1)) or not currentpath.endswith(str(1)):
return False
return True
#This part is using only for self-testing
if __name__ == "__main__":
def check_solution(func, teleports_str):
route = func(teleports_str)
teleports_map = [tuple(sorted([int(x), int(y)])) for x, y in teleports_str.split(",")]
if route[0] != '1' or route[-1] != '1':
print("The path must start and end at 1")
return False
ch_route = route[0]
for i in range(len(route) - 1):
teleport = tuple(sorted([int(route[i]), int(route[i + 1])]))
if not teleport in teleports_map:
print("No way from {0} to {1}".format(route[i], route[i + 1]))
return False
teleports_map.remove(teleport)
ch_route += route[i + 1]
for s in range(1, 9):
if not str(s) in ch_route:
print("You forgot about {0}".format(s))
return False
return True
assert check_solution(checkio, "13,14,23,25,34,35,47,56,58,76,68"), "Fourth"

The line
newMatrix = adjMatrix
merely creates another reference to your list. You'll need to actually create a new list object. As this is a matrix, do so for the contents:
newMatrix = [row[:] for row in adjMatrix]
This creates a new list of copies of your nested lists.

Related

my pop( ) function does not delete the top element of a list, but rather a random one

I have created the following pop function:
def pop(arr):
if not isempty(arr):
topelement = arr[len(arr)-1]
arr.remove(topelement)
return topelement
And it worked correctly until I used it in order to reverse order of a stack of numbers and operators:
"3 6 2 + * 14 3 4 + + /"
into
"/ + + 4 3 14 * + 2 6 3".
In first iteration of while loop shown below it pushed "/" operator to the auxiliary stack and deleted it from the top of entry, which is OK - but in the second iteration it deleted "+" sign from the middle of the entry instead of the plus sign with the highest index.
def evaluation(eq):
entryunsplit = errpostfix(eq)
entry = entryunsplit.split()
lengthofentry = len(entry)
stack = []
while len(stack) != lengthofentry:
push(stack,pop(entry))
Could someone please explain me why didn't it delete the last element and how can I avoid that error?
I am putting the whole code below in case some other element turns out to be significant.
stack1 = []
max_size = 30
def push(arr,a):
if len(arr) < max_size:
arr.append(a)
def isempty(arr):
if len(arr) == 0:
return True
else:
return False
def top(arr):
if not isempty(arr):
return arr[len(arr)-1]
def pop(arr):
if not isempty(arr):
topelement = arr[len(arr)-1]
arr.remove(topelement)
return topelement
def errpostfix(eq):
entry = eq.split()
opstack = []
exit = []
priorities = { "+": 1, "-": 1, "*": 0, "/": 0 }
for token in entry:
if token == "(":
push(opstack,token)
elif token == "*" or token == "/" or token == "+" or token == "-":
if top(opstack) == "*" or top(opstack) == "/" or top(opstack) == "+" or top(opstack) == "-":
while not isempty(opstack) and priorities[top(opstack)] >= priorities[token]:
push(exit,pop(opstack))
isempty(opstack)
push(opstack,token)
elif token == ")":
while top(opstack) != "(":
push(exit,pop(opstack))
pop(opstack)
else:
push(exit,token)
while not isempty(opstack):
push(exit, pop(opstack))
output = " ".join(exit)
return output
def isop(ch):
if ch == "+" or ch == "-" or ch == "*" or ch == "/":
return True
else:
return False
def evaluation(eq):
entryunsplit = "3 6 2 + * 14 3 4 + + /"
entry = entryunsplit.split()
lengthofentry = len(entry)
stack = []
while len(stack) != lengthofentry:
push(stack,pop(entry))
The remove() operation on a list will delete the first occurrence of an item in that list, is not "random" (check the docs). If there are several repeated elements, the first one encountered will be the one that gets deleted. To delete the last element, simply use the built-in pop() method:
def pop(arr):
if not isempty(arr):
topelement = arr[-1]
arr.pop()
return topelement

how to solve out of range probleme in python

I'm trying to build 4 in row game so when I try to make the players have the same choice it give this error
list index out of range
this is an example of what happedenter image description here
it seems the probleme with winning condition but I don't understand why this happend
it gives right answer when the input is correct like make the one player win but when make them have same choice it is break.
the code is
Width = 4
Height = 4
game_board = []
for x in range(Width): game_board.append(list(['a'] * Height))
def make_move(board, borad_row, board_col, piece):
board[borad_row][board_col] = piece
# check if the slot is empty
def is_slot_empty(board, board_col):
return board[Width - 1][board_col] == 'a'
# get the next available
def next_available_slot(board, board_col):
for i in range(Width):
if board[i][board_col] == 'a':
return i
# method for winning conditions
def winning(board, piece):
# check horizontally
for i in range(Height):
for j in range(Width):
if board[j][i] == piece and board[j][i + 1] == piece and board[j][i + 2] == piece and board[j][
i + 3] == piece:
return True
# check vertically
for i in range(Height):
for j in range(Width):
if board[j][i] == piece and board[j + 1][i] == piece and board[j + 2][i] == piece and board[j + 3][
i] == piece:
return True
# positive diagonal
for i in range(Height):
for j in range(Width):
if board[j][i] == piece and board[j + 1][i + 1] == piece and board[j + 2][i + 2] == piece and board[j + 3][
i + 3] == piece:
return True
# negative diagonal
for i in range(Height):
for j in range(Width):
if board[j][i] == piece and board[j - 1][i + 1] == piece and board[j - 2][i + 2] == piece and board[j - 3][
i + 3] == piece:
return True
game_end = False
turn_1 = 0
while not game_end:
if turn_1 == 0:
user_input = int(input("player_1:"))
if is_slot_empty(game_board, user_input):
user_input_row = next_available_slot(game_board, user_input)
make_move(game_board, user_input_row, user_input, 'X')
if winning(game_board, 'X'):
print("player 1 wins")
game_end = True
else:
user_input: int = int(input("player_2:"))
if is_slot_empty(game_board, user_input):
user_input_row = next_available_slot(game_board, user_input)
make_move(game_board, user_input_row, user_input, 'Z')
if winning(game_board, 'Z'):
print("player_2 wins")
game_end = True
for row in reversed(game_board):
print(row)
# alternating between 2 users
turn_1 += 1
turn_1 = turn_1 % 2
To fix winning(), try something like this:
def winning(board, piece):
# check horizontally
for i in range(Height):
if all(board[j][i] == piece for j in range(Width)):
return True
# check vertically
for j in range(Width):
if all(board[j][i] == piece for i in range(Height)):
return True
# positive diagonal
if all(board[i][i] == piece for i in range(Width)):
return True
# negative diagonal
if all(board[i][-(i+1)] == piece for i in range(Width)):
return True
This is only designed to handle a board with equal values for Height and Width.
When you do the checks, make sure to check only the indices that are within the board.
For example, for the horizontal check, both the left end (i) and the right end (i + 3) need to be within the 0..Width-1 range. So you should limit the value of the i index so that i + 3 is still less than Width:
...
# check horizontally
for i in range(Width - 3):
for j in range(Height):
if board[j][i] == piece and board[j][i + 1] == piece and board[j][i + 2] == piece and board[j][i + 3] == piece:
return True
...

Trouble with minimax algorithm in tic tac toe game with adjustable game size

I am trying to create a tic tac toe game with an adjustable game size and a computer that uses the minimax algorithm. The game sizes can only be odd numbers, to make sure that diagonal wins are always possible. The game runs with no errors, but I know that the minimax algorithm isn't working 100% correct because I can still beat the computer. I've looked extensively over my code and cannot find where the algorithm is going wrong. Here is my code:
Main.py
import TicTacToe
import Minimax
if (__name__ == "__main__"):
t = TicTacToe.ttt(3)
m = Minimax.Minimax(3, t)
while (t.winner == None):
if (t.turn == 1):
playerInputI = int(input("Input row: "))
playerInputJ = int(input("Input column: "))
bestIndex = (playerInputI, playerInputJ)
else:
winner, bestIndex = m.minimax(t.grid, (-1, -1), 15, -1)
t.winner = None
t.findWinner(bestIndex, t.grid)
t.updateGameGrid(bestIndex)
print(t.grid)
print(t.grid)
Minimax.py
class Minimax:
def __init__(self, gs, t):
self.gridSize = gs
self.ttt = t
def minimax(self, state, currIndex, depth, turn):
if (currIndex[0] != -1 and currIndex[1] != -1):
winner = self.ttt.findWinner(currIndex, state)
if (winner == -1):
return winner - depth, currIndex
elif (winner == -1):
return winner + depth, currIndex
elif (winner == 0):
return 0, currIndex
if (depth==0 and winner==None):
return 0, currIndex
evalLimit = -turn * 1000
bestIndex = None
for i in range(self.gridSize):
for j in range(self.gridSize):
if (state[i][j] == 0):
state[i][j] = turn
eval, newIndex = self.minimax(state, (i, j), depth-1, -turn)
state[i][j] = 0
if (turn > 0 and eval > evalLimit):
bestIndex = newIndex
evalLimit = eval
elif (turn < 0 and eval < evalLimit):
bestIndex = newIndex
evalLimit = eval
return evalLimit, bestIndex
Tictactoe.py
from random import randint
class ttt:
def __init__(self, size):
self.gridSize = size
self.grid = self.createGrid()
# If using minimax algorithm, user is maximizer(1) and computer is minimizer(-1)
# If single player, then user is 1, computer is -1
# If multiplayer, user1 is 1, user2 = -1
self.turn = 1
self.winner = None
def createGrid(self):
grid = []
for i in range(self.gridSize):
grid.append([])
for j in range(self.gridSize):
grid[i].append(0)
# grid = [[-1, 1, 0], [0, -1, 0], [0, 0, 0]]
return grid
def updateGameGrid(self, index):
if (self.grid[index[0]][index[1]] != 0):
return
self.grid[index[0]][index[1]] = self.turn
winner = self.findWinner(index, self.grid)
self.turn = -self.turn
def randomIndex(self):
x = randint(0, self.gridSize-1)
y = randint(0, self.gridSize-1)
while (self.grid[x][y] != 0):
x = randint(0, self.gridSize-1)
y = randint(0, self.gridSize-1)
return (x, y)
def findWinner(self, index, grid):
# Row
found = True
for j in range(self.gridSize-1):
if (grid[index[0]][j] != grid[index[0]][j+1] or grid[index[0]][j] == 0):
found = False
break
if (found):
self.winner = self.turn
return self.turn
# Column
found = True
for i in range(self.gridSize-1):
if (grid[i][index[1]] != grid[i+1][index[1]] or grid[i][index[1]] == 0):
found = False
break
if (found):
self.winner = self.turn
return self.turn
# Top Left to Bottom Right Diagonal
if (index[0] == index[1]):
found = True
for i in range(self.gridSize-1):
if (grid[i][i] != grid[i+1][i+1] or grid[i][i] == 0):
found = False
break
if (found):
self.winner = self.turn
return self.turn
# Top Right to Bottom Left Diagonal
if (index[0] + index[1] == self.gridSize-1):
found = True
for i in range(self.gridSize-1):
if (grid[self.gridSize-i-1][i] != grid[self.gridSize-i-2][i+1] or grid[self.gridSize-i-1][i] == 0):
found = False
break
if (found):
self.winner = self.turn
return self.turn
tie = True
for i in range(self.gridSize):
for j in range(self.gridSize):
if (grid[i][j] == 0):
tie = False
if (tie):
self.winner = 0
return 0
return None
The grid is represented as a 2d array, with each element being either a -1 for O, 1 for X and 0 for nothing. The player is 1 and the computer is -1. Who's turn it is is represented as a -1 or 1, corresponding to O or X. If anyone is able to find where the error in my code is that would be a great.
I see two troubles :
a) the two following conditions are the same in minimax
if (winner == -1):
return winner - depth, currIndex
elif (winner == -1):
return winner + depth, currIndex
b) When you return bestIndex, you actually return the winning move, the one that completes a line or a row or a diagonal, at one of the leaves of the game tree. What you really want is the next move to play. Write instead bestIndex = (i, j) in the condition if eval > evalLimit
I didn't check for everything but that is a good start. Run your code at depth=1 or 2 with many printf inside the minimax function, and look at the different moves, with the corresponding score, if they look correct or not.

I cant increase specific value at my list in for loop

I use python for my autonomous car project. So, I worked on an algorithm that returns values from the Dijkstra algorithm. I give the algorithm (location, destination) and it returns the shortest path. And then I'm adding the directions values. But I cant increase the values at some point. Here is my code:
coordinates = [['X',0,20],['B',15,20],['H',15,45],['G',20,45],['Y',20,55]]
dir = dijsktra(graph,'X','Y')
indexes = []
for i in range(len(dir)):
for j in range(len(coordinates)):
if dir[i] == coordinates[j][0]:
indexes.append(j)
for i in range(len(dir)-1):
if coordinates[indexes[i]][1] == coordinates[indexes[i+1]][1]:
turnons.append(['R',i+1])
elif coordinates[indexes[i]][2] == coordinates[indexes[i+1]][2]:
turnons.append(['L',i+1])
list_lenght = len(dir) + len(turnons)
for i in range(list_lenght):
for j in range(len(turnons)):
if turnons[j][1] == i:
dir.insert(i,turnons[j][0])
if turnons[j] != turnons[len(turnons)-1]:
print(turnons[j])
turnons[j + 1][1] += 1 // That's is the problem.
This is the expected output: ['L', 1]['R', 3]['L', 5]['R', 7]
This is what i get: ['L', 1]['R', 3]['L', 4]
Here
L = left
R = right
Ladies and Gentlemen, We Got Him.
coordinates = [['X',0,20],['B',15,20],['G',20,45],['Y',20,55],['H',15,45]]
dir = dijsktra(graph,'B','X')
indexes = []
for i in range(len(dir)):
for j in range(len(coordinates)):
if dir[i] == coordinates[j][0]:
indexes.append(j)
turnons = []
newdir = []
for i in range(len(dir)-1):
if coordinates[indexes[i]][1] == coordinates[indexes[i+1]][1]:
turnons.append(['R',i+1])
elif coordinates[indexes[i]][2] == coordinates[indexes[i+1]][2]:
turnons.append(['L',i+1])
uzunluk = len(dir) + len(turnons)
turnsyc = 0
dirsyc = 0
print(dir,turnons)
for i in range(uzunluk):
if i % 2 == 0 or i == 0:
newdir.append(dir[dirsyc])
dirsyc += 1
else:
newdir.append(turnons[turnsyc][0])
turnsyc += 1

program who returns true or false whether a matrix is a magic square or not

I'm trying to make a program that returns a boolean whether a matrix is a magic square or not. I try to submit this code at my college's website, but it returns "Wrong Answer". I can't see what's wrong with it. Can you help me?
def magico(xs):
#print(soma(xs),soma2(xs),diag(xs))
if(soma(xs) == soma2(xs) == diag(xs) != -1 ):
return True
else:
return False
def soma(xs):
sant = 0
s = 0
for i in range(len(xs)):
if(s != sant):
return -1
s = 0
for j in range(len(xs)):
s = s + int(xs[i][j])
sant = s
return s
def soma2(xs):
s = 0
sant = 0
for j in range(len(xs)):
if(s != sant):
return -1
s = 0
for i in range(len(xs)):
s = s + int(xs[j][i])
sant = s
return s
def diag(xs):
s = 0
for i in range(len(xs)):
s = s + int(xs[i][i])
t = 0
for i in range(len(xs)):
t = t + int(xs[i][len(xs) - 1 - i])
if(s == t):
return s
else:
return -1
Pseudocode
magic = true
answer = sum(square)/n_rows(square)
for r in rows(square):
if sum(r) not equal to answer
magic = false
for c in columns(square):
if sum(c) not equal to answer
magic = false
d1 = principal_diagonal(square)
d2 = secondary_diagonal(square)
if sum(d1) or sum(d2) not equal to answer
magic = false
display magic
You are not checking if the matrix is square, you are not checking if the numbers in the matrix are unique. Beyond that you have a serious coding issue:
Your loops all end with
sant = s
They start with
if(s != sant):
But you have just made them equal...

Categories