

'''simple docstring'''


from __future__ import annotations

lowerCAmelCase__						:       Union[str, Any]										=						[
    [-1, 0],  # left
    [0, -1],  # down
    [1, 0],  # right
    [0, 1],  # up
]




def 	_a       (				__lowerCAmelCase		:      list[list[int]]   ,							__lowerCAmelCase		:      list[int]   ,							__lowerCAmelCase		:      list[int]   ,							__lowerCAmelCase		:      int   ,							__lowerCAmelCase		:      list[list[int]]   ,							):

		"""simple docstring"""

		snake_case__						:       Tuple       						=  [
		    [0 for col in range(len(grid[0]     )     )] for row in range(len(__lowerCAmelCase     )     )
		]  # the reference grid
		snake_case__						:       str       						=  1
		snake_case__						:       Tuple       						=  [
		    [0 for col in range(len(grid[0]     )     )] for row in range(len(__lowerCAmelCase     )     )
		]  # the action grid

		snake_case__						:       Optional[int]       						=  init[0]
		snake_case__						:       int       						=  init[1]
		snake_case__						:       Dict       						=  0
		snake_case__						:       Optional[int]       						=  g + heuristic[x][y]  # cost from starting cell to destination cell
		snake_case__						:       List[Any]       						=  [[f, g, x, y]]

		snake_case__						:       Dict       						=  False  # flag that is set when search is complete
		snake_case__						:       int       						=  False  # flag set if we can't find expand

		while not found and not resign:
				if len(__lowerCAmelCase     ) == 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()
						snake_case__						:       Union[str, Any]       						=  cell.pop()
						snake_case__						:       str       						=  next_cell[2]
						snake_case__						:       Union[str, Any]       						=  next_cell[3]
						snake_case__						:       List[str]       						=  next_cell[1]

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

		snake_case__						:       Optional[int]       						=  []
		for i in range(len(__lowerCAmelCase     )     ):
				path.append(invpath[len(__lowerCAmelCase     ) - 1 - i]     )
		return path, action


if __name__ == "__main__":
					lowerCAmelCase__						:       List[Any]										=						[
					    [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],
					]

					lowerCAmelCase__						:       Union[str, Any]										=						[0, 0]
					# all coordinates are given in format [y,x]
					lowerCAmelCase__						:       Optional[Any]										=						[len(grid) - 1, len(grid[0]) - 1]
					lowerCAmelCase__						:       Optional[int]										=						1

					# the cost map which pushes the path closer to the goal
					lowerCAmelCase__						:       Optional[Any]										=						[[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])):
															lowerCAmelCase__						:       List[str]										=						abs(i - goal[0]) + abs(j - goal[1])
															if grid[i][j] == 1:
																				# added extra penalty in the heuristic map
																				lowerCAmelCase__						:       int										=						99

					lowerCAmelCase__						,			lowerCAmelCase__						:       Any										=						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])






'''simple docstring'''


def 	_a       (				__lowerCAmelCase		:      float   ,							__lowerCAmelCase		:      float   ,							__lowerCAmelCase		:      int     ):

		"""simple docstring"""

		if principal <= 0:
				raise Exception('''Principal borrowed must be > 0'''     )
		if rate_per_annum < 0:
				raise Exception('''Rate of interest must be >= 0'''     )
		if years_to_repay <= 0 or not isinstance(__lowerCAmelCase   ,							__lowerCAmelCase     ):
				raise Exception('''Years to repay must be an integer > 0'''     )

		# Yearly rate is divided by 12 to get monthly rate
		snake_case__						:       int       						=  rate_per_annum / 12

		# Years to repay is multiplied by 12 to get number of payments as payment is monthly
		snake_case__						:       Tuple       						=  years_to_repay * 12

		return (
		    principal
		    * rate_per_month
		    * (1 + rate_per_month) ** number_of_payments
		    / ((1 + rate_per_month) ** number_of_payments - 1)
		)


if __name__ == "__main__":
					import doctest

					doctest.testmod()



