I am currently writing an eight queens problem solving algorithm.
The alogorithm is not the problem tho. Its the storing of the solutions.
I am trying to append the solutions (solutions are stored in a list of lists) to a list,
but after saving the solution and continuing through the algorithm,
the Values of the saved list keep changing.
I suppose the saved list and the one I am changing are somehow still "connected",
but I dont know how.
Does anyone know a solution or a different approach to my saving strategy?
This is the part of the code I am having Problems with.
# The Code only gets executed if there is a valid solution.
if found_solution():
# Saving solution
solutions.append(board)
# deleting last Queen
temp = last_queen.pop()
board[temp[0]][temp[1]] = "-"
# going back one Row
Reihe -= 1
# return
return
The board does look like this
board = [["-","-","-","-"],
["-","-","-","-"],
["-","-","-","-"],
["-","-","-","-"]]
the solution list like this
solutions = []
If anyone wants to take a look at the whole code (There are a few german variables tho):
board = [["-","-","-","-"],
["-","-","-","-"],
["-","-","-","-"],
["-","-","-","-"]]
Reihe = 0
solutions = []
last_queen = []
def found_solution():
count = 0
for i in range(4):
for j in range(4):
if board[i][j] == "D":
count += 1
if count == 4:
return True
return False
def board_clear(temp_Reihe, temp_i):
#Check Column and Row
for k in range(4):
if board[temp_Reihe][k] == "D":
return False
if board[k][temp_i] == "D":
return False
#Check Diagonals
#temp_i == x and temp_Reihe == y
st1_x = temp_i - min(temp_i, temp_Reihe)
st1_y = temp_Reihe - min(temp_i, temp_Reihe)
st2_x = temp_i - min(temp_i, 3-temp_Reihe)
st2_y = temp_Reihe + min(temp_i, 3-temp_Reihe)
while st1_x < 4 and st1_y < 4:
if board[st1_y][st1_x] == "D":
return False
st1_x += 1
st1_y += 1
while st2_x < 4 and st2_y > -1:
if board[st2_y][st2_x] == "D":
return False
st2_x += 1
st2_y -= 1
return True
def main():
global Reihe, board, solutions, last_queen
if found_solution():
#Saving solution
solutions.append(board)
#deleting last Queen
temp = last_queen.pop()
board[temp[0]][temp[1]] = "-"
#going back one Row
Reihe -= 1
return
for i in range(4):
#placing Queen if valid spot
if board_clear(Reihe, i):
board[Reihe][i] = "D"
last_queen.append([Reihe,i])
Reihe += 1
main()
#delete last Queen
temp = last_queen.pop()
board[temp[0]][temp[1]] = "-"
#going back one Row
Reihe -= 1
return
main()
People have suggested using copy or deepcopy
list2 = list1.deepcopy()
Related
I have 5 columns ( NO = index of vehicle / LEADER = index of the vehicle of the front / SEC = instant in seconds / X = position of the vehicle)
Some vehicles stop ( X stay the same for a while) and I want to get the exact time it starts to move again. Then, calculate the difference between their instant and their respective 'leader' vehicle.
I made a code but it has so many bugs
OBS: Some vehicles never stop or stop,but never return to move. I want to remove them too.
Here's my code:
dados = pd.read_excel('teste-reaction_001.xlsx')
n=dados["NO"].unique()
final=np.zeros(1)
for i in n:
botao = 0
array_aux=dados[dados["NO"] == i ]["X"]
df = pd.DataFrame(array_aux)
aux=df.diff().to_numpy()
count1 = 0
aux1 = []
for j in aux:
if j == 0:
botao = 1
elif j != 0 and botao == 1:
aux1=np.where(aux==j)[0]
aux1=aux1[np.where(aux1>=count1)[0]]
break
else :
botao = 0
count1 = count1 + 1
aux2=dados["SEC"][dados[dados["NO"]==i]["SEC"].index[aux1]].values[0]
final=np.append(final,aux2)
tr=np.zeros(1)
for i in n:
aux=dados[dados["NO"] == i ]["LEADER"].unique()[0]
aux1=np.where(dados["NO"].unique()==i)[0]
aux2=np.where(dados["NO"].unique()==aux)[0]
if aux2>-1:
aux3=final[int(aux1)]-final[aux2]
else:
aux3 = "s"
tr=np.append(tr,aux3)
columns = ["N", "TR"]
tabela = np.array([dados["NO"].unique(), tr[1:]])
res = pd.DataFrame(data=tabela.T,index=np.arange(len(tabela.T)), columns=columns)
I have the following code for solving the n-queens problem and I am supposed to count the number of recursive calls made. I have a function called ConstructCandidates to get the candidate solutions and I am trying to count the number of recursive calls it makes. I was wondering if I am counting the recursive calls correctly as I am not sure if I am doing this correctly.
def createChessBoard(boardSize):
chessBoard = [0]*boardSize
for index in range(boardSize):
chessBoard[index] = [0]*boardSize
return chessBoard
def isSolution(results, numberOfQueens):
if numberOfQueens==n:
for r in results:
for row in r:
print(row)
print()
return numberOfQueens>len(results)
def safeToPlaceQueen(chessBoard, boardRow, boardColumn, boardSize):
for indexColumn in range(boardColumn):
if chessBoard[boardRow][indexColumn] == 1:
return False
indexRow, indexColumn = boardRow, boardColumn
while indexRow >= 0 and indexColumn >= 0:
if chessBoard[indexRow][indexColumn] == 1:
return False
indexRow-=1
indexColumn-=1
diagonalRow, diagonalColumn = boardRow,boardColumn
while diagonalRow < boardSize and diagonalColumn >= 0:
if chessBoard[diagonalRow][diagonalColumn] == 1:
return False
diagonalRow+=1
diagonalColumn-=1
return True
def ConstructCandidates(chessBoard, columnLength, boardSize):
global recursionCounter
if columnLength >= boardSize:
return
for row in range(boardSize):
if safeToPlaceQueen(chessBoard, row, columnLength, boardSize):
chessBoard[row][columnLength] = 1
if columnLength == boardSize-1:
Process(chessBoard)
chessBoard[row][columnLength] = 0
return
#recursively call ConstructCandidates to find more candidate solutions
ConstructCandidates(chessBoard, columnLength+1, boardSize)
chessBoard[row][columnLength] = 0
recursionCounter+=1
def Process(chessBoard):
global results
solutions = copy.deepcopy(chessBoard)
results.append(solutions)
global count
count= len(results)
def isFinished():
if count >0:
return False
n = 8
chessBoard = createChessBoard(n)
results = []
recursionCounter =0
ConstructCandidates(chessBoard, 0, n)
isSolution(results, n)
if isFinished() is False:
print("All possible solutions without the Queen being in danger have been found")
print("The total number of possible solutions for",n,"Queens is:",len(results))
print("The total number of recursive calls to solve the problem of",n,"Queens is:",recursionCounter)
If I am not doing this correctly would someone be able to show me how? The current result I get for 8-queens is 1964
A few days ago a started making my simple board game. First of all, I generate a board for the game. It looks like this:
the gameboard generated for 13x13
Secondly, I place my character on the board, which is 'A':
The player placed
I made a dice for it which generates numbers from 1 to 6.
My goal right now is to get the 'A' character moving around by the dice on the '*' symbols, until it gets at the top left corner:
I need to get here by the dice
So here is my code that I tried:
import math
import random
import os
board= []
def generator(boardsize):
for row in range(boardsize+1):
brow = []
for column in range(boardsize+1):
if row == column == 0:
brow.append(' ')
elif row==0:
brow.append(str(column-1)[-1])
elif column==0:
brow.append(str(row-1)[-1])
elif ((math.ceil(boardsize/2)-1 )<= column) and(column <= (math.ceil(boardsize/2)+1)) or ((math.ceil(boardsize/2)-1 )<= row) and(row <= (math.ceil(boardsize/2)+1)):
if row == 1 or column == 1 or row == boardsize or column == boardsize:
brow.append('*')
else:
if row == (math.ceil(boardsize/2)) and column == (math.ceil(boardsize/2)):
brow.append('X')
elif row == (math.ceil(boardsize/2)) or column == (math.ceil(boardsize/2)):
brow.append('D')
else:
brow.append('*')
else:
brow.append(' ')
board.append(brow)
return board
def print_table(x):
os.system('cls')
for x in board:
print(' '.join(x))
number_from_dice= []
def dice():
min = 1
max = 6
x = random.randint(min, max)
number_from_dice[:]= [x]
return number_from_dice
def player1(x):
generator(x)
prev_char_y = 1
prev_char_x = math.ceil(x/2)+1
char_y= 1
char_x= math.ceil(x/2)+1
board[char_y][char_x] = "A"
print_table(x)
dice()
f = number_from_dice[0]
for i in range(f):
if(char_y<x):
if (board[char_y+1][char_x]) == '*':
char_y= char_y +1
board[char_y][char_x] = "A"
board[prev_char_y][prev_char_x] = '*'
prev_char_x = char_x
prev_char_y = char_y
print_table(x)
else:
if(char_x!=x):
char_x2 = char_x
if (board[char_y][char_x+1]=='*'):
char_x = char_x +1
board[char_y][char_x] = "A"
board[prev_char_y][prev_char_x] = '*'
prev_char_x = char_x
prev_char_y = char_y
print_table(x)
else:
if (board[char_y+1][char_x]) == '*':
char_y= char_y +1
board[char_y][char_x] = "A"
board[prev_char_y][prev_char_x] = '*'
prev_char_x = char_x
prev_char_y = char_y
print_table(x)
else:
if (board[char_y][char_x2-1]) == '*':
char_x2 = char_x2 -1
board[char_y][char_x2] = "A"
board[prev_char_y][prev_char_x] = '*'
prev_char_x = char_x2
prev_char_y = char_y
print_table(x)
else:
if (board[char_y+1][char_x2]) == '*':
char_y = char_y +1
board[char_y][char_x2] = "A"
board[prev_char_y][prev_char_x] = '*'
prev_char_x = char_x2
prev_char_y = char_y
print_table(x)
print('Number from dice: ', end='')
print(f)
player1(13)
Does the technic I used have potential? Or is it too complicated? How would you do it?
Just in a generic sense you've made it overly complicated.
Consider this - the board, as far as movement is concerned, is just a set of ordered spaces.
But right now you have information about how the board is created as part of the player code.
Best to separate this, and you will find that things get simpler.
Instead, have the player simply track it's progress, in other words, what numbered space is it on.
Then you can generate the board and, knowing the space numbers, you can see if it matches the player location.
And then take it one step further (and simpler still) and just draw the board on a 2D array, and then output that, instead of trying to figure out the board as you go line-by-line.
I've been trying out to solve the monty hall problem in Python in order to advance in coding, which is why I tried to randomize everything. The thing is: I've been running into some trouble. As most of you probably know the monty problem is supposed to show that changing the door has a higher winrate (66%) than staying on the chosen door (33%). For some odd reason though my simulation shows a 33% winrate for both cases and I am not really sure why.
Here's the code:
from random import *
def doorPriceRandomizer():
door1 = randint(0,2) #If a door is defined 0, it has a price in it
door2 = randint(0,2) #If a door is defined either 1 or 2, it has a goat in it.
door3 = randint(0,2)
while door2 == door1:
door2 = randint(0,2)
while door3 == door2 or door3 == door1:
door3 = randint(0,2)
return door1,door2,door3 #This random placement generator seems to be working fine.
while True:
loopStart = 0
amountWin = 0
amountLose = 0
try:
loopEnd = int(input("How often would you like to run this simulation: "))
if loopEnd < 0:
raise ValueError
doorChangeUser = int(input("[0] = Do not change door; [1] = Change door: "))
if doorChangeUser not in range(0,2):
raise ValueError
except ValueError:
print("Invalid input. Try again.\n")
else:
while loopStart != loopEnd:
gameDoors = doorPriceRandomizer()
inputUser = randint(0,2)
if doorChangeUser == 0:
if gameDoors[inputUser] == 0:
amountWin += 1
loopStart += 1
else:
amountLose += 1
loopStart += 1
elif doorChangeUser == 1:
ChangeRandom = 0
while gameDoors[ChangeRandom] == gameDoors[inputUser]:
ChangeRandom = randint(0,2)
if gameDoors[ChangeRandom] == 0:
amountWin += 1
loopStart += 1
else:
amountLose += 1
loopStart += 1
print("Win amount: ",amountWin,"\tLose amount: ",amountLose)
What am I doing wrong? I really appreciate all help! Thanks in advance!
ChangeRandom = 0
while gameDoors[ChangeRandom] == gameDoors[inputUser]:
ChangeRandom = randint(0,2)
This doesn't do what you think it does. Instead of checking if the ChangeRandom door is the same as the inputUser door, this checks if the ChangeRandom door and the inputUser door have the same value -- that is to say they're either both winners or both losers.
That said, that's not even what you want to do. What you want to do is to find a door that's not the user's input that IS a loser door, then switch to the OTHER one that isn't the user's input. This could be implemented with minimal change to your code as:
other_wrong_door = next(c for c, v in enumerate(gameDoors) if v != 0 and c != inputUser)
new_door = next(c for c, _ in enumerate(gameDoors) if c != inputUser and c != other_wrong_door)
But honestly this merits a re-examining of your code's structure. Give me a few minutes to work something up, and I'll edit this answer to give you an idea of how I'd implement this.
import random
DOORS = [1, 0, 0]
def runonce(switch=False):
user_choice = random.choice(DOORS)
if user_choice == 1:
# immediate winner
if switch:
# if you won before and switch doors, you must lose now
return False
else:
new_doors = [0, 0] # remove the user-selected winner
new_doors = [0] # remove another loser
return bool(random.choice(new_doors))
# of course, this is always `0`, but
# sometimes it helps to show it. In production you
# wouldn't bother writing the extra lines and just return False
else:
if switch:
new_doors = [1, 0] # remove the user-selected loser
new_doors = [1] # remove another loser
return bool(random.choice(new_doors))
# as above: this is always True, but....
else:
return False # if you lost before and don't switch, well, you lost.
num_trials = int(input("How many trials?"))
no_switch_raw = [run_once(switch=False) for _ in range(num_trials)]
switch_raw = [run_once(switch=True) for _ in range(num_trials)]
no_switch_wins = sum(1 for r in no_switch_raw if r)
switch_wins = sum(1 for r in switch_raw if r)
no_switch_prob = no_switch_wins / num_trials * 100.0
switch_prob = switch_wins / num_trials * 100.0
print( " WINS LOSSES %\n"
f"SWITCH: {switch_wins:>4} {num_trials-switch_wins:>6} {switch_prob:.02f}\n"
f"NOSWITCH:{no_switch_wins:>4} {num_trials-no_switch_wins:>6} {no_switch_prob:.02f}")
You have gotten the mechanics of the problem wrong so you are getting the wrong result. I have rewritten the choice mechanics, but I am leaving the user input stuff to you so that you can continue to learn python. This is one of many ways to solve the problem, but hopefully it demonstrates some things to you.
def get_choices():
valid_choices = [0, 1, 2] # these are the values for a valid sample
shuffle(valid_choices) # now randomly shuffle that list
return valid_choices # return the shuffled list
def get_door(user_choice):
return user_choice.index(0)
def monty_sim(n, kind):
"""
:param n: number of runs in this simulation
:param kind: whether to change the door or not, 0 - don't change, 1 = change door
:return: (win_rate, 1 - win_rate)
"""
wins = 0
for i in range(0, n):
game_doors = get_choices()
user_choice = get_door(get_choices()) # use the same method and find user door choice
# so there are two branches.
# In both, a door with a goat (game_door = 1) is chosen, which reduce the result to
# a choice between two doors, rather than 3.
if kind == 0:
if user_choice == game_doors.index(0):
wins += 1
elif kind == 1:
# so now, the user chooses to change the door
if user_choice != game_doors.index(0):
wins += 1
# Because the original choice wasn't the right one, then the new
# must be correct because the host already chose the other wrong one.
win_rate = (wins / n) * 100
return win_rate, 100 - win_rate
if __name__ == '__main__':
n = 1000
kind = 1
wins, loses = monty_sim(n, kind)
print(f'In a simulation of {n} experiments, of type {kind} user won {wins:02f} of the time, lost {loses:02f} of the time')
So i'm making a genetic algorithm in python. The goal is for the "organism" to get to the top of the screen (x,20). I have a loop that creates the population which is a list of objects of type "Organism". Here is the code for the Organism class:
class Organism(object):
def __init__(self, genes,ID):
self.genes = genes
self.position = [0,0]
self.thisTime=str()
self.geneTranslation = []
self.ID=ID
def move(self,d):
if d == "f" or d == "forward":
self.position[1] += 1
elif d == "b" or d == "back":
self.position[1] -= 1
elif d == "r" or d == "right":
self.position[0] += 1
elif d == "l" or d == "left":
self.position[0] -= 1
print(self.position)
def isInContactWith(self,point):
point = list(point)
if self.position == point:
return True
else:
return False
def run(self):
for i in range(0,4):
if i == 0:
self.geneTranslation.extend(["f"] * self.genes[0])
elif i == 1:
self.geneTranslation.extend(["b"] * self.genes[1])
elif i == 2:
self.geneTranslation.extend(["r"] * self.genes[2])
elif i == 3:
self.geneTranslation.extend(["l"] * self.genes[3])
r.shuffle(self.geneTranslation)
for x in range(1,20):
self.thisTime = r.choice(self.geneTranslation)
self.move(self.thisTime)
As you can see, the genes specify the chance of a particular move. The problem is in the for loop that creates the population and runs it(ive added prints for debugging):
population = []
yValues={}
running = True
BestOrganism=Organism([25,25,25,25],0)
SecondOrganism=Organism([25,25,25,25],1)
for count in range(5):
for x in range(10):
a = lambda: r.randint(0, 3)
c = lambda: r.randint(-1, 1)
b = BestOrganism.genes
anOrganism = Organism(b,x)
anOrganism.genes[a()]+=c()
population.append(anOrganism)
for j in range(len(population)):
print("Organism " + str(population[j].ID) + str(population[j].genes))
population[j].run()
yValues[population[j].ID]=population[j].position[1]
if population[j].position[1]>=20:
print(population[j].genes)
running = False
break
BestOrganism=max(yValues)
for k in range(len(population)):
if population[k].ID==BestOrganism:
BestOrganism=population[k]
print(yValues[max(yValues)])
print(str(population)+"\n"+str(yValues)+"\n"+str(BestOrganism.genes))
population=[]
yValues={}
No errors pop up but, whenever I try to "mutate" a particular part of the organism's genes with anOrganism.genes[a()]=c(), it ends up mutating every organism in the list, even the ones not yet created, so that all of their genes are the exact same at the end (as seen in the final product). Why is python doing this?
It's because of this line: anOrganism = Organism(b,popPos).
So on the first iteration of the loop, you create an Organism and set the self.genes to b. Then you modify the .genes of that organism you just created.
When you iterate through the loop again, you are creating a new organism but with the same exact list, so it has the changes from the previous one.
Basically, there is only one b, and you are setting the .genes attribute of every organism to point to that single list. So any and everytime you change it, it changes for all of the organisms.
What you need to do is be sending in a copy of b to the constructor of Organism.
And then change the line anOrganism = Organism(b,popPos) to be
anOrganism = Organism(list(b), popPos)
The key is these lines:
b = BestOrganism.genes
anOrganism = Organism(b,popPos)
The list of genes will be shared by every organism created by that line. That is, anOrganism.genes is exactly the same object as BestOrganism.genes. So a change to BestOrganism.genes is seen in anOrganism.genes.
Python has an easy way to make a copy of a list, using "slicing". Change the line to this:
anOrganism = Organism(b[:],popPos)
Now anOrganism has its own genes, starting off identical to but still distinct from BestOrganism's genes.
Postscript:
Here is a simplified form, using literal ints instead of the random functions:
>>> class Organism(object):
... def __init__(self, genes, ID):
... self.genes = genes
... self.ID = ID
...
>>> zero = Organism([25,25,25,25],0)
>>> one = Organism(zero.genes, 1)
>>> two = Organism(zero.genes[:], 2)
>>> one.genes[2] += 5
>>> two.genes[3] += 7
>>> zero.genes
[25, 25, 30, 25]
>>> one.genes
[25, 25, 30, 25]
>>> two.genes
[25, 25, 25, 32]
>>>