python maze recurrsion not recurssing - python

I'm trying to solve a maze recursively and I can get it to go where I want it to (check to make sure it can go a way and then to mark it as been there) but for some reason when it runs into a dead end, it does not recursively go back to an open place to check another path. Is there anything wrong with the way I'm using recursion?
class maze(object):
def __init__(self, maze):
self.maze = maze
self.maze2d = []
n = 0
i = 0
for row in self.maze:
self.maze2d.append([])
print(row)
for col in row:
self.maze2d[i].append(col)
i += 1
print(self.maze2d)
def find_start(self):
x = 0
y = 0
for row in self.maze2d:
for index in row:
if index == "S":
self.maze2d[x][y] = index
return x,y
y += 1
x += 1
y = 0
return -1
def mazeSolver(self,x,y,path):
if self.maze2d[x][y] == "E":
return True
else:
if self.maze2d[x] != 0:
if self.maze2d[x+1][y] == ".":
self.maze2d[x+1][y] = "_"
self.mazeSolver(x+1,y,path + "S")
if self.maze2d[x] < len(self.maze2d):
if self.maze2d[x-1][y] == ".":
self.maze2d[x-1][y] = "_"
self.mazeSolver(x-1,y,path + "N")
if y < len(self.maze2d[x]):
if self.maze2d[x][y+1] == ".":
self.maze2d[x][y+1] = "_"
self.mazeSolver(x,y+1,path + "E")
if self.maze2d[y] != 0:
if self.maze2d[x][y-y] == ".":
self.maze2d[x][y-1] = "_"
self.mazeSolver(x,y-1,path + "W")
and where I'm calling the function and the maze itself:
from eachstep import *
maze1 = []
maze1.append("S..*..")
maze1.append("*...*.")
maze1.append("..*..E")
var1 = maze(maze1)
x,y = var1.find_start()
var1.mazeSolver(x,y,"")

I changed your mazeSolver function with this. And I print the path at the end:
def mazeSolver(self,x,y,path):
if self.maze2d[x][y] == '.':
self.maze2d[x][y] = "_"
if self.maze2d[x][y] == "E":
print path
return True
else:
if x < len(self.maze2d)-1:
if self.maze2d[x+1][y] in ['.','E']:
self.mazeSolver(x+1,y,path + "S")
if x > 0:
if self.maze2d[x-1][y] in ['.','E']:
self.mazeSolver(x-1,y,path + "N")
if y < len(var1.maze2d[x])-1:
if self.maze2d[x][y+1] in ['.','E']:
self.mazeSolver(x,y+1,path + "E")
if y > 0:
if self.maze2d[x][y-y] in ['.','E']:
self.mazeSolver(x,y-1,path + "W")
>>> var1.mazeSolver(x,y,"")
ESEESEE
>>>> var1.maze2d
[['S', '_', '_', '*', '.', '.'],
['*', '_', '_', '_', '*', '.'],
['_', '_', '*', '_', '_', 'E']]

Your code will never reach the end, since it only visits locations with the value ., and the end has the value E.

Related

How to handle or detect when a maze has no solution?

I am trying to make maze solver in python.
The parameters are as follows
y (int): Start location of y
x (int): Start location of x
The starting point is (y,x), The coordinates for the left-top, left-bottom, right-top, and right-bottom are (0,0), (N,0), (0,N), (N,N), respectively, for the maze map of size N by N.
The search function return (bool): If maze has solution or not, return True or False respectively.
The solve function returns nothing: Print out a single path solution.
I have managed to write the code and get solutions for the maze, but I have a problem when the maze has no solution. It does not stop and just goes on running infinite loops.
Below is my code
class Maze():
def __init__(self, grid):
self.grid = grid
def search(self, y, x):
self.y = y
self.x = x
if x == len(self.grid[0]) or y == len(self.grid):
print('out of maze')
return False
if self.grid[y][x] == 'F':
self.cleanup()
return True
if self.grid[y][x] != 'o' and self.grid[y][x] != ' ':
print('ran into a wall')
return False
self.grid[y][x] = ' '
if x <= len(self.grid[0])-2:
if self.grid[y][x+1] == 'o' or self.grid[y][x+1] == 'F':
print(x,y)
return self.search(y,x+1)
if y <= len(self.grid)-2:
if self.grid[y+1][x] == 'o' or self.grid[y+1][x] == 'F':
print(x,y)
return self.search(y+1,x)
if x > 1:
if self.grid[y][x-1] == 'o' or self.grid[y][x-1] == 'F':
print(x,y)
return self.search(y,x-1)
if y > 1:
if self.grid[y-1][x] == 'o' or self.grid[y-1][x] == 'F':
print(x,y)
return self.search(y-1,x)
if x > 1:
if self.grid[y][x-1] == ' ' or self.grid[y][x-1] == 'F':
print(x,y)
return self.search(y,x-1)
if y > 1:
if self.grid[y-1][x] == ' ' or self.grid[y-1][x] == 'F':
print(x,y)
return self.search(y-1,x)
if x <= len(self.grid[0])-2:
if self.grid[y][x+1] == ' ' or self.grid[y][x+1] == 'F':
print(x,y)
return self.search(y,x+1)
if y <= len(self.grid)-2:
if self.grid[y+1][x] == ' ' or self.grid[y+1][x] == 'F':
print(x,y)
return self.search(y+1,x)
print("can't find a way")
return False
def cleanup(self):
for r in range(len(self.grid)):
for c in range(len(self.grid[0])):
if self.grid[r][c] == ' ':
self.grid[r][c] = 'o'
def solve(self, y, x):
if self.search(y, x):
print("Solution")
### CODE HERE ###
else:
print('There are NO solutions')
This is my main
for i, maze_map in enumerate(maze_map_list):
maze = Maze(maze_map)
print(i+1, '-1')
maze.solve(0,0)
print(i+1, '-2')
maze.solve(4,0)
print()
and this is the grid that I am unable to work on
.
.
grid2 = ['o o o o o o'.split(' '),
'+ + o + + +'.split(' '),
'F + o o o o'.split(' '),
'o o + + + o'.split(' '),
'o o o + + o'.split(' ')]
.
.
.
maze_map_list = [grid1, grid2, grid3, grid4]

I am trying to append an arithmetic operation list into another empty list and returning the list

I want to append an arithmetic operation string into another list by splitting every numbers and operators. when i append 3.1 it becomes 3.0 then 1.0 instead.
I added float
def tokenization(expr):
opr = ["+", "-", "*", "/", "^","(",")"]
tokens = []
for char in expr:
if char.isdigit():
tokens.append(float(char)
if char == '':
continue
if char in opr:
tokens.append(char)
return tokens
Code:
def tokenization(expr):
opr = ["+", "-", "*", "/", "^", "(", ")"]
tokens = []
digit_readed, dot_readed, zero_readed = 0, 0, 0
for idx, char in enumerate(expr):
if char == " ":
digit_readed, dot_readed, zero_readed = 0, 0, 0
elif char in opr:
tokens.append(char)
digit_readed, dot_readed, zero_readed = 0, 0, 0
else:
if char.isdigit():
digit_readed += 1
if char == "0":
zero_readed += 1
if dot_readed > 0:
continue
elif char == "." and digit_readed > 0:
dot_readed += 1
zero_readed, digit_readed = 0, 0
continue
else:
raise ValueError("Unexpected '{}' on {} symbol".format(char, idx + 1))
if dot_readed == 1:
tmp = (str(round(tokens[-1])) + "." if digit_readed == zero_readed + 1 else str(tokens[-1])) + \
"0" * zero_readed
tokens[-1] = float(tmp + char)
zero_readed = 0
elif digit_readed == 1:
tokens.append(float(char))
elif digit_readed > 1:
tokens[-1] = float(str(round(tokens[-1])) + char)
return tokens
print(tokenization("(3.1 + 6*2^2) * (2 - 1)"))
Result:
['(', 3.1, '+', 6.0, '*', 2.0, '^', 2.0, ')', '*', '(', 2.0, '-', 1.0, ')']

Basic Tic Tac Toe Game: Somehow, when I call a function in a different file, that function changes a list in the original file

main.py:
import ai
import utility
def main(): # {
# Main Loop Variables
win_condition = '*'
player_turn = True
turn = 0
board_state = [['*', '*', '*'],
['*', '*', '*'],
['*', '*', '*']]
# Start of Main Turn Loop
while (win_condition == '*') and (turn <= 9):
turn += 1
print('Turn: ', turn)
player_input = 0
for y in range(3): # Prints Board
print(board_state[y][0] + board_state[y][1] + board_state[y][2])
if player_turn: # Player Moves
player_turn = not player_turn
player_input = int(input("Enter 1, 2, 3...9")) - 1
board_state[int(player_input) // 3][int(player_input) % 3] = 'X'
else: # Computer moves
print('Thinking...')
player_turn = not player_turn
ai_move = ai.random(board_state)
print(utility.list_possible_states(board_state))
print(board_state)
board_state[int(ai_move) // 3][int(ai_move) % 3] = 'O'
win_condition = utility.test_for_win(board_state)
# }
main()
ai.py:
import utility
from random import randrange
def random(board_state):
possible_moves = utility.list_possible_moves(board_state)
return possible_moves[randrange(len(possible_moves))]
utility.py:
def test_for_win(test_board): # {
return_value = '*'
for y in range(3): # Tests for horizontal win.
test_set = set(test_board[y])
if len(test_set) == 1 and not ('*' in test_set):
print("The winner is " + test_board[y][1])
return_value = test_board[y][1]
break
for x in range(3): # Tests for vertical win.
test_list = []
for y in range(3):
test_list.append(test_board[y][x])
test_set = set(test_list)
if (len(test_set) == 1) and not ('*' in test_set):
print("The winner is " + test_board[1][x])
return_value = test_board[1][x]
break
test_list = []
for xy in range(3): # Tests for diagnoal win (-)
test_list.append(test_board[xy][xy])
# print(test_list, len(test_list)) #Debugging
if (len(set(test_list)) == 1) and not ('*' in test_list):
print("The winner is " + test_board[1][1])
return_value = test_board[1][1]
test_list = []
for xy in range(3): # Tests for diagnoal win (+)
test_list.append(test_board[xy][2 - xy])
# print(test_list, len(test_list)) #Debugging
if (len(set(test_list)) == 1) and not ('*' in test_list):
print("The winner is " + test_board[1][1])
return_value = test_board[1][1]
return return_value
# }
def list_possible_moves(board): # {
possible_moves = []
for move_counter in range(9): # Prints Possible Moves to List
if board[move_counter // 3][move_counter % 3] == '*':
possible_moves.append(move_counter)
return possible_moves
# }
def list_possible_states(board): # {
possible_moves = list_possible_moves(board)
xoro = '*'
if (len(possible_moves)) % 2 == 0:
xoro = 'O'
else:
xoro = 'X'
possible_states = []
for move in possible_moves:
board_s = board
board_s[move // 3][move % 3] = xoro
possible_states.append(board_s)
del board_s
return possible_states
# }
If I comment out this print statement in main.py:
print(utility.list_possible_states(board_state))
This prints out:
[['X', '*', '*'], ['*', '*', '*'], ['*', '*', '*']]
But if I don't comment out that line it prints out:
[['X', 'O', 'O'], ['O', 'O', 'O'], ['O', 'O', 'O']]
How is the variable board_state being changed in the function main() from the function list_possible_states()? And if you have any suggestions / see any major errors don't hesitate to bring them up as well.
*edit to utility.py{
import copy
def test_for_win(test_board): # {
return_value = '*'
for y in range(3): # Tests for horizontal win.
test_set = set(test_board[y])
if len(test_set) == 1 and not ('*' in test_set):
print("The winner is " + test_board[y][1])
return_value = test_board[y][1]
break
for x in range(3): # Tests for vertical win.
test_list = []
for y in range(3):
test_list.append(test_board[y][x])
test_set = set(test_list)
if (len(test_set) == 1) and not ('*' in test_set):
print("The winner is " + test_board[1][x])
return_value = test_board[1][x]
break
test_list = []
for xy in range(3): # Tests for diagnoal win (-)
test_list.append(test_board[xy][xy])
# print(test_list, len(test_list)) #Debugging
if (len(set(test_list)) == 1) and not ('*' in test_list):
print("The winner is " + test_board[1][1])
return_value = test_board[1][1]
test_list = []
for xy in range(3): # Tests for diagnoal win (+)
test_list.append(test_board[xy][2 - xy])
# print(test_list, len(test_list)) #Debugging
if (len(set(test_list)) == 1) and not ('*' in test_list):
print("The winner is " + test_board[1][1])
return_value = test_board[1][1]
return return_value
# }
def list_possible_moves(board): # {
testtest = copy.copy(board)
possible_moves = []
for move_counter in range(9): # Prints Possible Moves to List
if testtest[move_counter // 3][move_counter % 3] == '*':
possible_moves.append(move_counter)
return possible_moves
# }
def list_possible_states(board): # {
test = copy.copy(board)
possible_moves = list_possible_moves(test)
xoro = '*'
if (len(possible_moves)) % 2 == 0:
xoro = 'O'
else:
xoro = 'X'
possible_states = []
for move in possible_moves:
board_s = test
board_s[move // 3][move % 3] = xoro
possible_states.append(board_s)
del board_s
return possible_states
# }
}
The problem with your list_possible_states function is that the line board_s = board doesn't do what you seem to expect it to do. It doesn't copy the board list. It just creates a new reference to the existing list object. When you change the list's contents, you'll see the change through both references.
The fact that list_possible_states is defined in a different module than where you call it from doesn't matter, since it's not modifying a global variable. You're passing it a reference to the board, and it's modifying it by mistake.
If you want to make a copy, use the deepcopy function from the copy module in the standard library:
board_s = copy.deep_copy(board)
Just using copy.copy (as you're doing in your update) is not enough, since board is a nested list and you need new lists at all levels.
I'm not sure, but it could be because in the for loop:
for move in possible_moves:
board_s = board
board_s[move // 3][move % 3] = xoro
possible_states.append(board_s)
del board_s
board_s might be being pointed to board, rather than being set to a copy of what board is. This would explain the list values changing. If this is true, when board_s is deleted at the end of the loop, the pointer is being deleted, not the board itself.
board_state = [['*', '*', '*'],['*', '*', '*'],['*', '*', '*']]
board_s = board_state
board_s[0][0] = 'O'
print board_state
Same result ^
def list_possible_states(board):
possible_moves = list_possible_moves(board)
xoro = '*'
if (len(possible_moves)) % 2 == 0:
xoro = 'O'
else:
xoro = 'X'
possible_states = []
...START OF NEW...
board_s = []
for i in range(0, len(board)):
for j in range(0, len(board[i])):
board_s[i][j] = board[i][j]
for move in possible_moves:
board_s[move // 3][move % 3] = xoro
possible_states.append(board_s)
del board_s
...END OF NEW....
return possible_states

Python - Conway's Game Of Life - Wont update to next cycle

I'm new to python, coming from Java and C#. I have a working implementation in Java, but when I tried writing it in Python the grid will not update to the next cycle. I don't think the issues is with the deepcopy. Could it be reassignment of array elements?
import copy
liveSymbol = "X"
deadSymbol = "-"
class Cell:
def __init__(self, live, symbol, row, column):
self.live = live
self.symbol = symbol
self.row = row
self.column = column
def __repr__(self):
return repr(self.symbol)
class Model:
def __init__(self, rows, columns):
self.grid = []
self.nextGrid = []
self.rows = rows
self.columns = columns
self.initGrids()
self.addPatternToGrid()
def initGrids(self):
for i in range(self.rows):
self.grid.append([])
self.nextGrid.append([])
for j in range(self.columns):
cell = Cell(False, deadSymbol, i, j)
self.grid[i].append(cell)
self.nextGrid[i].append(cell)
def addPatternToGrid(self):
self.grid[1][2] = Cell(True, liveSymbol, 1, 2)
self.grid[2][2] = Cell(True, liveSymbol, 2, 2)
self.grid[3][2] = Cell(True, liveSymbol, 3, 2)
def printGrid(self):
print("GRID")
print("\n______________________", end=" ")
for i in range(self.rows):
print("")
for j in range(self.columns):
print(self.grid[i][j], end=" ")
def printNextGrid(self):
print("Next Grid")
print("\n______________________", end=" ")
for i in range(self.rows):
print("")
for j in range(self.columns):
print(self.grid[i][j], end=" ")
def start(self):
for i in range(self.rows):
for j in range(self.columns):
willLive = self.aliveNextCycle(self.grid[i][j])
symbol = self.getSymbol(willLive)
self.nextGrid[i][j] = Cell(willLive, symbol, i, j)
print("Before update grid to next cycle")
self.printGrid()
self.printNextGrid()
self.updateGridToNextCycle()
print("After update grid to next cycle")
self.printGrid()
self.printNextGrid()
def getSymbol(self, isLive):
return liveSymbol if True else deadSymbol
def aliveNextCycle(self, cell):
liveNeighbors = self.countTheLiveNeighbors(cell)
if cell.live:
live = not (liveNeighbors < 2 or liveNeighbors > 3)
return not live
else:
lives = liveNeighbors==3
return lives
def updateGridToNextCycle(self):
# for i in range(self.rows):
# for j in range(self.columns):
# self.grid[i][j] = self.nextGrid[i][j]
self.grid = copy.deepcopy(self.nextGrid)
def countTheLiveNeighbors(self, cell):
count = 0
# Directly Left
if cell.column != 0:
if self.grid[cell.row][cell.column - 1].live:
count += 1
# Upper Left
if cell.row != 0 and cell.column != 0:
if self.grid[cell.row - 1][cell.column - 1].live:
count += 1
# Directly above
if cell.row != 0:
if self.grid[cell.row - 1][cell.column].live:
count += 1
# Above right
if cell.row != 0 and cell.column != self.columns - 1:
if self.grid[cell.row - 1][cell.column + 1].live:
count += 1
# Directly right
if cell.column != self.columns - 1:
if self.grid[cell.row][cell.column + 1].live:
count += 1
# Right under
if cell.row != self.rows - 1 and cell.column != self.columns - 1:
if self.grid[cell.row + 1][cell.column + 1].live:
count += 1
# Directly beneath
if cell.row != self.rows - 1:
if self.grid[cell.row + 1][cell.column].live:
count += 1
# Down left
if cell.row != self.rows - 1 and cell.column != 0:
if self.grid[cell.row + 1][cell.column - 1].live:
count += 1
return count
model = Model(5, 5)
model.start()
Below is the output
Before update grid to next cycle
GRID
______________________
'-' '-' '-' '-' '-'
'-' '-' 'X' '-' '-'
'-' '-' 'X' '-' '-'
'-' '-' 'X' '-' '-'
'-' '-' '-' '-' '-' Next Grid
______________________
'-' '-' '-' '-' '-'
'-' '-' 'X' '-' '-'
'-' '-' 'X' '-' '-'
'-' '-' 'X' '-' '-'
'-' '-' '-' '-' '-' After update grid to next cycle
GRID
______________________
'X' 'X' 'X' 'X' 'X'
'X' 'X' 'X' 'X' 'X'
'X' 'X' 'X' 'X' 'X'
'X' 'X' 'X' 'X' 'X'
'X' 'X' 'X' 'X' 'X' Next Grid
______________________
'X' 'X' 'X' 'X' 'X'
'X' 'X' 'X' 'X' 'X'
'X' 'X' 'X' 'X' 'X'
'X' 'X' 'X' 'X' 'X'
'X' 'X' 'X' 'X' 'X'
I see several problems here.
First, your printNextGrid() function is exactly the same as printGrid(); it prints data from self.grid instead of self.nextGrid. Your use of copy.deepcopy is perfectly fine.
Second, you're embedding too much information in the Cell object. Each cell only needs to track its own state; it doesn't need to also separately store the symbol used for its current state and its location. (Truthfully, it's not clear this needs to be an object at all; I'd strongly recommend that you store True and False in the grid instead of objects. This will make your code much simpler.)
Critically, though, your implementations of getSymbol() and aliveNextCycle() are incorrect. First:
def getSymbol(self, isLive):
return liveSymbol if True else deadSymbol
^^^^^^^
True is always true. The condition you want here is isLive.
Second:
def aliveNextCycle(self, cell):
liveNeighbors = self.countTheLiveNeighbors(cell)
if cell.live:
live = not (liveNeighbors < 2 or liveNeighbors > 3)
return not live
else:
lives = liveNeighbors==3
return lives
The logic for the cell.live case is excessively convoluted, and ends up inverting the conditions for survival, causing incorrect behavior. A much simpler (and correct) implementation would be:
def aliveNextCycle(self, cell):
liveNeighbors = self.countTheLiveNeighbors(cell)
if liveNeighbors == 3: return True
if liveNeighbors == 2: return cell.live
return False

Parentheses pairing ({}[]()<>) issue

I want to be able to pair up all parentheses in a string, if they aren't paired then then they get their index number and False. It seems like it is repeating some values over and over, i.e cl == pop[1]. I have tried to see where the problem is but I can't see it no matter how hard I try. So I'm asking if anyone help me to locate the error and maybe even improve my code ;)
def check_parentheses(string):
pending = 0
brackets = []
'''Checks if parens are paired, otherwise they are bad.'''
parenstack = collections.deque()
for ch in string:
if ch in lrmap:
try:
cl = string.index(ch, pending)
pending = cl + 1
except:
cl = False
if ch in lparens:
parenstack.append([ch, cl])
print parenstack
elif ch in rparens:
try:
pop = parenstack.pop()
if lrmap[pop[0]] != ch:
print 'wrong type of parenthesis popped from stack',\
pop[0], ch, pop[1], cl
brackets.append([pop[1], False])
brackets.append([cl, False])
else:
brackets.append([pop[1], cl])
except IndexError:
print 'no opening parenthesis left in stack'
brackets.append([cl, False])
# if we are not out of opening parentheses, we have a mismatch
for p in parenstack:
brackets.append([p[1],False])
return brackets
You can adapt my code to a similar question:
def Evaluate(str):
stack = []
pushChars, popChars = "<({[", ">)}]"
for c in str :
if c in pushChars :
stack.append(c)
elif c in popChars :
if not len(stack) :
return False
else :
stackTop = stack.pop()
balancingBracket = pushChars[popChars.index(c)]
if stackTop != balancingBracket :
return False
else :
return False
return not len(stack)
iparens = iter('(){}[]<>')
parens = dict(zip(iparens, iparens))
closing = parens.values()
def balanced(astr):
stack = []
for c in astr:
d = parens.get(c, None)
if d:
stack.append(d)
elif c in closing:
if not stack or c != stack.pop():
return False
return not stack
Example:
>>> balanced('[1<2>(3)]')
True
>>> balanced('[1<2(>3)]')
False
BRACES = { '(': ')', '[': ']', '{': '}' }
def group_check(s):
stack = []
for b in s:
c = BRACES.get(b)
if c:
stack.append(c)
elif not stack or stack.pop() != b:
return False
return not stack
Thanks hughdbrown your code was a breeze to get working and it's really short! You've just saved me a headache :D
converted it to pep8 if thats ok :)
Edit
Added support for comments and strings, it will not match inside them.
Added support for easy language brace checking, modify the charset dict.
Correctly paires up, i.e right to left
HTML
charset = dict(opening='{[(<',\
closing='}])>',\
string = ('"', "'"),\
comment=(('<!--', '-->')))
Python
charset = dict(opening='{[(<',\
closing='}])>',\
string = ('"', "'"),\
comment=(("'''", "'''"), ('"""', '"""'), ('#', '\n')))
C++
charset = dict(opening='{[(<',\
closing='}])>',\
string = ('"', "'"),\
comment=(('/*', '*/'), ('//', '\n')))
you get the point? :)
charset = dict(opening='{[(<',\
closing='}])>',\
string = ('"', "'"),\
comment=(('<!--', '-->'), ('"""', '"""'), ('#', '\n')))
allowed = ''.join([x[0][0] + x[1][0] for x in charset['comment']])
allowed += ''.join(charset['string'])
allowed += charset['opening']
allowed += charset['closing']
def brace_check(text):
o = []
c = []
notr = []
found = []
busy = False
last_pos = None
for i in xrange(len(text)):
ch = text[i]
if not busy:
cont = True
for comment in charset['comment']:
if ch == comment[0][0]:
como = text[i:len(comment[0])]
if como == comment[0]:
busy = comment[1]
if ch in charset['opening']:
last_pos = i
cont = False
break
if cont:
if ch in charset['string']:
busy = ch
elif ch in charset['opening']:
o.append((ch, i))
elif ch in charset['closing']:
c.append((ch, i))
else:
if ch == busy[0]:
if len(busy) == 1:
comc = ch
else:
comc = text[i:i + len(busy)]
if comc == busy:
if last_pos is not None:
if busy[-1] in charset['closing']:
found.append((last_pos, i))
last_pos = None
text = text[:i] + '\n' * len(comc) +\
text[i + len(comc):]
busy = not busy
elif busy in charset['string']:
if ch == '\n':
busy = not busy
for t, e in reversed(o):
try:
n = next((b, v) for b, v in c\
if b == charset['closing'][\
charset['opening'].find(t)] and v > e)
c.remove(n)
n = n[1]
if found != []:
if e < found[-1][0] and n > found[-1][0] and n < found[-1][1]\
or e < found[-1][1] and n > found[-1][1] and e > found[-1][0]:
found.append((n, False))
n = False
except StopIteration:
n = False
found.append((e, n))
for t, e in c:
found.append((e, False))
return found
An understandable solution in Python 3:
def check_balanced_string(str):
stack = []
dicc = {'(': ')', '[': ']', '{': '}'}
for char in str:
if char in dicc.keys(): # opening char
stack.append(char)
elif char in dicc.values(): # closing char
if dicc[stack[-1]] == char: # check if closing char corresponds to last opening char
stack.pop()
else:
return False
return not len(stack) # returns True when len == 0
eq = '{1+[3*5+(2+1)]}'
print(check_balanced_string(eq))
Try this:
def matched(s):
stack=[]
open,close="(",")"
for i in s:
if i in open:
stack.append(i)
if i in close:
if len(stack)==0:
return(False)
else:
stack.pop()
if len(stack):
return(False)
else:
return(True)
The below code will display the missing parentheses and the no of times missing in the given string.
from collections import Counter
def find_missing(str):
stack1 = []
stack2 = []
result = []
res_dict = {}
open_set = '<[{('
closed_set = '>]})'
a = list(str)
for i in a:
if i in open_set:
stack1.append(i)
elif i in closed_set:
stack2.append(i)
dict1 = Counter(stack1)
dict2 = Counter(stack2)
print(dict1)
print(dict2)
for i in open_set:
if dict1[i] > dict2[closed_set[open_set.index(i)]]:
res_dict[closed_set[open_set.index(i)]] = dict1[i] - dict2[closed_set[open_set.index(i)]]
result.append(closed_set[open_set.index(i)])
for i in closed_set:
if dict2[i] > dict1[open_set[closed_set.index(i)]]:
res_dict[open_set[closed_set.index(i)]] = dict2[i] - dict1[open_set[closed_set.index(i)]]
result.append(open_set[closed_set.index(i)])
return res_dict
# return result
if __name__ == '__main__':
str1 = '{This ((()bracket {[function]} <<going> crazy}'
x = find_missing(str1)
if len(x) > 0:
print("Imbalanced")
print(x)
else:
print("Balanced")
First we will scan the string from left to right, and every time we see an opening parenthesis we push it to a stack, because we want the last opening parenthesis to be closed first. (Remember the FILO structure of a stack!)
Then, when we see a closing parenthesis we check whether the last opened one is the corresponding closing match, by popping an element from the stack. If it’s a valid match, then we proceed forward, if not return false.
Code:
https://gist.github.com/i143code/51962bfb1bd5925f75007d4dcbcf7f55
I needed something for a recent project and figured I could build on the OP's solution a bit. It allows for comment patterns, quotes and brackets to be checked, whilst ignoring the surrounding text. I've purposefully made it more generic than it needs to be so that others can take what they want and cut out what they don't.
"""
This module is for testing bracket pairings within a given string
Tested with Python 3.5.4
>>> regexp = getRegexFromList(opening + closing)
>>> print(regexp)
(\\<\\-\\-|\\-\\-\\>|\\/\\*|\\/\\/|\\*\\/|\\#|\\"|\\'|\\(|\\[|\\{|\\<|\\\n|\\\n|\\"|\\'|\\)|\\]|\\}|\\>)
>>> test_string = 'l<--([0])-->1/*{<2>}*/3//<--4 &-->\\n5#"6"\\n7"/*(8)*/"9\'"10"\'11({12\ta})13[<14>]'
>>> patterns = re.findall(regexp, test_string)
>>> print(patterns)
['<--', '(', '[', ']', ')', '-->', '/*', '{', '<', '>', '}', '*/', '//', '<--', '-->', '\\n', '#', '"', '"', '\\n', '"', '/*', '(', ')', '*/', '"', '(', '{', '}', ')', '[', '<', '>', ']']
>>> doBracketsMatch(patterns)
True
>>> doBracketsMatch(['"', ')', '"', '[', ']', '\\''])
False
"""
# Dependencies
import re
# Global Variables
# Provide opening and closing patterns, along with their priorities & whether a priority is nestable
opening = ['<--', '/*', '//', '#', '"', '\'', '(', '[', '{', '<']
closing = ['-->', '*/', '\n', '\n', '"', '\'', ')', ']', '}', '>']
priority = [ 1, 1, 1, 1, 1, 1, 0, 0, 0, 0]
nestable = {0: True, 1: False}
bracket_pairs = dict(zip(opening + closing, \
[[(closing + opening)[i], (priority + priority)[i]] \
for i in range(0, opening.__len__() * 2)]))
def getRegexFromList(listOfPatterns):
"""
Generate the search term for the regular expression
:param listOfPatterns:
:return:
>>> getRegexFromList(['"', '<--', '##', 'test'])
'(\\\\t\\\\e\\\\s\\\\t|\\\\<\\\\-\\\\-|\\\\#\\\\#|\\\\")'
"""
# Longer patterns first to prevent false negatives
search_terms = sorted(listOfPatterns, key=len, reverse=True)
regex = ""
for term in search_terms:
for char in str(term):
regex = regex + '\\' + char # Search for all characters literally
regex = regex + '|' # Search pattern = (a|b|c)
return '(' + regex[:-1] + ')' # Remove excess '|' and add brackets
def doBracketsMatch(list_of_brackets):
"""
Determine if brackets match up
:param list_of_brackets:
:return:
"""
stack = []
for bracket in list_of_brackets:
# Check empty stack conditions
if stack.__len__() is 0:
# Check for openings first to catch quotes
if bracket in opening:
stack.append(bracket)
elif bracket in closing:
return False
else:
continue
# Check for a matching bracket
elif bracket == bracket_pairs[stack[-1]][0]:
stack.pop()
# Ignore cases:
# - False positives
# - Lower priority brackets
# - Equal priority brackets if nesting is not allowed
elif bracket not in bracket_pairs or \
bracket_pairs[bracket][1] < bracket_pairs[stack[-1]][1] or \
(bracket_pairs[bracket][1] == bracket_pairs[stack[-1]][1] and \
not nestable[bracket_pairs[bracket][1]]):
continue
# New open bracket
elif bracket in opening:
stack.append(bracket)
# Otherwise, unpaired close bracket
else:
return False
# If stack isn't empty, then there is an unpaired open bracket
return not bool(stack)
if __name__ == '__main__':
import doctest
doctest.testmod()

Categories