Riconosco che probabilmente hai ottenuto l'essenza di altre risposte, ma è stata una domanda divertente e mi è venuta voglia di scrivere un po 'di codice Python. Questo è il mio approccio orientato agli oggetti. Il rientro definisce l'ambito.
Rappresentazione grafica
Il grafico può essere facilmente memorizzato come chiave, dizionario dei valori in cui la chiave è l'id della room e il valore è una matrice delle room a cui conduce.
map = {
1:[5, 2],
2:[1, 3, 5],
3:[2, 4],
4:[3, 5, 6],
5:[2, 4, 1],
6:[4]
}
Interfaccia agente
Innanzitutto dovremmo pensare a quali informazioni l'agente dovrebbe essere in grado di apprendere dall'ambiente e alle operazioni che dovrebbe essere in grado di eseguire. Ciò semplifica la riflessione sull'algoritmo.
In questo caso l'agente dovrebbe essere in grado di interrogare l'ambiente per l'id della stanza in cui si trova, dovrebbe essere in grado di ottenere un conteggio delle porte nella stanza in cui si trova ( nota che questo non è l'id delle stanze le porte portano a! ) e dovrebbe essere in grado di muoversi attraverso una porta specificando un indice di porta. Qualsiasi altra cosa che un agente conosce deve essere capito dall'agente stesso.
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
Conoscenza dell'agente
Quando l'agente entra per la prima volta nella mappa, conosce solo la quantità di porte nella stanza e l'id della stanza in cui si trova attualmente. Avevo bisogno di creare una struttura che memorizzasse le informazioni che l'agente aveva appreso, ad esempio quali porte non erano state attraverso, e dove le porte conducono a ciò è stato attraversato.
Questa classe rappresenta le informazioni su una singola stanza. Ho scelto di memorizzare le porte non visitate come a set
e le porte visitate come a dictionary
, dove la chiave è l'ID della porta e il valore è l'id della stanza a cui conduce.
class RoomKnowledge(object):
def __init__(self, unvisited_door_count):
self.unvisited_doors = set(range(unvisited_door_count))
self.visited_doors = {}
Algoritmo dell'agente
Ogni volta che l'agente entra in una stanza, cerca nel suo dizionario di conoscenza informazioni sulla stanza. Se non ci sono voci per questa stanza, ne crea una nuova RoomKnowledge
e la aggiunge al dizionario della conoscenza.
Verifica se la stanza corrente è la stanza target, in tal caso poi ritorna.
Se ci sono porte in questa stanza che non abbiamo visitato, passiamo attraverso la porta e riponiamo dove conduce. Quindi continuiamo il ciclo.
Se non c'erano porte non visitate, torniamo indietro attraverso le stanze che abbiamo visitato per trovarne una con porte non visitate.
La Agent
classe eredita dalla AgentInterface
classe.
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)
Funzioni di supporto
Ho dovuto scrivere una funzione che avrebbe trovato una chiave in un dizionario con un valore, dato che quando facciamo il backtrack conosciamo l'id della stanza che stiamo cercando di raggiungere, ma non quale porta usare per raggiungerla.
def find_key(dictionary, value):
for key in dictionary:
if dictionary[key]==value:
return key
analisi
Ho testato tutte le combinazioni di posizione iniziale / finale nella mappa indicata sopra. Per ogni combinazione stampa le stanze visitate.
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))
Appunti
Il backtracking non è molto efficiente - nel peggiore dei casi potrebbe passare attraverso ogni stanza per raggiungere una stanza adiacente, ma il backtracking è abbastanza raro - nei test sopra riportati fa solo tre passi indietro. Ho evitato di inserire la gestione delle eccezioni per mantenere il codice conciso. Tutti i commenti sul mio Python sono stati apprezzati :)