





from __future__ import annotations

SCREAMING_SNAKE_CASE_   :      Optional[Any]			=   [
    [-1, 0],  # left
    [0, -1],  # down
    [1, 0],  # right
    [0, 1],  # up
]



def  SCREAMING_SNAKE_CASE				(      snake_case						,   snake_case						,   snake_case						,   snake_case						,   snake_case						,   )		->    tuple[list[list[int]], list[list[int]]]:
		__lowercase											=     [
		    [0 for col in range(len(grid[0]							)							)] for row in range(len(snake_case							)							)
		]  # the reference grid
		__lowercase											=     1
		__lowercase											=     [
		    [0 for col in range(len(grid[0]							)							)] for row in range(len(snake_case							)							)
		]  # the action grid

		__lowercase											=     init[0]
		__lowercase											=     init[1]
		__lowercase											=     0
		__lowercase											=     g + heuristic[x][y]  # cost from starting cell to destination cell
		__lowercase											=     [[f, g, x, y]]

		__lowercase											=     False  # flag that is set when search is complete
		__lowercase											=     False  # flag set if we can't find expand

		while not found and not resign:
				if len(snake_case							) == 0:
						raise ValueError('Algorithm is unable to find solution'							)
				else:  # to choose the least costliest action so as to move closer to the goal
						cell.sort()
						cell.reverse()
						__lowercase											=     cell.pop()
						__lowercase											=     next_cell[2]
						__lowercase											=     next_cell[3]
						__lowercase											=     next_cell[1]

						if x == goal[0] and y == goal[1]:
								__lowercase											=     True
						else:
								for i in range(len(snake_case							)							):  # to try out different valid actions
										__lowercase											=     x + DIRECTIONS[i][0]
										__lowercase											=     y + DIRECTIONS[i][1]
										if xa >= 0 and xa < len(snake_case							) and ya >= 0 and ya < len(grid[0]							):
												if closed[xa][ya] == 0 and grid[xa][ya] == 0:
														__lowercase											=     g + cost
														__lowercase											=     ga + heuristic[xa][ya]
														cell.append([fa, ga, xa, ya]							)
														__lowercase											=     1
														__lowercase											=     i
		__lowercase											=     []
		__lowercase											=     goal[0]
		__lowercase											=     goal[1]
		invpath.append([x, y]							)  # we get the reverse path from here
		while x != init[0] or y != init[1]:
				__lowercase											=     x - DIRECTIONS[action[x][y]][0]
				__lowercase											=     y - DIRECTIONS[action[x][y]][1]
				__lowercase											=     xa
				__lowercase											=     ya
				invpath.append([x, y]							)

		__lowercase											=     []
		for i in range(len(snake_case							)							):
				path.append(invpath[len(snake_case							) - 1 - i]							)
		return path, action


if __name__ == "__main__":
		SCREAMING_SNAKE_CASE_   :      str			=   [
		    [0, 1, 0, 0, 0, 0],
		    [0, 1, 0, 0, 0, 0],  # 0 are free path whereas 1's are obstacles
		    [0, 1, 0, 0, 0, 0],
		    [0, 1, 0, 0, 1, 0],
		    [0, 0, 0, 0, 1, 0],
		]

		SCREAMING_SNAKE_CASE_   :      str			=   [0, 0]
		# all coordinates are given in format [y,x]
		SCREAMING_SNAKE_CASE_   :      List[Any]			=   [len(grid) - 1, len(grid[0]) - 1]
		SCREAMING_SNAKE_CASE_   :      Dict			=   1

		# the cost map which pushes the path closer to the goal
		SCREAMING_SNAKE_CASE_   :      Dict			=   [[0 for row in range(len(grid[0]))] for col in range(len(grid))]
		for i in range(len(grid)):
				for j in range(len(grid[0])):
						SCREAMING_SNAKE_CASE_   :      str			=   abs(i - goal[0]) + abs(j - goal[1])
						if grid[i][j] == 1:
								# added extra penalty in the heuristic map
								SCREAMING_SNAKE_CASE_   :      List[str]			=   99

		SCREAMING_SNAKE_CASE_	,SCREAMING_SNAKE_CASE_   :      str			=   search(grid, init, goal, cost, heuristic)

		print('''ACTION MAP''')
		for i in range(len(action)):
				print(action[i])

		for i in range(len(path)):
				print(path[i])











def  SCREAMING_SNAKE_CASE				(      snake_case						,   snake_case							)		->    bool:
		__lowercase											=     len(snake_case							) + 1
		__lowercase											=     len(snake_case							) + 1

		# dp is a 2d matrix where dp[i][j] denotes whether prefix string of
		# length i of input_string matches with prefix string of length j of
		# given pattern.
		# "dp" stands for dynamic programming.
		__lowercase											=     [[0 for i in range(snake_case							)] for j in range(snake_case							)]

		# since string of zero length match pattern of zero length
		__lowercase											=     1

		# since pattern of zero length will never match with string of non-zero length
		for i in range(1						,   snake_case							):
				__lowercase											=     0

		# since string of zero length will match with pattern where there
		# is at least one * alternatively
		for j in range(1						,   snake_case							):
				__lowercase											=     dp[0][j - 2] if pattern[j - 1] == '*' else 0

		# now using bottom-up approach to find for all remaining lengths
		for i in range(1						,   snake_case							):
				for j in range(1						,   snake_case							):
						if input_string[i - 1] == pattern[j - 1] or pattern[j - 1] == ".":
								__lowercase											=     dp[i - 1][j - 1]

						elif pattern[j - 1] == "*":
								if dp[i][j - 2] == 1:
										__lowercase											=     1
								elif pattern[j - 2] in (input_string[i - 1], "."):
										__lowercase											=     dp[i - 1][j]
								else:
										__lowercase											=     0
						else:
								__lowercase											=     0

		return bool(dp[-1][-1]							)


if __name__ == "__main__":
		import doctest

		doctest.testmod()
		# inputing the strings
		# input_string = input("input a string :")
		# pattern = input("input a pattern :")

		SCREAMING_SNAKE_CASE_   :      Any			=   '''aab'''
		SCREAMING_SNAKE_CASE_   :      str			=   '''c*a*b'''

		# using function to check whether given string matches the given pattern
		if match_pattern(input_string, pattern):
				print(F"""{input_string} matches the given pattern {pattern}""")
		else:
				print(F"""{input_string} does not match with the given pattern {pattern}""")




