Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Closed 6 years ago.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Improve this question
To start, sorry for the not-so-descriptive tittle, I really don't know how to call this problem, so let's start...
I have to designe an AI for a 4x4x4-4 in line game and we're using Monte Carlo method to do this AI, so basically I have to make a simulation of the posible moves of the computer n-times and determine which next move is the best posible, our professor gave us some base code to play a 4x4x4-4 in line game and we had to designe the AI so here is my method to simulate the AI:
EDIT1: Added full program.
from __future__ import print_function
import random
from copy import deepcopy
import time
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, 0, 0],
[0, 0, 0, 0]
],
[
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0]
]
]
p1_token = 1
p2_token = -1
draw_token = 0
pool = ThreadPool(processes=1)
def slice_winner(state_slice):
slice_size = len(state_slice)
sums = [sum(row) for row in state_slice]
sums.extend([sum([row[i] for row in state_slice]) for i in range(slice_size)])
if (p1_token * slice_size) in sums:
return p1_token
elif (p2_token * slice_size) in sums:
return p2_token
return 0
def winner(state):
for state_slice in state:
winner_in_slice = slice_winner(state_slice)
if winner_in_slice != draw_token:
return winner_in_slice
state_size = len(state)
for i in range(state_size):
state_slice = []
for j in range(state_size):
state_slice.append([state[j][i][k] for k in range(state_size)])
winner_in_slice = slice_winner(state_slice)
if winner_in_slice != draw_token:
return winner_in_slice
diagonals = [0, 0, 0, 0]
for i in range(state_size):
diagonals[0] += state[i][i][i]
diagonals[1] += state[state_size - 1 - i][i][i]
diagonals[2] += state[i][state_size - 1 - i][i]
diagonals[3] += state[state_size - 1 - i][state_size - 1 - i][i]
if (p1_token * state_size) in diagonals:
return p1_token
elif (p2_token * state_size) in diagonals:
return p2_token
return draw_token
def str_token(cell):
if cell == p1_token:
return "X"
elif cell == p2_token:
return "O"
return "."
def draw_board(state):
result = ""
state_size = len(state)
for y in range(state_size):
for z in range(state_size):
for x in range(state_size):
result += str_token(state[x][y][z]) + " "
result += "\t"
result += "\n"
return result
def isInVector(vector, x, y, z):
n = 0
while (n < len(vector)):
if (vector[n][0] == x and vector[n][1] == y and vector[n][2] == z):
return True
n += 1
return False
def getInVector(vector, x, y, z):
n = 0
while (n < len(vector)):
if (vector[n][0] == x and vector[n][1] == y and vector[n][2] == z):
return n
n += 1
return -1
def getBestPlay(vector):
max_value = -100000
index_of_max = -1
for i in range(len(vector)):
if (vector[i][3] > max_value):
max_value = vector[i][3]
index_of_max = i
return [vector[index_of_max][0], vector[index_of_max][1], vector[index_of_max][2]]
def AISim(main_state, p1x, p1y, p1z, maxIt):
n = 0 # Number of simulations
p2Moves = [] # A vector to hold player 2 moves.
while (n < maxIt): # While 1
x = p1x
y = p1y
z = p1z
player_turn = False # False because simulation will always start with player 2 turn
moves = 0
first_move = [0, 0, 0]
new_state = deepcopy(main_state)
while winner(new_state) == draw_token: # While 2
temp = new_state[x][y][z]
while temp != draw_token: # While 3
x = random.randint(0, 3)
y = random.randint(0, 3)
z = random.randint(0, 3)
temp = new_state[x][y][z]
# THIS IS THE PROBLEEEEEM!!!!
print (temp)
# END while 3
if (moves == 0):
first_move = [x, y, z]
if (not isInVector(p2Moves, x, y, z)):
p2Moves.append([x, y, z, 0])
# END if
# END if
new_state[x][y][z] = (1 if player_turn else -1)
player_turn = not player_turn
moves += 1
# END while 2
if (winner(new_state) == 1):
temPos = getInVector(p2Moves, first_move[0], first_move[1], first_move[2])
p2Moves[temPos][3] -= 1
else:
temPos = getInVector(p2Moves, first_move[0], first_move[1], first_move[2])
p2Moves[temPos][3] += 1
# END if-else
n += 1
# END while 1
return getBestPlay(p2Moves)
# --------------------------------------------------------------------------------------------------------
# ----------------------------------------- MAIN PROGRAM -------------------------------------------------
# --------------------------------------------------------------------------------------------------------
AIMove = [0, 0, 0]
player_1_turn = True
while winner(board) == draw_token:
# Print board state
print ("")
print ("Board:")
print (draw_board(board))
print ("")
# Print
print ("Player %s turn:" % (1 if player_1_turn else 2))
if (player_1_turn):
# Get input
x = int(raw_input("x: "))
y = int(raw_input("y: "))
z = int(raw_input("z: "))
else:
# Player 2 turn
start = time.time()
AIMove = AISim(board, x, y, z, 500)
end = time.time()
print ("Thinking time: %0.4f seconds" % (end - start))
x = AIMove[0]
print ("x:",x)
y = AIMove[1]
print ("y:",y)
z = AIMove[2]
print ("z:",z)
if board[x][y][z] == draw_token:
board[x][y][z] = 1 if player_1_turn else -1
player_1_turn = not player_1_turn
else:
print ("")
print ("ERROR: occupied position, please retry in a new position")
print ("")
print ("Player %s is the winner!" % (1 if winner(board) == 1 else 2))
And the code works I've test it many times and all, the problem is in the "While 3", for an unknown reason SOMETIMES the code may get stuck in a somewhat infinite loop regardless of the state of the board, like if there were no posible (x, y, z) coordinates that make the loop end, but I know there're! Because for the same unknown reason if I place a print (x, y, z) inside the loop, the AI work perfectly 100% of the times, but wait, there's more! As you might notice by printing (x, y, z) inside that loop make's the final output horrible, so I try print(x, y, z, end='\r) (I'm importing from __future__ import print_function) and it didn't work, the same weird behavior again, I've try so many things but the only solution seems to be printing the values I've been trying for hours and I need help, please!
You can test the program here.
My list of fail trys:
Save (x, y, z) in another array. It worked if I printed the vector...
Writing in an eternal file the coordinates, the coordinates were saved correctly, but it didn't fix it.
Assigning the random values generated to other variables and then those variables to the x, y and z.
Printing only 1 or 2 values, like x and z.
Swap x, y and z values.
EDIT2: Added a link to c9 so you can test it.
EDIT3: If you run it in your PC you might want to change the number of simulations, because printing over 1000 simulations might feel like it is infinite, but it isn't. Try printing like 100 or 300 simulations it might take a while but you'll see it working, then try like 1000 without printing(time should be the same since printing takes so much time) and you'll see it doesn't work.
EDIT4: Removed threading code.
UPDATE: I don't need this anymore for an assignment, I solve it in other way not using this code, but I really want to know what is happening and why does the print make's the program work or not.
P.S. Sorry again if it's somehow unclear what is happening, but I don't really know how to explain it better than this.
Related
I'm trying to do a game of life. There's this weird bug I can't really fix because I don't really know where the problem is? I'm guessing it's in the loop? I don't really know. I tried to debug it using the if total > 0 print(total), and the total is only 2 when it should've been 3. I'm sorry if i'm explaining it confusing because i'm also confused.
def test():
board = [[0, 0, 0, 0, 0],
[0, 0, 1, 0, 0],
[0, 0, 1, 0, 0],
[0, 0, 1, 0, 0],
[0, 0, 0, 0, 0]]
#Tracking the neighbor, it shows that there is 3 alive neighbors in
#here.
print(board[2][1])
print(board[2-1][1+1])
print(board[2][1+1])
print(board[2+1][1+1])
return board
def update(grid, N):
newGrid = grid.copy()
for i in range(N):
if i == 0 or i == 4:
continue
for j in range(N):
if j == 0 or j == 4:
continue
total = 0
total = total + grid[i][j-1] #
total = total + grid[i][j+1] #
total = total + grid[i-1][j] #
total = total + grid[i+1][j] #
total = total + grid[i-1][j-1] #
total = total + grid[i-1][j+1] #
total = total + grid[i+1][j-1] #
total = total + grid[i+1][j+1] #
# In here it only states that there's only 2 alive neighbors
# when there should've been 3
if total > 0:
print(total)
# apply Conway's rules
if grid[i][j] == 1:
if (total < 2) or (total > 3):
newGrid[i][j] = 0
elif total == 3:
newGrid[i][j] = 1
else:
if total == 3:
newGrid[i][j] = 1
grid[:] = newGrid[:]
return(grid)
f = 0
zboard = test()
while f <= 3:
print("Generation: " + str(f))
gen = update(zboard, 5)
for i in gen:
print(i)
f += 1
You need to use deepcopy.
When you do newGrid = grid.copy(), since you have a 2D-list, the sublists in newGrid will not be independent from the sublists from grid. Your problem was that grid was updated each time you updated newGrid.
You need to replace this:
newGrid = grid.copy()
by this :
import copy
newGrid = copy.deepcopy(grid)
Here is an example to show you what was happening. cop_1 is a dependent copy whereas cop_2 is an independent one :
board = [[0, 0],
[0, 0]]
cop_1 = board.copy()
import copy
cop_2 = copy.deepcopy(board)
board[0][0] = 3 # change a value of board
print("cop_1[0][0] =", cop_1[0][0])
# cop_1[0][0] = 3
print("cop_2[0][0] =", cop_2[0][0])
# cop_2[0][0] = 0
If you run the code like you posted, you get a mistake because you didn't indent the lines after your function def test(): until return board
I've been working on this leetcode problem, which is essentially finding the number of valid paths in a maze given some obstacleGrid matrix. If obstacleGrid[i][j] == 1, then we have an obstacle at (i,j) and we have zero otherwise, which a valid spot. We can only move down and right with the goal of starting from the upper left to the bottom right.
I have written the code below:
def uniquePathsWithObstacles(self, obstacleGrid):
# obstruction at the start
if (obstacleGrid[0][0] == 1): return 0
# obstruction at the end
if (obstacleGrid[-1][-1] == 1): return 0
m, n = len(obstacleGrid), len(obstacleGrid[0])
memo = [[0] * n] * m
# starting move
memo[0][0] = 1
# now check the first row
for j in range(1, n):
memo[0][j] = 1 if (obstacleGrid[0][j] == 0 and memo[0][j-1] != 0) else 0
# now check the first column
for i in range(1, m):
memo[i][0] = 1 if (obstacleGrid[i][0] == 0 and memo[i-1][0] != 0) else 0
# now check everything else
for i in range(1, m):
for j in range(1, n):
if (obstacleGrid[i][j] == 1): memo[i][j] = 0
else: memo[i][j] = memo[i-1][j] + memo[i][j-1]
return memo[-1][-1]
I took the obvious DP approach and I know the idea works but something is wrong with the code; for some reason I don't think my memo matrix is being updated properly? I feel like the problem is staring at me in the face but for some reason I can't see it. Any help appreciated!
Edit: For obstacleGrid = [[0,0,0],[0,1,0],[0,0,0]] and if I had a print(memo) right before the return statement, I get [[1, 1, 2], [1, 1, 2], [1, 1, 2]]. This happens to give me the right answer, but the memo matrix is wrong!
One problem lies in the line memo = [[0] * n] * m.
This does not really create mcopies of the same list, but instead, it only creates the [0] * n list once and then creates memo as a list of m references to this list. Any change to any of these lists therefore modifies all other lists!
You can try this yourself:
memo = [[0] * 3] * 4
memo[0][1] = 1
print(memo)
This gives [[0, 1, 0], [0, 1, 0], [0, 1, 0], [0, 1, 0]].
Instead, you have to initialize each list on their own, e.g.,
memo = []
for i in range(m):
memo.append([0] * n)
I just tried to do this with recursion as an comparison rather than an answer.
import numpy as np
def number_of_paths(obstacles):
"""
Calculate the number of paths available in a maze with obstacles, with only right and down moves, from top left
to bottom right.
Args:
obstacles (ndarray): binary matrix with 1 representing obstacle
Returns:
int: the number of paths
"""
if obstacles[0,0] == 1:
raise ValueError # cannot start on an obstacle
count = 0
if obstacles.shape == (2,1):
return 1
if obstacles.shape == (1,2):
return 1
if obstacles.shape[1] > 1 and obstacles[0,1] == 0:
count += number_of_paths(obstacles[:,1:])
if obstacles.shape[0] > 1 and obstacles[1,0] == 0:
count += number_of_paths(obstacles[1:,:])
return count
your code is correct and 1 line must be updated per the below:
def uniquePathsWithObstacles(self, obstacleGrid):
# obstruction at the start
if (obstacleGrid[0][0] == 1): return 0
# obstruction at the end
if (obstacleGrid[-1][-1] == 1): return 0
m, n = len(obstacleGrid), len(obstacleGrid[0])
memo = [[0] * n for i in range(m)]
# starting move
memo[0][0] = 1
# now check the first row
for j in range(1, n):
#memo[0][j] = 1 if (obstacleGrid[0][j] == 0 and memo[0][j-1] != 0) else 0
memo[0][j] = 1 if (obstacleGrid[0][j] == 0 and memo[0][j-1] != 0) else 0
# now check the first column
for i in range(1, m):
memo[i][0] = 1 if (obstacleGrid[i][0] == 0 and memo[i-1][0] != 0) else 0
# now check everything else
for i in range(1, m):
for j in range(1, n):
if (obstacleGrid[i][j] == 1): memo[i][j] = 0
else: memo[i][j] = memo[i-1][j] + memo[i][j-1]
return memo[-1][-1]
I'm building a game of Tic-Tac-Toe, and I have a vertical and horizontal check that look like this:
def check_win_left_vert (board):
win = True
x = 0
for y in range (2):
if board[y][x] != board[y+1][x]:
win = False
return win
It looks through the board by incrementing the y axis; I use the same method for the x axis. How would I do this for a diagonal axis? Would I increment both?
You would use the same variable for both on one diagonal, and "2 invert" it on the other:
for x in range(2):
if board[x][x] ...
for x in range(2):
if board[x][2-x] ...
Note that you have to watch out for boundary conditions. I strongly suspect that you haven't bothered to test your horizontal code yet, as it tries to check a space off the right edge of the board. Reduce the range to fix that.
You need to make in the same loop check for diagonal case
if board[y][y] != board[y+1][y+1] or board[2-y][y] != board[1-y][1+y]:
win = False
if win == False:
break;
All checks with list comprehensions
game_board = [ [1, 0, 1],
[0, 1, 0],
[0, 1, 0] ]
# Horizontals
h = [str(i+1) + ' Row' for i, v in enumerate(game_board) if sum(v) == 3]
# Verticals
v = [str(i+1) + ' Col' for i in range(3) if sum([j[i] for j in game_board]) == 3]
# Diagonals
d = [['Left Diag', '','Right Diag'][i+1] for i in [-1, 1] if sum([game_board[0][1+i], game_board[1][1]], game_board[2][1-i]) == 3]
if any([h,v,d]):
print('You won on:', h, v, d)
else:
print('No win yet')
import random
def lottery(lucky_numbers, run):
i = 0
while i < run:
x = random.uniform(0, 1) #prints out a random number between 0 and 1
numbers = lucky_numbers
NewNumbers = numbers[-1:] + numbers[:-1] #shifts each element in the to the right
lucky_numbers = NewNumbers
print(lucky_numbers, x)
i += 1
lottery([1, 2, 0], 3)
This code prints out something like:
>>>>>>>>>>
[0, 1, 2] 0.33016179294984127
[2, 0, 1] 0.7797639530009745
[1, 2, 0] 0.6292245916315391
>>>>>>>>>>
The x values will always be different because they are random numbers between 0 and 1.
I am trying to add a function that says if x is the lowest value(min) in the loop then the programme should print the list of that iteration, for example in this case the lowest value of x in this loop is 0.33016179.. , the program should therefore print the list [0, 1, 2]
I would just save the info in a variable and print it after the loop ends:
import random
def lottery(lucky_numbers, run):
i = 0
min_x = 1
while i < run:
x = random.uniform(0, 1) #prints out a random number between 0 and 1
numbers = lucky_numbers
NewNumbers = numbers[-1:] + numbers[:-1] #shifts each element in the to the right
lucky_numbers = NewNumbers
if x < min_x:
min_x = x
min_lucky_numbers = lucky_numbers
i += 1
print(min_lucky_numbers, min_x)
lottery([1, 2, 0], 3)
You can create a "cache" that stores all the x values then call the lowest value.
cache = []
for _ in range(3):
x = random.uniform(0, 1)
cache.append(x)
print min(cache)
to do what you want, you have just to store your items in two different lists, sort them and display the firt elements of each one :
import random
luckiest_num = list()
luckiest_list = list()
def lottery(lucky_numbers, run):
i = 0
while i < run:
x = random.uniform(0, 1)
numbers = lucky_numbers
NewNumbers = numbers[-1:] + numbers[:-1]
print(NewNumbers, x)
i += 1
luckiest_num.append(x)
luckiest_list.append(NewNumbers)
lottery([1, 2, 0], 3)
luckiest_num.sort()
luckiest_list.sort()
print ("The luckiest item is : ")
print(luckiest_num[0],luckiest_list[0])
I am trying to solve an exercise that requires me to write a function that takes as input an integer which then returns a list of tribonacci terms up until the input value. I have been "successful" for the most part but an extra term is output as well. This is my code:
def tribonacci(m):
tribs = [0, 0, 1]
if m == 0 or m == 1:
tribs = [0, 0]
elif m == 2:
tribs = [0, 0, 1]
else:
while tribs[-1] < m:
tribs.append(tribs[-1] + tribs[-3] + tribs[-2])
return tribs
I understand that the issue is the while loop which runs an extra iteration because the last element is still not greater than m. However, I can't see immediately how to fix this. I would resort to a while-else loop, but I'd like to see some other suggestions.
Just compare the term that is about to be genrated with m, like this:
def tribonacci(m):
tribs = [0, 0, 1]
if m == 0 or m == 1:
tribs = [0, 0]
elif m == 2:
tribs = [0, 0, 1]
else:
while tribs[-1] + tribs[-3] + tribs[-2] < m:
tribs.append(tribs[-1] + tribs[-3] + tribs[-2])
return tribs