Solve problem 81 to 83 in Python and learn A* algorithm along the way.
This commit is contained in:
@@ -1,8 +1,51 @@
|
|||||||
|
from functools import namedtuple
|
||||||
|
from lib_a_star import A_Star
|
||||||
|
|
||||||
|
|
||||||
|
def get_grid():
|
||||||
|
with open("../txt/EulerProblem081.txt", "r") as f:
|
||||||
|
grid = list(map(lambda line: list(map(int, line.split(","))),
|
||||||
|
f.readlines()))
|
||||||
|
return grid
|
||||||
|
|
||||||
|
|
||||||
def euler_081():
|
def euler_081():
|
||||||
return 0
|
Node = namedtuple("Node", ["row", "col"])
|
||||||
|
|
||||||
|
def cost(grid):
|
||||||
|
n_rows = len(grid)
|
||||||
|
n_cols = len(grid[0])
|
||||||
|
start_node = Node(0, 0)
|
||||||
|
end_node = Node(n_rows - 1, n_cols - 1)
|
||||||
|
|
||||||
|
def h(node):
|
||||||
|
return (end_node.row - node.row) + (end_node.col - node.col)
|
||||||
|
|
||||||
|
def d(current_node, next_node):
|
||||||
|
return grid[next_node.row][next_node.col]
|
||||||
|
|
||||||
|
def neighbors(node):
|
||||||
|
neighbors = []
|
||||||
|
# right neighbor
|
||||||
|
if not node.col + 1 == n_cols:
|
||||||
|
neighbors.append(Node(node.row, node.col + 1))
|
||||||
|
# down neighbor
|
||||||
|
if not node.row + 1 == n_rows:
|
||||||
|
neighbors.append(Node(node.row + 1, node.col))
|
||||||
|
return neighbors
|
||||||
|
|
||||||
|
a = A_Star([start_node], [end_node], h, d, neighbors)
|
||||||
|
return a.cost
|
||||||
|
|
||||||
|
grid = [[131, 673, 234, 103, 18],
|
||||||
|
[201, 96, 342, 965, 150],
|
||||||
|
[630, 803, 746, 422, 111],
|
||||||
|
[537, 699, 497, 121, 956],
|
||||||
|
[805, 732, 524, 37, 331]]
|
||||||
|
assert(cost(grid) == 2427) # Example from problem statement.
|
||||||
|
return cost(get_grid())
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
print("e081.py: " + str(euler_081()))
|
print("e081.py: " + str(euler_081()))
|
||||||
assert(euler_081() == 0)
|
assert(euler_081() == 427337)
|
||||||
|
|||||||
@@ -1,8 +1,50 @@
|
|||||||
|
from functools import namedtuple
|
||||||
|
from lib_a_star import A_Star
|
||||||
|
from e081 import get_grid
|
||||||
|
|
||||||
|
|
||||||
def euler_082():
|
def euler_082():
|
||||||
return 0
|
Node = namedtuple("Node", ["row", "col"])
|
||||||
|
|
||||||
|
def cost(grid):
|
||||||
|
n_rows = len(grid)
|
||||||
|
n_cols = len(grid[0])
|
||||||
|
start_nodes = [Node(row, 0) for row in range(n_rows)]
|
||||||
|
end_nodes = [Node(row, n_cols - 1) for row in range(n_rows)]
|
||||||
|
|
||||||
|
def h(node):
|
||||||
|
c_self = grid[node.row][node.col]
|
||||||
|
c_steps = n_cols - node.col
|
||||||
|
return c_self + c_steps
|
||||||
|
|
||||||
|
def d(current_node, next_node):
|
||||||
|
return grid[next_node.row][next_node.col]
|
||||||
|
|
||||||
|
def neighbors(node):
|
||||||
|
neighbors = []
|
||||||
|
# right neighbor
|
||||||
|
if not node.col + 1 == n_cols:
|
||||||
|
neighbors.append(Node(node.row, node.col + 1))
|
||||||
|
# down neighbor
|
||||||
|
if not node.row + 1 == n_rows:
|
||||||
|
neighbors.append(Node(node.row + 1, node.col))
|
||||||
|
# up neighbor
|
||||||
|
if not node.row == 0:
|
||||||
|
neighbors.append(Node(node.row - 1, node.col))
|
||||||
|
return neighbors
|
||||||
|
|
||||||
|
a = A_Star(start_nodes, end_nodes, h, d, neighbors)
|
||||||
|
return a.cost
|
||||||
|
|
||||||
|
grid = [[131, 673, 234, 103, 18],
|
||||||
|
[201, 96, 342, 965, 150],
|
||||||
|
[630, 803, 746, 422, 111],
|
||||||
|
[537, 699, 497, 121, 956],
|
||||||
|
[805, 732, 524, 37, 331]]
|
||||||
|
assert(cost(grid) == 994) # Example from problem statement.
|
||||||
|
return cost(get_grid())
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
print("e082.py: " + str(euler_082()))
|
print("e082.py: " + str(euler_082()))
|
||||||
assert(euler_082() == 0)
|
assert(euler_082() == 260324)
|
||||||
|
|||||||
@@ -1,8 +1,51 @@
|
|||||||
|
from functools import namedtuple
|
||||||
|
from lib_a_star import A_Star
|
||||||
|
from e081 import get_grid
|
||||||
|
|
||||||
|
|
||||||
def euler_083():
|
def euler_083():
|
||||||
return 0
|
Node = namedtuple("Node", ["row", "col"])
|
||||||
|
|
||||||
|
def cost(grid):
|
||||||
|
n_rows = len(grid)
|
||||||
|
n_cols = len(grid[0])
|
||||||
|
start_node = Node(0, 0)
|
||||||
|
end_node = Node(n_rows - 1, n_cols - 1)
|
||||||
|
|
||||||
|
def h(node):
|
||||||
|
return (end_node.row - node.row) + (end_node.col - node.col)
|
||||||
|
|
||||||
|
def d(current_node, next_node):
|
||||||
|
return grid[next_node.row][next_node.col]
|
||||||
|
|
||||||
|
def neighbors(node):
|
||||||
|
neighbors = []
|
||||||
|
# right neighbor
|
||||||
|
if not node.col + 1 == n_cols:
|
||||||
|
neighbors.append(Node(node.row, node.col + 1))
|
||||||
|
# left neighbor
|
||||||
|
if not node.col == 0:
|
||||||
|
neighbors.append(Node(node.row, node.col - 1))
|
||||||
|
# down neighbor
|
||||||
|
if not node.row + 1 == n_rows:
|
||||||
|
neighbors.append(Node(node.row + 1, node.col))
|
||||||
|
# up neighbor
|
||||||
|
if not node.row == 0:
|
||||||
|
neighbors.append(Node(node.row - 1, node.col))
|
||||||
|
return neighbors
|
||||||
|
|
||||||
|
a = A_Star([start_node], [end_node], h, d, neighbors)
|
||||||
|
return a.cost
|
||||||
|
|
||||||
|
grid = [[131, 673, 234, 103, 18],
|
||||||
|
[201, 96, 342, 965, 150],
|
||||||
|
[630, 803, 746, 422, 111],
|
||||||
|
[537, 699, 497, 121, 956],
|
||||||
|
[805, 732, 524, 37, 331]]
|
||||||
|
assert(cost(grid) == 2297) # Example from problem statement.
|
||||||
|
return cost(get_grid())
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
print("e083.py: " + str(euler_083()))
|
print("e083.py: " + str(euler_083()))
|
||||||
assert(euler_083() == 0)
|
assert(euler_083() == 425185)
|
||||||
|
|||||||
33
python/lib_a_star.py
Normal file
33
python/lib_a_star.py
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
class A_Star(object):
|
||||||
|
def __init__(self, starts, goals, h, d, neighbors):
|
||||||
|
"""
|
||||||
|
:param h: heuristic function
|
||||||
|
:param d: cost from node to node function
|
||||||
|
:param neighbors: neighbors function
|
||||||
|
"""
|
||||||
|
open_set = []
|
||||||
|
g_score = {}
|
||||||
|
f_score = {}
|
||||||
|
|
||||||
|
for start in starts:
|
||||||
|
open_set.append(start)
|
||||||
|
g_score[start] = d(0, start)
|
||||||
|
f_score[start] = h(start)
|
||||||
|
|
||||||
|
while open_set:
|
||||||
|
open_set.sort(key=lambda node: f_score[node])
|
||||||
|
current = open_set[0]
|
||||||
|
|
||||||
|
if current in goals:
|
||||||
|
self.cost = g_score[current]
|
||||||
|
break
|
||||||
|
|
||||||
|
open_set = open_set[1:] # remove current
|
||||||
|
|
||||||
|
for neighbor in neighbors(current):
|
||||||
|
tentative_g_score = g_score[current] + d(current, neighbor)
|
||||||
|
if neighbor not in g_score or \
|
||||||
|
tentative_g_score < g_score[neighbor]:
|
||||||
|
g_score[neighbor] = tentative_g_score
|
||||||
|
f_score[neighbor] = g_score[neighbor] + h(neighbor)
|
||||||
|
open_set.append(neighbor)
|
||||||
Reference in New Issue
Block a user