77 lines
2.8 KiB
Python
77 lines
2.8 KiB
Python
import numpy as np
|
|
def solution(map):
|
|
map = np.array(map)
|
|
station_door = (0, 0)
|
|
escape_pod = (map.shape[0] - 1, map.shape[1] - 1)
|
|
distance = np.zeros(map.shape, dtype = np.int)
|
|
|
|
visited_points, has_route = update_distance(distance, map, station_door, True)
|
|
if not has_route:
|
|
update_distance(distance, map, escape_pod, False)
|
|
|
|
min_length = find_minimum_length(distance, visited_points, has_route)
|
|
|
|
return min_length
|
|
|
|
def get_nearby_points(x, y, shape, card_dist):
|
|
points = []
|
|
for i in range(-card_dist, card_dist+1):
|
|
for j in range(-card_dist, card_dist+1):
|
|
if abs(i) + abs(j) == card_dist:
|
|
if x + i >= 0 and x + i < shape[0] and y + j >= 0 and y + j < shape[1]:
|
|
points += [(x+i, y+j)]
|
|
return points
|
|
|
|
def get_nearby_points_with_count(x, y, shape, count):
|
|
points = []
|
|
for point in get_nearby_points(x, y, shape, 1):
|
|
points += [(point[0], point[1], count)]
|
|
return points
|
|
|
|
def update_distance(distance, map, start, direction):
|
|
points = [(start[0], start[1], 0)]
|
|
visited_points = []
|
|
can_reach_escape_pod = False
|
|
while points:
|
|
x, y, count = points.pop(0)
|
|
count += 1 if direction else -1
|
|
if map[x, y] == 0 and distance[x, y] == 0:
|
|
distance[x, y] = count
|
|
visited_points += [(x, y)]
|
|
points += get_nearby_points_with_count(x, y, distance.shape, count)
|
|
if (x+1, y+1) == distance.shape:
|
|
can_reach_escape_pod = True
|
|
|
|
return visited_points, can_reach_escape_pod
|
|
|
|
def get_length(distance, s, t, card_dist, has_route):
|
|
s_value = distance[s[0], s[1]]
|
|
t_value = distance[t[0], t[1]]
|
|
if has_route:
|
|
if t_value > 0:
|
|
return distance[distance.shape[0]-1, distance.shape[1]-1] - t_value + s_value + card_dist
|
|
else:
|
|
if card_dist > 1 and t_value < 0:
|
|
return s_value - t_value + (card_dist-1)
|
|
|
|
def find_minimum_length(distance, points, has_route):
|
|
min_length = distance.shape[0] * distance.shape[1]
|
|
for source in points:
|
|
for card_dist in [1, 2]:
|
|
for target in get_nearby_points(source[0], source[1], distance.shape, card_dist):
|
|
length = get_length(distance, source, target, card_dist, has_route)
|
|
if length:
|
|
min_length = min(min_length, length)
|
|
return min_length
|
|
|
|
|
|
tests = [
|
|
([[0, 1, 1, 0], [0, 0, 0, 1], [1, 1, 0, 0], [1, 1, 1, 0]], 7),
|
|
([[0, 0, 0, 0, 0, 0], [1, 1, 1, 1, 1, 0], [0, 0, 0, 0, 0, 0], [0, 1, 1, 1, 1, 1], [0, 1, 1, 1, 1, 1], [0, 0, 0, 0, 0, 0]], 11),
|
|
([[0, 0, 0, 0, 0, 0], [1, 1, 1, 1, 1, 0], [0, 0, 1, 0, 0, 0], [0, 1, 1, 1, 1, 1], [0, 1, 1, 1, 1, 1], [0, 0, 0, 0, 0, 0]], 11),
|
|
]
|
|
|
|
for i, o in tests:
|
|
result = solution(i)
|
|
print(i, result == o, result, o)
|