-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrun2.py
More file actions
130 lines (94 loc) · 4.01 KB
/
run2.py
File metadata and controls
130 lines (94 loc) · 4.01 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
import sys
import collections
# Константы для символов ключей и дверей
keys_char = [chr(i) for i in range(ord('a'), ord('z') + 1)]
doors_char = [k.upper() for k in keys_char]
def get_input():
"""Чтение данных из стандартного ввода."""
return [list(line.strip()) for line in sys.stdin]
# ближайише доступные неисследованные клетки
def get_neighbors(data, pos, collected_keys=set()):
rows = len(data)
if rows == 0:
return []
cols = len(data[0])
x, y = pos
neighbors = []
directions = [(-1, 0), (1, 0), (0, -1), (0, 1)]
for dx, dy in directions:
nx, ny = x + dx, y + dy
# проверка на index out of range
if 0 <= nx < rows and 0 <= ny < cols:
cell = data[nx][ny]
# проверка на проходимость
if (cell == '.' or cell == '@' or
cell.islower() or
(cell.isupper() and cell.lower() in collected_keys)): # на двери
neighbors.append((nx, ny))
return neighbors
# ищет ключ, ближайший к текущей позиции и считает число шагов до него
def pathway(data, pos, collected_keys=None):
if collected_keys is None:
collected_keys = set()
checked = [pos] # проверенные клетки
ways = [pos]
steps = 0 # счетчик
while ways:
next_ways = []
for current_pos in ways:
x, y = current_pos
cell = data[x][y]
# проверяем нашли ли ключ
if cell.islower() and cell not in collected_keys:
return (steps, current_pos, cell)
# получаем соседей для текущей позиции
for neighbor in get_neighbors(data, current_pos, collected_keys):
if neighbor not in checked:
checked.append(neighbor)
next_ways.append(neighbor)
ways = next_ways
steps += 1
return None # если ключ не найден
# определяет положения всех роботов на сетке
def robot_finder(data):
robot_positions = []
for i in range(len(data)):
row = data[i]
for j in range(len(row)):
if row[j] == '@':
robot_positions.append((i, j))
return robot_positions
def solve(data):
collected_keys = set()
count = 0
while True:
# все роботы
robots = [(i, j) for i, row in enumerate(data)
for j, cell in enumerate(row) if cell == '@']
# ищем ближайший ключ для каждого робота
candidates = []
for pos in robots:
result = pathway(data, pos, collected_keys)
if result: # если ключ найден
candidates.append((pos, result)) # (стартовая позиция, (шаги, позиция_ключа, ключ))
# если ключей больше нет то конец цикла
if not candidates:
break
# выбираем робота с минимальным количеством шагов до его ближайшего ключа
candidates.sort(key=lambda x: x[1][0])
best_robot_pos, (steps, key_pos, key) = candidates[0]
# обновляем данные
count += steps
collected_keys.add(key)
# обновляем позицию робота (в сетке)
x, y = best_robot_pos
data[x][y] = '.' # очистка
x, y = key_pos
data[x][y] = '@' # постановка
return count
def main():
data = get_input()
result = solve(data)
print(result)
if __name__ == '__main__':
main()