|
|
|
|
@ -167,7 +167,6 @@ class Explore:
|
|
|
|
|
# print()
|
|
|
|
|
# for p, pu in self.unification_id.items():
|
|
|
|
|
# print(f" {p}: {pu}")
|
|
|
|
|
|
|
|
|
|
# print()
|
|
|
|
|
|
|
|
|
|
def unify(self, path1, path2):
|
|
|
|
|
@ -195,10 +194,7 @@ class Explore:
|
|
|
|
|
for n, ((p, rid), (pm, rmid)) in enumerate(zip(self.neighbors[path], self.neighbors[pmerge])):
|
|
|
|
|
if rid and rmid and rid != rmid:
|
|
|
|
|
raise ExploreError(f"neighbor {n} of '{path}'({rid}) and '{pmerge}'({rmid}) do not match")
|
|
|
|
|
if rmid:
|
|
|
|
|
merged_neighbors.append((self._path(pm), rmid))
|
|
|
|
|
else:
|
|
|
|
|
merged_neighbors.append((self._path(p), rid))
|
|
|
|
|
merged_neighbors.append((self._path(p), rid or rmid))
|
|
|
|
|
|
|
|
|
|
# fix rooms
|
|
|
|
|
del self.rooms[pmerge]
|
|
|
|
|
@ -253,7 +249,7 @@ class Explore:
|
|
|
|
|
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, orig=None, start=Path()):
|
|
|
|
|
def layout(self, orig=None, start=Path()):
|
|
|
|
|
aedi = graph.Aedificium(self.problem)
|
|
|
|
|
|
|
|
|
|
ids = {}
|
|
|
|
|
@ -263,6 +259,7 @@ class Explore:
|
|
|
|
|
|
|
|
|
|
connected = set()
|
|
|
|
|
connections = []
|
|
|
|
|
connect_errors = []
|
|
|
|
|
for path, ns in self.neighbors.items():
|
|
|
|
|
src_path = path
|
|
|
|
|
for src_door, (trg_path, _) in enumerate(ns):
|
|
|
|
|
@ -272,7 +269,10 @@ class Explore:
|
|
|
|
|
None,
|
|
|
|
|
)
|
|
|
|
|
if trg_door is None:
|
|
|
|
|
raise ExploreError(f"backlink not found: {(src, trg_path, self.neighbors[trg_path])}")
|
|
|
|
|
# raise Exception(f"backlink not found: {(src, trg_path, self.neighbors[trg_path])}")
|
|
|
|
|
print(f"backlink not found: {(src, trg_path, self.neighbors[trg_path])}")
|
|
|
|
|
connect_errors.append((src[0], src[1], trg_path))
|
|
|
|
|
trg_door = 0
|
|
|
|
|
trg = (trg_path, trg_door)
|
|
|
|
|
|
|
|
|
|
if (src, trg) in connected or (trg, src) in connected:
|
|
|
|
|
@ -286,6 +286,21 @@ class Explore:
|
|
|
|
|
)
|
|
|
|
|
aedi.add_edge(src[0], src[1], trg[0], trg[1])
|
|
|
|
|
|
|
|
|
|
if connect_errors:
|
|
|
|
|
# try to fix connection issues
|
|
|
|
|
updated = False
|
|
|
|
|
src = {src_path: (trg_path, src_door) for src_path, src_door, trg_path in connect_errors}
|
|
|
|
|
trg = {trg_path: (src_path, src_door) for src_path, src_door, trg_path in connect_errors}
|
|
|
|
|
|
|
|
|
|
for trg_path, (src_path, src_door) in trg.items():
|
|
|
|
|
if trg_path in src:
|
|
|
|
|
self.neighbors[trg_path][src_door] = (src_path, "**FIXED**")
|
|
|
|
|
updated = True
|
|
|
|
|
|
|
|
|
|
assert updated, "could not fix connections"
|
|
|
|
|
self.dump()
|
|
|
|
|
return self.layout(orig=orig, start=start)
|
|
|
|
|
|
|
|
|
|
if orig:
|
|
|
|
|
rooms = orig
|
|
|
|
|
else:
|
|
|
|
|
@ -300,7 +315,7 @@ class Explore:
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
aedi.render()
|
|
|
|
|
return api.guess(layout)
|
|
|
|
|
return layout
|
|
|
|
|
|
|
|
|
|
def returnfrom(self, path):
|
|
|
|
|
queue = [(path, Path())]
|
|
|
|
|
@ -314,40 +329,13 @@ class Explore:
|
|
|
|
|
|
|
|
|
|
assert False, "return path not found"
|
|
|
|
|
|
|
|
|
|
def walk(self, path):
|
|
|
|
|
here = Path()
|
|
|
|
|
def walk(self, path, start=Path()):
|
|
|
|
|
here = start
|
|
|
|
|
for d in map(int, path.path):
|
|
|
|
|
here = self.neighbors[here][d][0]
|
|
|
|
|
return here
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def room_solve(problem, nrooms, plen):
|
|
|
|
|
ex = Explore(problem, [d + d + d + d + d + d for d in DOORS[:plen]])
|
|
|
|
|
api.select(ex.problem)
|
|
|
|
|
res = ex.explore(Path())
|
|
|
|
|
ex.update(Path(), res)
|
|
|
|
|
ex.dump()
|
|
|
|
|
|
|
|
|
|
while True:
|
|
|
|
|
door, unexplored = next(ex.unexplored(), (None, None))
|
|
|
|
|
if unexplored is None:
|
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
print("explore", door, unexplored)
|
|
|
|
|
path = unexplored + Path([door])
|
|
|
|
|
res = ex.explore(path)
|
|
|
|
|
ex.update(path, res)
|
|
|
|
|
ex.dump()
|
|
|
|
|
|
|
|
|
|
ex.unify_all()
|
|
|
|
|
ex.dump()
|
|
|
|
|
|
|
|
|
|
print("explored", ex.is_explored())
|
|
|
|
|
if ex.is_explored():
|
|
|
|
|
print("guess", ex.guess())
|
|
|
|
|
print("score", ex.score)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_mark(rid, mask):
|
|
|
|
|
return Path("[" + str(int(rid[0]) ^ mask) + "]")
|
|
|
|
|
|
|
|
|
|
@ -398,6 +386,7 @@ def mark_solve(problem, nrooms):
|
|
|
|
|
assert ex.is_explored(), "not fully explored"
|
|
|
|
|
if nrooms % len(ex.rooms) != 0:
|
|
|
|
|
raise ExploreError(f"not all rooms could be identifed {len(ex.rooms)}/{nrooms}")
|
|
|
|
|
|
|
|
|
|
if len(ex.rooms) == nrooms:
|
|
|
|
|
print("found all rooms")
|
|
|
|
|
break
|
|
|
|
|
@ -415,6 +404,7 @@ def mark_solve(problem, nrooms):
|
|
|
|
|
orig[path] = rid[0]
|
|
|
|
|
print(path, p, rid)
|
|
|
|
|
print(orig)
|
|
|
|
|
|
|
|
|
|
# try to identify original start
|
|
|
|
|
start = apply_mask(exs[0].rooms[Path()], mask)
|
|
|
|
|
starts = []
|
|
|
|
|
@ -426,9 +416,21 @@ def mark_solve(problem, nrooms):
|
|
|
|
|
starts.append(p)
|
|
|
|
|
print("start", start, starts, all_masked)
|
|
|
|
|
assert len(starts) > 0
|
|
|
|
|
|
|
|
|
|
print("guess", ex.guess(orig=orig, start=starts[0]))
|
|
|
|
|
# try to reach . from there
|
|
|
|
|
start = None
|
|
|
|
|
for s in starts:
|
|
|
|
|
t = ex.walk(loop, start=s)
|
|
|
|
|
print(f"walk {s} => {t}")
|
|
|
|
|
if t == Path():
|
|
|
|
|
start = s
|
|
|
|
|
print("use as start", start)
|
|
|
|
|
assert start
|
|
|
|
|
|
|
|
|
|
layout = ex.layout(orig=orig, start=starts[0])
|
|
|
|
|
guess_ok = api.guess(layout)
|
|
|
|
|
print("guess", guess_ok)
|
|
|
|
|
print("score", sum(e.score for e in exs))
|
|
|
|
|
return guess_ok
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def path_solve(problem, nrooms, plen):
|
|
|
|
|
@ -496,12 +498,15 @@ if __name__ == "__main__":
|
|
|
|
|
if problem not in problems:
|
|
|
|
|
raise ExploreError(f"unknown problem {problem}")
|
|
|
|
|
|
|
|
|
|
ok = False
|
|
|
|
|
try:
|
|
|
|
|
mark_solve(problem, problems[problem]["size"])
|
|
|
|
|
ok = mark_solve(problem, problems[problem]["size"])
|
|
|
|
|
api.clean_explore_cache()
|
|
|
|
|
except ExploreError as exc:
|
|
|
|
|
api.clean_explore_cache()
|
|
|
|
|
raise exc
|
|
|
|
|
print(exc)
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
api.write_explore_cache()
|
|
|
|
|
raise exc
|
|
|
|
|
print(exc)
|
|
|
|
|
|
|
|
|
|
sys.exit(0 if ok else 1)
|
|
|
|
|
|