87 lines
3.0 KiB
Python
87 lines
3.0 KiB
Python
#!/bin/python3
|
|
import sys,time,re
|
|
from pprint import pprint
|
|
sys.path.insert(0, '../../')
|
|
from fred import list2int,get_re,nprint,lprint,loadFile,dijkstra,toGrid,dfs,bfs,findInGrid,get_value_in_direction,addTuples,subTuples,create_graph_from_grid,manhattan_distance
|
|
start_time = time.time()
|
|
|
|
input_f = 'input'
|
|
|
|
#########################################
|
|
# #
|
|
# Part 1 #
|
|
# #
|
|
#########################################
|
|
|
|
def part1():
|
|
grid = toGrid(input_f)
|
|
|
|
start = findInGrid(grid,'S')
|
|
end = findInGrid(grid,'E')
|
|
|
|
print(start,end)
|
|
|
|
def a_star(graph, start, end, heuristic):
|
|
|
|
import heapq
|
|
|
|
# Priority queue stores (f_score, current_node, current_direction)
|
|
priority_queue = [(0, start, None)]
|
|
g_scores = {node: float('inf') for node in graph} # Cost from start to each node
|
|
g_scores[start] = 0
|
|
|
|
f_scores = {node: float('inf') for node in graph}
|
|
f_scores[start] = heuristic(start, end)
|
|
|
|
previous_nodes = {node: None for node in graph}
|
|
|
|
while priority_queue:
|
|
current_f_score, current_node, previous_direction = heapq.heappop(priority_queue)
|
|
|
|
if current_node == end:
|
|
break
|
|
|
|
for neighbor, weight in graph[current_node]:
|
|
current_direction = (
|
|
neighbor[0] - current_node[0], # Row direction (-1, 0, 1)
|
|
neighbor[1] - current_node[1] # Col direction (-1, 0, 1)
|
|
)
|
|
|
|
turn_cost = 1000 if previous_direction and current_direction != previous_direction else 0
|
|
tentative_g_score = g_scores[current_node] + weight + turn_cost
|
|
|
|
if tentative_g_score < g_scores[neighbor]:
|
|
g_scores[neighbor] = tentative_g_score
|
|
f_scores[neighbor] = tentative_g_score + heuristic(neighbor, end)
|
|
previous_nodes[neighbor] = current_node
|
|
heapq.heappush(priority_queue, (f_scores[neighbor], neighbor, current_direction))
|
|
|
|
path = []
|
|
while end is not None:
|
|
path.append(end)
|
|
end = previous_nodes[end]
|
|
path.reverse()
|
|
|
|
return path, g_scores[path[-1]]
|
|
|
|
|
|
graph = create_graph_from_grid(grid,start,end,'#')
|
|
|
|
path, score = a_star(graph,start,end,manhattan_distance)
|
|
#print(path)
|
|
return score #Instead of implementing edge cases, just try with turning (adding 1000) to the result, if that's wrong, just don't add it. I got it right by not turning right away.
|
|
|
|
start_time = time.time()
|
|
print('Part 1:',part1(), '\t\t', round((time.time() - start_time)*1000), 'ms')
|
|
|
|
|
|
#########################################
|
|
# #
|
|
# Part 2 #
|
|
# #
|
|
#########################################
|
|
def part2():
|
|
return
|
|
|
|
start_time = time.time()
|
|
print('Part 2:',part2(), '\t\t', round((time.time() - start_time)*1000), 'ms') |