|
|
|
|
@ -1,4 +1,5 @@
|
|
|
|
|
import api
|
|
|
|
|
import ast
|
|
|
|
|
from collections import defaultdict
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -19,7 +20,28 @@ class Explore:
|
|
|
|
|
def _path(self, path):
|
|
|
|
|
return self.unification_id.get(path, path)
|
|
|
|
|
|
|
|
|
|
def id_room(self, path):
|
|
|
|
|
def save(self):
|
|
|
|
|
return {
|
|
|
|
|
"problem": self.problem,
|
|
|
|
|
"room": dict(self.rooms),
|
|
|
|
|
"room_ids": dict(self.room_ids),
|
|
|
|
|
"neighbours": dict(self.neighbors),
|
|
|
|
|
"unification_id": dict(self.unification_id),
|
|
|
|
|
"unifications": dict(self.unifications),
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
|
def load(cls, obj):
|
|
|
|
|
new = cls(obj["problem"])
|
|
|
|
|
new.problem = obj["problem"]
|
|
|
|
|
new.rooms.update(obj["room"])
|
|
|
|
|
new.room_ids.update(obj["room_ids"])
|
|
|
|
|
new.neighbors.update(obj["neighbours"])
|
|
|
|
|
new.unification_id.update(obj["unification_id"])
|
|
|
|
|
new.unifications.update(obj["unifications"])
|
|
|
|
|
return new
|
|
|
|
|
|
|
|
|
|
def explore(self, path):
|
|
|
|
|
path = self._path(path)
|
|
|
|
|
if path in self.room_ids:
|
|
|
|
|
return self.r
|
|
|
|
|
@ -29,7 +51,7 @@ class Explore:
|
|
|
|
|
|
|
|
|
|
results = api.explore(paths)["results"]
|
|
|
|
|
|
|
|
|
|
# print("id", path, results)
|
|
|
|
|
print("id", path, results)
|
|
|
|
|
label = results[0][-2]
|
|
|
|
|
neighbors = [r[-1] for r in results]
|
|
|
|
|
|
|
|
|
|
@ -39,7 +61,7 @@ class Explore:
|
|
|
|
|
|
|
|
|
|
# update pen-ultimate room
|
|
|
|
|
if path:
|
|
|
|
|
p, rid = self.neighbors[path[:-1]][int(path[-1])]
|
|
|
|
|
p, _ = self.neighbors[path[:-1]][int(path[-1])]
|
|
|
|
|
self.neighbors[path[:-1]][int(path[-1])] = (p, room_id)
|
|
|
|
|
|
|
|
|
|
return room_id
|
|
|
|
|
@ -72,7 +94,9 @@ class Explore:
|
|
|
|
|
raise ExploreError(f"room '{path2}' not explored")
|
|
|
|
|
|
|
|
|
|
if self.rooms[path1] != self.rooms[path2]:
|
|
|
|
|
raise ExploreError(f"ids of '{path1}'({self.rooms[path1]}) and '{path2}'({self.rooms[path2]}) do not match")
|
|
|
|
|
raise ExploreError(
|
|
|
|
|
f"ids of '{path1}'({self.rooms[path1]}) and '{path2}'({self.rooms[path2]}) do not match"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
path = min(path1, path2)
|
|
|
|
|
pmerge = max(path1, path2)
|
|
|
|
|
@ -85,9 +109,13 @@ class Explore:
|
|
|
|
|
unification_id = self.unification_id.copy()
|
|
|
|
|
|
|
|
|
|
merged_neighbors = []
|
|
|
|
|
for n, ((p, rid), (pm, rmid)) in enumerate(zip(neighbors[path], neighbors[pmerge])):
|
|
|
|
|
for n, ((p, rid), (pm, rmid)) in enumerate(
|
|
|
|
|
zip(neighbors[path], neighbors[pmerge])
|
|
|
|
|
):
|
|
|
|
|
if rid and rmid and rid != rmid:
|
|
|
|
|
raise ExploreError(f"neighbor {n} of '{path}'({rid}) and '{pmerge}'({rmid}) do not match")
|
|
|
|
|
raise ExploreError(
|
|
|
|
|
f"neighbor {n} of '{path}'({rid}) and '{pmerge}'({rmid}) do not match"
|
|
|
|
|
)
|
|
|
|
|
merged_neighbors.append((p, rid or rmid))
|
|
|
|
|
|
|
|
|
|
# unify paths
|
|
|
|
|
@ -125,33 +153,95 @@ class Explore:
|
|
|
|
|
|
|
|
|
|
return unified
|
|
|
|
|
|
|
|
|
|
def unify_all(self):
|
|
|
|
|
unified = self
|
|
|
|
|
|
|
|
|
|
while True:
|
|
|
|
|
for rid, paths in unified.room_ids.items():
|
|
|
|
|
if len(paths) > 1:
|
|
|
|
|
paths = list(paths)
|
|
|
|
|
unified = unified.unify(paths[0], paths[1])
|
|
|
|
|
break
|
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
return unified
|
|
|
|
|
|
|
|
|
|
def unexplored(self):
|
|
|
|
|
for path, ns in self.neighbors.items():
|
|
|
|
|
for p, rid in ns:
|
|
|
|
|
if not rid:
|
|
|
|
|
yield p
|
|
|
|
|
|
|
|
|
|
def is_explored(self):
|
|
|
|
|
return next(self.unexplored(), None) is None and all(
|
|
|
|
|
len(p) == 1 for p in self.room_ids.values()
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
def guess(self):
|
|
|
|
|
ids = {}
|
|
|
|
|
for i, rid in enumerate(self.room_ids.keys()):
|
|
|
|
|
ids[rid] = i
|
|
|
|
|
|
|
|
|
|
connected = set()
|
|
|
|
|
connections = []
|
|
|
|
|
for path, ns in self.neighbors.items():
|
|
|
|
|
src_id = self.rooms[path]
|
|
|
|
|
for src_door, (trg_path, trg_id) in enumerate(ns):
|
|
|
|
|
src = (ids[src_id], src_door)
|
|
|
|
|
trg_door = next(
|
|
|
|
|
j
|
|
|
|
|
for j, (p, rid) in enumerate(self.neighbors[trg_path])
|
|
|
|
|
if rid == src_id
|
|
|
|
|
)
|
|
|
|
|
trg = (ids[trg_id], trg_door)
|
|
|
|
|
|
|
|
|
|
if (src, trg) in connected or (trg, src) in connected:
|
|
|
|
|
continue
|
|
|
|
|
connected.add((src, trg))
|
|
|
|
|
connections.append(
|
|
|
|
|
{
|
|
|
|
|
"from": {"room": src[0], "door": src[1]},
|
|
|
|
|
"to": {"room": trg[0], "door": trg[1]},
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
layout = {
|
|
|
|
|
"rooms": list(ids.values()),
|
|
|
|
|
"startingRoom": ids[self.rooms[""]],
|
|
|
|
|
"connections": connections,
|
|
|
|
|
}
|
|
|
|
|
# print(layout)
|
|
|
|
|
return api.guess(layout)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test():
|
|
|
|
|
ex = Explore("probatio")
|
|
|
|
|
ex.rooms = {
|
|
|
|
|
"": "0101112",
|
|
|
|
|
"0": "1002001",
|
|
|
|
|
"1": "0101112",
|
|
|
|
|
"2": "1002001",
|
|
|
|
|
"3": "1002001",
|
|
|
|
|
"4": "1002001",
|
|
|
|
|
"5": "2212022",
|
|
|
|
|
}
|
|
|
|
|
ex.room_ids = {"0101112": {"", "1"}, "1002001": {"0", "2", "3", "4"}, "2212022": {"5"}}
|
|
|
|
|
ex.neighbors = {
|
|
|
|
|
"": [
|
|
|
|
|
("0", "1002001"),
|
|
|
|
|
("1", "0101112"),
|
|
|
|
|
("2", "1002001"),
|
|
|
|
|
("3", "1002001"),
|
|
|
|
|
("4", "1002001"),
|
|
|
|
|
("5", "2212022"),
|
|
|
|
|
],
|
|
|
|
|
"0": [("00", None), ("01", None), ("02", None), ("03", None), ("04", None), ("05", None)],
|
|
|
|
|
"1": [("10", None), ("11", None), ("12", None), ("13", None), ("14", None), ("15", None)],
|
|
|
|
|
"2": [("20", None), ("21", None), ("22", None), ("23", None), ("24", None), ("25", None)],
|
|
|
|
|
"3": [("30", None), ("31", None), ("32", None), ("33", None), ("34", None), ("35", None)],
|
|
|
|
|
"4": [("40", None), ("41", None), ("42", None), ("43", None), ("44", None), ("45", None)],
|
|
|
|
|
"5": [("50", None), ("51", None), ("52", None), ("53", None), ("54", None), ("55", None)],
|
|
|
|
|
}
|
|
|
|
|
return ex
|
|
|
|
|
api.select(ex.problem)
|
|
|
|
|
ex.explore("")
|
|
|
|
|
ex.dump()
|
|
|
|
|
|
|
|
|
|
while True:
|
|
|
|
|
unexplored = next(ex.unexplored(), None)
|
|
|
|
|
if not unexplored:
|
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
print("explore", unexplored)
|
|
|
|
|
ex.explore(unexplored)
|
|
|
|
|
ex.dump()
|
|
|
|
|
|
|
|
|
|
print("unify")
|
|
|
|
|
ex = ex.unify_all()
|
|
|
|
|
ex.dump()
|
|
|
|
|
|
|
|
|
|
print("explored", ex.is_explored())
|
|
|
|
|
# with open("test.rooms","w") as h:
|
|
|
|
|
# h.write(str(ex.save()))
|
|
|
|
|
if ex.is_explored():
|
|
|
|
|
print("guess", ex.guess())
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
|
# with open("test.rooms") as h:
|
|
|
|
|
# obj = ast.literal_eval(h.read())
|
|
|
|
|
|
|
|
|
|
test()
|
|
|
|
|
|