|
|
|
@ -1,5 +1,5 @@
|
|
|
|
import api
|
|
|
|
import api
|
|
|
|
import ast
|
|
|
|
import functools
|
|
|
|
from collections import defaultdict
|
|
|
|
from collections import defaultdict
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -7,6 +7,41 @@ class ExploreError(Exception):
|
|
|
|
pass
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@functools.total_ordering
|
|
|
|
|
|
|
|
class Path:
|
|
|
|
|
|
|
|
def __init__(self, path=""):
|
|
|
|
|
|
|
|
self.path = path
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def __repr__(self):
|
|
|
|
|
|
|
|
return "." +self.path if self.path else "."
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def __bool__(self):
|
|
|
|
|
|
|
|
return bool(self.path)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def __eq__(self, other):
|
|
|
|
|
|
|
|
return self.path == other.path
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def __lt__(self, other):
|
|
|
|
|
|
|
|
return (len(self.path), self.path) < (len(other.path), other.path)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def __hash__(self):
|
|
|
|
|
|
|
|
return self.path.__hash__()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def __format__(self, spec):
|
|
|
|
|
|
|
|
return str(self).__format__(spec)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def extend(self, door):
|
|
|
|
|
|
|
|
return Path(self.path + str(door))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def last(self):
|
|
|
|
|
|
|
|
return Path(self.path[:-1]), int(self.path[-1])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def shorten(self, path, pmerge):
|
|
|
|
|
|
|
|
if self.path.startswith(pmerge.path):
|
|
|
|
|
|
|
|
return Path(path.path + self.path[len(pmerge.path):])
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
return self
|
|
|
|
|
|
|
|
|
|
|
|
class Explore:
|
|
|
|
class Explore:
|
|
|
|
def __init__(self, problem):
|
|
|
|
def __init__(self, problem):
|
|
|
|
self.problem = problem
|
|
|
|
self.problem = problem
|
|
|
|
@ -41,15 +76,16 @@ class Explore:
|
|
|
|
new.unifications.update(obj["unifications"])
|
|
|
|
new.unifications.update(obj["unifications"])
|
|
|
|
return new
|
|
|
|
return new
|
|
|
|
|
|
|
|
|
|
|
|
def explore(self, path):
|
|
|
|
def explore(self, path=Path()):
|
|
|
|
path = self._path(path)
|
|
|
|
path = self._path(path)
|
|
|
|
if path in self.room_ids:
|
|
|
|
if path in self.rooms:
|
|
|
|
return self.r
|
|
|
|
return self.rooms[path]
|
|
|
|
|
|
|
|
|
|
|
|
paths = [path + str(i) for i in range(6)]
|
|
|
|
paths = [path.extend(i) for i in range(6)]
|
|
|
|
self.neighbors[path] = [(p, None) for p in paths]
|
|
|
|
self.neighbors[path] = [(p, None) for p in paths]
|
|
|
|
|
|
|
|
|
|
|
|
results = api.explore(paths)["results"]
|
|
|
|
print("explore", paths)
|
|
|
|
|
|
|
|
results = api.explore([p.path for p in paths])["results"]
|
|
|
|
|
|
|
|
|
|
|
|
print("id", path, results)
|
|
|
|
print("id", path, results)
|
|
|
|
label = results[0][-2]
|
|
|
|
label = results[0][-2]
|
|
|
|
@ -61,8 +97,9 @@ class Explore:
|
|
|
|
|
|
|
|
|
|
|
|
# update pen-ultimate room
|
|
|
|
# update pen-ultimate room
|
|
|
|
if path:
|
|
|
|
if path:
|
|
|
|
p, _ = self.neighbors[path[:-1]][int(path[-1])]
|
|
|
|
pl, dl = path.last()
|
|
|
|
self.neighbors[path[:-1]][int(path[-1])] = (p, room_id)
|
|
|
|
p, _ = self.neighbors[pl][dl]
|
|
|
|
|
|
|
|
self.neighbors[pl][dl] = (p, room_id)
|
|
|
|
|
|
|
|
|
|
|
|
return room_id
|
|
|
|
return room_id
|
|
|
|
|
|
|
|
|
|
|
|
@ -116,7 +153,7 @@ class Explore:
|
|
|
|
raise ExploreError(
|
|
|
|
raise ExploreError(
|
|
|
|
f"neighbor {n} of '{path}'({rid}) and '{pmerge}'({rmid}) do not match"
|
|
|
|
f"neighbor {n} of '{path}'({rid}) and '{pmerge}'({rmid}) do not match"
|
|
|
|
)
|
|
|
|
)
|
|
|
|
merged_neighbors.append((p, rid or rmid))
|
|
|
|
merged_neighbors.append((p.shorten(path, pmerge), rid or rmid))
|
|
|
|
|
|
|
|
|
|
|
|
# unify paths
|
|
|
|
# unify paths
|
|
|
|
unification_id[pmerge] = path
|
|
|
|
unification_id[pmerge] = path
|
|
|
|
@ -134,14 +171,13 @@ class Explore:
|
|
|
|
|
|
|
|
|
|
|
|
neighbors[path] = merged_neighbors
|
|
|
|
neighbors[path] = merged_neighbors
|
|
|
|
del neighbors[pmerge]
|
|
|
|
del neighbors[pmerge]
|
|
|
|
|
|
|
|
|
|
|
|
for p, ns in neighbors.items():
|
|
|
|
for p, ns in neighbors.items():
|
|
|
|
new = []
|
|
|
|
new = []
|
|
|
|
for np, rid in ns:
|
|
|
|
for np, rid in ns:
|
|
|
|
if np.startswith(pmerge):
|
|
|
|
np = np.shorten(path, pmerge)
|
|
|
|
new.append((path + np[len(pmerge) :], rid))
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
new.append((np, rid))
|
|
|
|
new.append((np, rid))
|
|
|
|
|
|
|
|
if rid:
|
|
|
|
|
|
|
|
assert np in rooms, f"path {np} of {(p,ns)} not in rooms"
|
|
|
|
neighbors[p] = new
|
|
|
|
neighbors[p] = new
|
|
|
|
|
|
|
|
|
|
|
|
unified = self.__class__(self.problem)
|
|
|
|
unified = self.__class__(self.problem)
|
|
|
|
@ -160,6 +196,7 @@ class Explore:
|
|
|
|
for rid, paths in unified.room_ids.items():
|
|
|
|
for rid, paths in unified.room_ids.items():
|
|
|
|
if len(paths) > 1:
|
|
|
|
if len(paths) > 1:
|
|
|
|
paths = list(paths)
|
|
|
|
paths = list(paths)
|
|
|
|
|
|
|
|
print("unify", paths[0], paths[1])
|
|
|
|
unified = unified.unify(paths[0], paths[1])
|
|
|
|
unified = unified.unify(paths[0], paths[1])
|
|
|
|
break
|
|
|
|
break
|
|
|
|
break
|
|
|
|
break
|
|
|
|
@ -187,37 +224,38 @@ class Explore:
|
|
|
|
for path, ns in self.neighbors.items():
|
|
|
|
for path, ns in self.neighbors.items():
|
|
|
|
src_id = self.rooms[path]
|
|
|
|
src_id = self.rooms[path]
|
|
|
|
for src_door, (trg_path, trg_id) in enumerate(ns):
|
|
|
|
for src_door, (trg_path, trg_id) in enumerate(ns):
|
|
|
|
src = (ids[src_id], src_door)
|
|
|
|
src = (src_id, src_door)
|
|
|
|
trg_door = next(
|
|
|
|
trg_door = next(
|
|
|
|
j
|
|
|
|
j
|
|
|
|
for j, (p, rid) in enumerate(self.neighbors[trg_path])
|
|
|
|
for j, (p, rid) in enumerate(self.neighbors[trg_path])
|
|
|
|
if rid == src_id
|
|
|
|
if rid == src_id
|
|
|
|
)
|
|
|
|
)
|
|
|
|
trg = (ids[trg_id], trg_door)
|
|
|
|
trg = (trg_id, trg_door)
|
|
|
|
|
|
|
|
|
|
|
|
if (src, trg) in connected or (trg, src) in connected:
|
|
|
|
if (src, trg) in connected or (trg, src) in connected:
|
|
|
|
continue
|
|
|
|
continue
|
|
|
|
|
|
|
|
print(src, trg)
|
|
|
|
connected.add((src, trg))
|
|
|
|
connected.add((src, trg))
|
|
|
|
connections.append(
|
|
|
|
connections.append(
|
|
|
|
{
|
|
|
|
{
|
|
|
|
"from": {"room": src[0], "door": src[1]},
|
|
|
|
"from": {"room": ids[src[0]], "door": src[1]},
|
|
|
|
"to": {"room": trg[0], "door": trg[1]},
|
|
|
|
"to": {"room": ids[trg[0]], "door": trg[1]},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
layout = {
|
|
|
|
layout = {
|
|
|
|
"rooms": list(ids.values()),
|
|
|
|
"rooms": [int(rid[0]) for rid in ids.keys()],
|
|
|
|
"startingRoom": ids[self.rooms[""]],
|
|
|
|
"startingRoom": ids[self.rooms[Path()]],
|
|
|
|
"connections": connections,
|
|
|
|
"connections": connections,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
# print(layout)
|
|
|
|
# print(layout)
|
|
|
|
return api.guess(layout)
|
|
|
|
return api.guess(layout)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test():
|
|
|
|
def solve(problem):
|
|
|
|
ex = Explore("probatio")
|
|
|
|
ex = Explore(problem)
|
|
|
|
api.select(ex.problem)
|
|
|
|
api.select(ex.problem)
|
|
|
|
ex.explore("")
|
|
|
|
ex.explore()
|
|
|
|
ex.dump()
|
|
|
|
ex.dump()
|
|
|
|
|
|
|
|
|
|
|
|
while True:
|
|
|
|
while True:
|
|
|
|
@ -234,8 +272,6 @@ def test():
|
|
|
|
ex.dump()
|
|
|
|
ex.dump()
|
|
|
|
|
|
|
|
|
|
|
|
print("explored", ex.is_explored())
|
|
|
|
print("explored", ex.is_explored())
|
|
|
|
# with open("test.rooms","w") as h:
|
|
|
|
|
|
|
|
# h.write(str(ex.save()))
|
|
|
|
|
|
|
|
if ex.is_explored():
|
|
|
|
if ex.is_explored():
|
|
|
|
print("guess", ex.guess())
|
|
|
|
print("guess", ex.guess())
|
|
|
|
|
|
|
|
|
|
|
|
@ -244,4 +280,4 @@ if __name__ == "__main__":
|
|
|
|
# with open("test.rooms") as h:
|
|
|
|
# with open("test.rooms") as h:
|
|
|
|
# obj = ast.literal_eval(h.read())
|
|
|
|
# obj = ast.literal_eval(h.read())
|
|
|
|
|
|
|
|
|
|
|
|
test()
|
|
|
|
solve("primus")
|
|
|
|
|