My Problem is on line 25 when it says
if conformation == 1:
for i in range(l, len(lines[k]), 1):
if lines[k][i].isdigit() or lines[k][i].istitle():
f += lines[k][i]
if f in var:
print(var[f])
What my issue is is that the "f" string isn't being added to and its value stays as "". For context, I'm trying to make my own sort of mini programming language, and I'm trying to make prints read for variables. Every time it loops to set f to the variable name, nothing happens. The only way I get remotely close to finding the variable name is by doing "print(lines[k][i])" before the "if lines[k][i]" condition.
Note: I was using a debugger, and I'm not sure if the "if f in var" condition is even being checked.
Python code that reads my custom programming language:
⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄
code = open("HelloWorld.sabo", 'r')
lines = code.readlines()
var = {}
for k in range(0, len(lines), 1):
conformation = 0
temp = ""
temp2 = ""
if lines[k][0:5] == "print":
r = 0
l = 0
p = False
f = ""
for i in lines[k]:
r += 1
if not p:
l += 1
if i == "(":
p = True
conformation += 1
if i == "\"" and conformation == 1:
conformation += 1
if conformation == 2:
break
if conformation == 1:
for i in range(l, len(lines[k]), 1):
if lines[k][i].isdigit() or lines[k][i].istitle():
f += lines[k][i]
if f in var:
print(var[f])
if conformation == 2:
for i in range(r, len(lines[k]), 1):
if not lines[k][i] == "\"":
f += lines[k][i]
else:
break
print(f)
elif lines[k][0:4] == "var ":
for i in range(4, len(lines[k]), 1):
if not lines[k][i] == " ":
temp += lines[k][i]
else: break
for i in range(4, len(lines[k])):
if lines[k][i] == "=":
conformation = 1
elif conformation == 1:
if not lines[k][i] == " ":
temp2 += lines[k][i]
elif not temp2 == "":
break
var[temp] = temp2.strip()
Code that is being read by the above script:
⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄
var val = hello
print(val)
So, I was being a bit dumb with this, but I found out that if I just account for Uppercase and Lowercase characters, then it will work.
if lines[k][i].islower() or lines[k][i].isdigit() or lines[k][i].isnumeric() or lines[k][i].istitle():
f += lines[k][i]
I might have gone overboard with the security though I'm just not sure about the difference isdigit and isnumeric.
This question already has answers here:
Why Python recursive function returns None [duplicate]
(1 answer)
Recursive function does not return specified value
(2 answers)
Closed 1 year ago.
I have written a maze solver program. I want the PathFinder function to return True if a path is found and then print the path or else simply return False. But my program always keeps returning False even if a path is found. It would be great if you guys can help me figure this out.
def findPaths(m,path,i,j):
r,c = len(m), len(m[0])
if i == r-1 and j == c-1:
print(path)
return True
#explore
path.append(m[i][j])
# move down
if i != r-1 and m[i+1][j] == '↓ ':
findPaths(m,path,i+2,j)
#move up
if i < 0 and m[i-1][j] == '↑ ':
findPaths(m,path,i-2,j)
#move right
if j != c-1 and m[i][j+1] == '→':
findPaths(m,path,i,j+2)
#move left
if j > 0 and m[i][j-1] == '←':
findPaths(m,path,i,j-2)
path.pop()
def maze(r,c):
m = []
for i in range(r):
row = []
for j in range(1, c + (c)):
rand_num = str(randint(1, 99))
if j % 2 != 0:
if len(rand_num) == 1:
row.append(' ' + rand_num)
else:
row.append(rand_num)
else:
row.append('?')
m.append(row)
up_left_count = r * c // 3
down_right_count = r * c * 2 // 3
for v in range(r + (r - 1)):
vertical_lst = []
for each in range(1, c + c):
if each % 2 == 0:
vertical_lst.append(' ')
else:
vertical_lst.append('? ')
if v % 2 != 0:
m.insert(v, vertical_lst)
idx_i = []
idx_j = []
idx_v_i = []
idx_v_j = []
for i in range(len(m)):
for j in range(len(m[0])):
if i % 2 == 0 and j % 2 != 0:
idx_i.append(i)
idx_j.append(j)
for v_i in range(len(m)):
for v_j in range(len(m[0])):
if v_i % 2 != 0 and v_j % 2 == 0:
idx_v_i.append(v_i)
idx_v_j.append(v_j)
idx_i = list(set(idx_i))
idx_j = list(set(idx_j))
idx_v_i = list(set(idx_v_i))
idx_v_j = list(set(idx_v_j))
for count in range(up_left_count):
i_int = randint(0, len(idx_i) - 1)
j_int = randint(0, len(idx_j) - 1)
if m[i_int][j_int] != '←':
m[idx_i[i_int]][idx_j[j_int]] = '←'
for count_v in range(up_left_count):
i_v_int = randint(0, len(idx_v_i) - 1)
j_v_int = randint(0, len(idx_v_j) - 1)
if m[i_v_int][j_v_int] != '↑':
m[idx_v_i[i_v_int]][idx_v_j[j_v_int]] = '↑ '
for i in range(len(m)):
for j in range(len(m[0])):
if i % 2 == 0 and j % 2 != 0:
if m[i][j] == '?':
m[i][j] = '→'
for i in range(len(m)):
for j in range(len(m[0])):
if i % 2 != 0 and j % 2 == 0:
if m[i][j] != '↑ ':
m[i][j] = '↓ '
m[0][0] = "S"
m[-1][-1] = "D"
for i in range(len(m)):
for j in range(len(m[0])):
print(m[i][j], end=" ")
print()
path = []
return findPaths(m, path, 0,0)
if maze(5,6):
print('True')
else:
print('False')
I have imported a text file with numbers as the following example:
3 0 0 0 0 1 0 0 3 3 3 0 3 0 0 0 0 0 3 3 3 0 3 0 0 0 0 0 3 3 3 0 3 0 0 0 0 0 3 3 3 0 3 0 0 0 0 0 3 3 3 0 3 0 0 0 0 2 3 3 3 0 3 0 0 0 0 3 3 3 3 0 3 0 0 0 0 3 3 3 3 0 3 2 2 0 0 3 3 3 3 3 3 3 3 2 0 3 3 3
The goal is to read in the text file, format it as a grid (i.e a 10 by 10 grid) which I am able to do, and then sort through the list of lists to reach the solution where the number 3 is an obstacle, number 1 is start point and number 2 is the solution, I am attempting to use a BFS algorithm where the agent can move UP, DOWN, LEFT, RIGHT.
I am trying to print the sequence of steps that is taken to reach the closest solution (i.e 2) from the beginning point(i.e 1). The numbers are formatted as strings/ text. The program I have written seems to be running but it never prints a solution or terminates. The move sequence that is to be printed as a solutions is in the format of:
'Move Down'
'Move UP'
ETC. where each move is on a newline
I am attaching my code below and any help that can be offered would be greatly appreciated
import queue
def read_user_input():
file_name = input('Enter the name of your file :\n')
return file_name
def read_to_grid():
file_name = read_user_input()
for nums in open(file_name):
line = list(nums.split())
result = []
for _ in range(0, len(line), 10):
result.append(line[_:_ + 10])
return result
file_name.close()
def print_grid(result, path=''):
for x, pos in enumerate(result[0]):
if pos == '0':
start = x
i = start
j = 0
pos = set()
for move in path:
if move == 'Move Left':
i -= 1
elif move == 'Move Right':
i += 1
elif move == 'Move Up':
j -= 1
elif move == 'Move Down':
j += 1
pos.add((j, i))
for j, row in enumerate(result):
for i, col in enumerate(row):
if (j, i) in pos:
print('#', end='')
else:
print(col + ' ', end='')
print()
def valid(result, moves):
for x, pos in enumerate(result[0]):
if pos == '0':
start = x
i = start
j = 0
for move in moves:
if move == 'Move Left':
i -= 1
elif move == 'Move Right':
i += 1
elif move == 'Move Up':
j -= 1
elif move == 'Move Down':
j += 1
if not (0 <= i < len(result[0]) and 0 <= j < len(result)):
return False
elif (result[i][j] == '3'):
return False
return True
def find_goal(result, moves):
for x, pos in enumerate(result[0]):
if pos == '0':
start = x
i = start
j = 0
for move in moves:
if move == 'Move Left':
i -= 1
elif move == 'Move Right':
i += 1
elif move == 'Move Up':
j -= 1
elif move == 'Move Down':
j += 1
if result[j][i] == '2':
print('Found: ' + moves)
print_grid(result, moves)
return True
return False
nums = queue.Queue()
nums.put('')
add = ''
result = read_to_grid()
while not find_goal(result, add):
add = nums.get()
for j in ['Move Left', 'Move Right', 'Move Up', 'Move Down']:
put = add + j
if valid(result, put):
nums.put(put)
Ok Ryan answer already says everything, here however is your code working though is not efficient in anyway, the only things I changed that is worth is that instead of using a list of list you can just use a list, and the valid function now check the traveled path so that it can know where it has been so it won't loop.
import queue
# Read name file from user
def read_user_input():
file_name = input('Enter the name of your file :\n')
return file_name
# Read file and return list of list[10]
def read_to_grid():
with open(read_user_input()) as file:
for nums in file:
line = list(nums.split())
return line
# Shows a text grid
def print_grid(result, path=[]):
for x, pos in enumerate(result):
if pos == '1':
start = x
i = start
#j = 0
pos = set()
for move in path:
if move == 'Move Left':
i -= 1
elif move == 'Move Right':
i += 1
elif move == 'Move Up':
i -= 10
elif move == 'Move Down':
i += 10
pos.add(i)
for i, celd in enumerate(result):
if i % 10 == 0:
print()
if i in pos:
print('# ', end='')
else:
print(celd + ' ', end='')
# Validates coordinates and traveled path
def valid(result, moves):
for x, pos in enumerate(result):
if pos == '1':
start = x
i = start % 10
j = start // 10
# Where we start
travel = [(j,i)]
for move in moves:
if move == 'Move Left':
i -= 1
elif move == 'Move Right':
i += 1
elif move == 'Move Up':
j -= 1
elif move == 'Move Down':
j += 1
# Check if we have already been there
if (j, i) in travel:
return False
else:
travel += [(j,i)]
# Check coordinates
if i >= 10 or i < 0 or j >= len(result) // 10 or j < 0:
return False
elif result[i+j*10] == '3':
return False
return True
# Return true if 2 is reached
def find_goal(result, moves):
for x, pos in enumerate(result):
if pos == '1':
start = x
i = start
#j = 0
for move in moves:
if move == 'Move Left':
i -= 1
elif move == 'Move Right':
i += 1
elif move == 'Move Up':
i -= 10
elif move == 'Move Down':
i += 10
if result[i] == '2':
print('Found: ',' '.join(moves))
print_grid(result, moves[0:-1])
return True
return False
nums = queue.Queue()
result = read_to_grid()
add = []
while not find_goal(result, add):
if not nums.empty():
add = nums.get()
for j in ['Move Left', 'Move Right', 'Move Up', 'Move Down']:
put = add + [j]
if valid(result, put):
nums.put(put)
EDIT:
I cleaned up a little:
import queue
# Read name file from user
def read_user_input():
file_name = input('Enter the name of your file :\n')
return file_name
# Read file and return list of list[10]
def read_to_grid():
with open(read_user_input()) as file:
for nums in file:
line = list(nums.split())
return line
# Shows a text grid
def print_grid(result, path=[]):
pos = set()
for (x,y), _ in path:
i = x + y*10
pos.add(i)
for i, celd in enumerate(result):
if i % 10 == 0:
print()
if i in pos:
print('# ', end='')
else:
print(celd + ' ', end='')
# Validates coordinates and traveled path
def valid(result, moves):
# Unpack
(i,j), _ = moves[-1]
# Check if already traveled
if any(x == i and y == j for (x,y), __ in moves[:-1]):
return False
# Check coordinates
if i >= 10 or i < 0 or j >= len(result) // 10 or j < 0:
return False
elif result[i+j*10] == '3':
return False
return True
# Return true if 2 is reached
def find_goal(result, moves):
# Unpack
(i,j), _ = moves[-1]
if result[i+j*10] == '2':
#Print moves
output = 'Found: '
for (x,y), _ in moves:
output += " "+_
print(output)
#Print grid
print_grid(result, moves[1:-1])
return True
return False
# Return new position and which movement was done.
def move(pos, dir):
(x, y), _ = pos
if dir == 'Move Left':
x -= 1
elif dir == 'Move Right':
x += 1
elif dir == 'Move Up':
y -= 1
elif dir == 'Move Down':
y += 1
return (x, y), dir
nums = queue.Queue()
result = read_to_grid()
# Find the starting position
for x, pos in enumerate(result):
if pos == '1':
start = x
add = [((start % 10, start // 10),'')]
while not find_goal(result, add):
if not nums.empty():
add = nums.get()
for j in ['Move Left', 'Move Right', 'Move Up', 'Move Down']:
put = add + [move(add[-1],j)]
if valid(result, put):
nums.put(put)
Whilst debugging your code I ran into some endless loops and other bugs when it came to your 'valid' and 'find_goal' functions.
In my experience with breadth first search its best to treat each point as a node (coordinates in this case) and to have your queue consist of lists of paths that are currently being tried. Where each path is a list of each node thats transversed. Typically you don't want to visit the same node more than once in a given path so you'll have to keep track of this information rather than soley 'left', 'right', etc...
All that said, I built-off your code and created a function that would return the valid adjacent nodes when given a node accounting for grid bound, not being a 3 and wether the node has been visited or not. Then for the BFS part the queue starts with a list containing the starting node (I made a function to find where the 1 was). Then while a queue exists the BFS will pop off the current path, get the last node in that path, find all valid adjacent nodes. With each valid adjacent node a new path entry will be added to the queue consisting of the old path + the adjacent node. If one of the adjacent nodes is a goal it will end the search and return the path. I've included the directional information in the path so that you can parse that out.
This should print off a path to the nearest 2 as such:
[((5, 0), ''), ((5, 1), 'Down'), ((6, 1), 'Right'), ((6, 2), 'Down'), ((7, 2), 'Right'), ((7, 3), 'Down'), ((7, 4), 'Down'), ((7, 5), 'Down')]
You'll see the ...sorted(path_queue, key=lambda... that line isn't needed but is a lazy way to prioritize the queue, always trying the shortest current path. If you remove it you'll see you still get a valid path but its much longer.
def read_user_input():
file_name = input('Enter the name of your file :\n')
return file_name
def read_to_grid():
file_name = read_user_input()
for nums in open(file_name):
line = list(nums.split())
result = []
for _ in range(0, len(line), 10):
result.append(line[_:_ + 10])
int_result = []
for i, row in enumerate(result):
int_result.append([])
for col in row:
int_result[i].append(int(col))
return int_result
def print_grid(result, path=''):
for x, pos in enumerate(result[0]):
if pos == 0:
start = x
i = start
j = 0
pos = set()
for move in path:
if move == 'Move Left':
i -= 1
elif move == 'Move Right':
i += 1
elif move == 'Move Up':
j -= 1
elif move == 'Move Down':
j += 1
pos.add((j, i))
for j, row in enumerate(result):
for i, col in enumerate(row):
if (j, i) in pos:
print('#', end='')
else:
print(str(col) + ' ', end='')
print()
def find_start_node(grid):
for i, row in enumerate(grid):
if 1 in row:
return ((row.index(1), i), '')
return (None, None)
def valid_adj(cur_node, grid, visited):
x = cur_node[0][0]
y = cur_node[0][1]
adj = []
if ((y + 1) < 10) and (grid[y + 1][x] != 3) and not (any((x, y + 1) in node for node in visited)):
adj.append(((x, y + 1), 'Down'))
if ((x + 1) < 10) and (grid[y][x + 1] != 3) and not (any((x + 1, y) in node for node in visited)):
adj.append(((x + 1, y), 'Right'))
if ((y - 1) >= 0) and (grid[y - 1][x] != 3) and not (any((x, y - 1) in node for node in visited)):
adj.append(((x, y - 1), 'Up'))
if ((x - 1) >= 0) and (grid[y][x - 1] != 3) and not (any((x - 1, y) in node for node in visited)):
adj.append(((x - 1, y), "Left"))
return adj
def BFS(grid):
start_node = find_start_node(grid)
path_queue = [[start_node]]
while path_queue:
path_queue = sorted(path_queue, key=lambda x: len(x), reverse=True) # More optimized to guarantee shortest path, not needed
cur_path = path_queue.pop()
cur_node = cur_path[-1]
if cur_node not in cur_path[:].pop():
adj = valid_adj(cur_node, grid, cur_path)
for node in adj:
new_path = list(cur_path)
new_path.append(node)
path_queue.append(new_path)
if grid[node[0][1]][node[0][0]] == 2:
print('path found')
return new_path
return -1
grid = read_to_grid()
print_grid(grid)
print(BFS(grid))
I'm making an isWin function that checks if there is a character that appears 5 consecutive times (either horizontally, vertically or diagonally).
I've tried using this code:
#VERTICAL WIN
count = 0
for row in range(1,grid_height):
print(row)
for col in range(1,grid_width):
print(col)
if grid[row][col-2] == p_char:
count += 1
if count == 5:
return True
else:
count = 0
continue
#HORIZONAL WIN
count=0
for col in range(0,grid_width):
for row in range(0,grid_height):
if grid[row][col-2] == p_char:
count += 1
if count == 5:
return True
else:
count = 0
continue
And this is where i place it in my main program:
def play():
grid,grid_height,grid_width,p1_name,p1_char,p2_name,p2_char=getGameSettings()
displayGrid(grid,grid_height,grid_width)
print('WELCOME TO THE GAME!')
playerA = Player(p1_name, PLAYING)
playerB = Player(p2_name, WAITING)
grid=[]
for row in range(grid_height): # FOR ROW
z =[]
for col in range(grid_width): # FOR COLUMN
z.append(" ")
grid.append(z)
numColFull = 0
turn=0
while turn < grid_height*grid_width:
player = playerA
if turn % 2 == 0 : #IF TURN IS AN ODD NUMBER, THEN IT IS player 1's turn, IF TURN IS EVEN, THEN IT IS player 2's turn
p_char= p1_char
player = playerA
playerA.setState(PLAYING)
playerB.setState(WAITING)
else :
p_char= p2_char
player = playerB
playerB.setState(PLAYING)
playerA.setState(WAITING)
print(".................................................. ")
print("User to play : ", player.playerInfo() , " SEQ : ", str(turn)) # TO COUNT THE TOTAL NUMBER OF MOVES
print(".................................................. ")
if numColFull == grid_width: #THE isDRAW function but embedded into the main function
# IF the numColFull is equal to gridwidth, it means that all of the columns has been occupied, meaning
#that every space has already been occupied, thus, game is over.
print('........All spaces had been occupied...........')
print('................THE GAME IS DRAW...............')
print('.................GAME OVER.....................')
break
else:
while True:
try:
move=int(input('Enter your move: '))
except ValueError:
print('Please enter a valid input.')
if move < 1 or move > grid_width:
print('Please enter a valid input.')
continue
break
updateGrid(grid,grid_height-1,grid_width,move,p_char)
while True:
if grid[0][move-2] == p_char: #IF THE TOP ROW OF A COLUMN HAS A PIECE IN IT, IT MEANS ITS ALREADY FULL
displayGrid(grid,grid_height, grid_width)
print('Column is full. Please choose another column for the next move.')
numColFull += 1
break
elif isWin == True: #IF THE IF CONDITION DIDNT HOLD TRUE, THEN THE FUNCTION CONTINUES AS USUAL
print(player, 'WINS!!!')
('.................GAME OVER.....................')
else:
displayGrid(grid,grid_height, grid_width)
break #GOES BACK TO THE THE WHILE CONDITION
turn += 1 #INCREMENTS 1 TO TURN SO IT WILL SWITCH BETWEEN BEING ODD AND EVEN
And this is my grid:
def displayGrid(grid,grid_height,grid_width):
for row in range(1,grid_height):
#print(row) #for checking
for col in range(grid_width):
print("|", end="")
print(str(grid[row-1][col-1]),end = "")
print("|")
print(" "+" ".join([str(i) for i in range(1, grid_width+1)]))
return grid
def updateGrid(grid,grid_height,grid_width,move,p_char):
for i in range(1,grid_height+1):
print(i)
#print(i) #ROW COUNTING STARTS FROM 1
if grid[grid_height-i][move-2] == " ":
grid[grid_height-i][move-2]= p_char #REPLACES THE " " TO THE CURRENT PLAYER'S CHARACTER (p_char)
else:
continue
break
return grid
I guess you are writing Five In a Row? But anyway, this code should work:
def isWin():
# Horizontal
for i in range(grid_height):
for j in range(grid_width - 4):
if set(grid[i][j:j+5]) == {p_char}:
return True
# Vertical
for i in range(grid_height - 4):
for j in range(grid_width):
if { grid[i+k][j] for k in range(5) } == {p_char}:
return True
# Diagonal
for i in range(grid_height - 4):
for j in range(grid_width - 4):
if { grid[i+k][j+k] for k in range(5) } == {p_char}:
return True
return False
# Simplified
def isWin():
return any(set(grid[i][j:j+5]) == {p_char} for i in range(grid_height) for j in range(grid_width - 4)) or \
any({ grid[i+k][j] for k in range(5) } == {p_char} for i in range(grid_height - 4) for j in range(grid_width)) or \
any({ grid[j+k][i+k] for k in range(5) } == {p_char} for i in range(grid_width - 4) for j in range(grid_width - 4))
Since set cannot have duplicates, using expressions like { grid[j+k][i+k] for k in range(5) } will put 5 consecutive pieces into a set. If there are 5 consecutive p_chars, then the set will become {p_char}.