Я усвідомлюю, що ви, мабуть, отримали суть інших відповідей, але це було цікаве питання, і мені здалося, що я пророблю трохи кодування Python. Це мій об’єктно-орієнтований підхід. Відступ визначає область.
Графічне представлення
Графік може легко зберігатися як ключ, словник значень, де ключовим є ідентифікатор кімнати, а значення - масив кімнат, до яких він веде.
map = {
1:[5, 2],
2:[1, 3, 5],
3:[2, 4],
4:[3, 5, 6],
5:[2, 4, 1],
6:[4]
}
Агентський інтерфейс
Спершу слід подумати про те, яку інформацію агент повинен мати змогу дізнатись із навколишнього середовища та які операції він повинен мати змогу виконувати. Це спростить роздуми про алгоритм.
У цьому випадку агент повинен мати можливість запитувати середовище щодо ідентифікатора кімнати, в якій він знаходиться, він повинен мати можливість отримати кількість дверей у кімнаті, в якій знаходиться ( зауважте, це не ідентифікатор номерів кімнат двері ведуть до! ), і він повинен мати можливість переміщатися через двері, вказавши покажчик дверей. Все, що знає агент, повинно з'ясувати сам агент.
class AgentInterface(object):
def __init__(self, map, starting_room):
self.map = map
self.current_room = starting_room
def get_door_count(self):
return len(self.map[self.current_room])
def go_through_door(self, door):
result = self.current_room = self.map[self.current_room][door]
return result
Агентські знання
Коли агент вперше виходить на карту, він знає лише кількість дверей у кімнаті та ідентифікатор кімнати, в якій він зараз знаходиться. Мені потрібно було створити структуру, яка б зберігала інформацію, яку агент дізнався, наприклад, у яких дверях не було наскрізь, і де двері ведуть до того, що пройшло.
Цей клас представляє інформацію про одну кімнату. Я вирішив зберігати незавідані двері як «a» set
та «відвідані» двері як «a» dictionary
, де ключовим є ідентифікатор дверей, а значення - ідентифікатор приміщення, до якого він веде.
class RoomKnowledge(object):
def __init__(self, unvisited_door_count):
self.unvisited_doors = set(range(unvisited_door_count))
self.visited_doors = {}
Алгоритм агента
Кожен раз, коли агент заходить до приміщення, він шукає у своєму словнику знань інформацію про кімнату. Якщо для цієї кімнати немає записів, вона створює нову RoomKnowledge
і додає це до свого словника знань.
Він перевіряє, чи поточна кімната є цільовою кімнатою, якщо так, то повертається.
Якщо в цій кімнаті є двері, яких ми не відвідували, ми проходимо через двері і зберігаємо, куди вона веде. Потім продовжуємо цикл.
Якщо не було жодних небачених дверей, ми проходимо через кімнати, які ми відвідали, щоб знайти одну з невідомих дверей.
В Agent
клас успадковує від AgentInterface
класу.
class Agent(AgentInterface):
def find_exit(self, exit_room_id):
knowledge = { }
room_history = [] # For display purposes only
history_stack = [] # Used when we need to backtrack if we've visited all the doors in the room
while True:
room_knowledge = knowledge.setdefault(self.current_room, RoomKnowledge(self.get_door_count()))
room_history.append(self.current_room)
if self.current_room==exit_room_id:
return room_history
if len(room_knowledge.unvisited_doors)==0:
# I have destination room id. I need door id:
door = find_key(room_knowledge.visited_doors, history_stack.pop())
self.go_through_door(door)
else:
history_stack.append(self.current_room)
# Enter the first unopened door:
opened_door = room_knowledge.unvisited_doors.pop()
room_knowledge.visited_doors[opened_door]=self.go_through_door(opened_door)
Підтримуючі функції
Мені довелося написати функцію, яка б знайшла ключ у словнику із заданим значенням, оскільки при зворотному відстеженні ми знаємо ідентифікатор кімнати, до якої ми намагаємось потрапити, але не до якої двері користуватися, щоб дістатися до неї.
def find_key(dictionary, value):
for key in dictionary:
if dictionary[key]==value:
return key
Тестування
Я випробував всі комбінації початкового / кінцевого положення на карті, наведеній вище. Для кожної комбінації він роздруковує відвідувані номери.
for start in range(1, 7):
for exit in range(1, 7):
print("start room: %d target room: %d"%(start,exit))
james_bond = Agent(map, start)
print(james_bond.find_exit(exit))
Примітки
Зворотний трек не дуже ефективний - у гіршому випадку він може пройти через кожну кімнату, щоб потрапити до сусідньої кімнати, але зворотній трек є досить рідкісним - у вищезгаданих тестах він займає лише три рази. Я уникав обробляти винятки, щоб тримати код стислим. Будь-які коментарі щодо мого Python оцінили :)