diff --git a/extra/prepare-the-bunnies-escape/solution.py b/extra/prepare-the-bunnies-escape/solution.py new file mode 100644 index 0000000..4280174 --- /dev/null +++ b/extra/prepare-the-bunnies-escape/solution.py @@ -0,0 +1,76 @@ +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)