|
|
|
|
@ -140,9 +140,7 @@ class Explore:
|
|
|
|
|
# self.dump()
|
|
|
|
|
|
|
|
|
|
p, rid = self.neighbors[pl][d]
|
|
|
|
|
assert (
|
|
|
|
|
rid is None or rid == room_id
|
|
|
|
|
), f"penultimate {path} {pl}: {rid} != {room_id}"
|
|
|
|
|
assert rid is None or rid == room_id, f"penultimate {path} {pl}: {rid} != {room_id}"
|
|
|
|
|
self.neighbors[pl][d] = (p, room_id)
|
|
|
|
|
|
|
|
|
|
# self.dump()
|
|
|
|
|
@ -185,9 +183,7 @@ class Explore:
|
|
|
|
|
assert path2 in self.rooms, 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)
|
|
|
|
|
@ -196,13 +192,9 @@ class Explore:
|
|
|
|
|
self.unification_id[pmerge] = path
|
|
|
|
|
|
|
|
|
|
merged_neighbors = []
|
|
|
|
|
for n, ((p, rid), (pm, rmid)) in enumerate(
|
|
|
|
|
zip(self.neighbors[path], self.neighbors[pmerge])
|
|
|
|
|
):
|
|
|
|
|
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"
|
|
|
|
|
)
|
|
|
|
|
raise ExploreError(f"neighbor {n} of '{path}'({rid}) and '{pmerge}'({rmid}) do not match")
|
|
|
|
|
if rmid:
|
|
|
|
|
merged_neighbors.append((self._path(pm), rmid))
|
|
|
|
|
else:
|
|
|
|
|
@ -233,9 +225,7 @@ class Explore:
|
|
|
|
|
new.append((np_, rid))
|
|
|
|
|
if rid:
|
|
|
|
|
try:
|
|
|
|
|
assert (
|
|
|
|
|
np_ in self.rooms
|
|
|
|
|
), f"unify: path {np} {np_} of {(p, ns)} not in rooms"
|
|
|
|
|
assert np_ in self.rooms, f"unify: path {np} {np_} of {(p, ns)} not in rooms"
|
|
|
|
|
except AssertionError as exc:
|
|
|
|
|
self.dump()
|
|
|
|
|
raise exc
|
|
|
|
|
@ -261,11 +251,9 @@ class Explore:
|
|
|
|
|
yield d, path
|
|
|
|
|
|
|
|
|
|
def is_explored(self):
|
|
|
|
|
return next(self.unexplored(), None) is None and all(
|
|
|
|
|
len(p) == 1 for p in self.room_ids.values()
|
|
|
|
|
)
|
|
|
|
|
return next(self.unexplored(), None) is None and all(len(p) == 1 for p in self.room_ids.values())
|
|
|
|
|
|
|
|
|
|
def guess(self, orig=None):
|
|
|
|
|
def guess(self, orig=None, start=Path()):
|
|
|
|
|
aedi = graph.Aedificium(self.problem)
|
|
|
|
|
|
|
|
|
|
ids = {}
|
|
|
|
|
@ -280,22 +268,15 @@ class Explore:
|
|
|
|
|
for src_door, (trg_path, _) in enumerate(ns):
|
|
|
|
|
src = (src_path, src_door)
|
|
|
|
|
trg_door = next(
|
|
|
|
|
(
|
|
|
|
|
j
|
|
|
|
|
for j, (p, rid) in enumerate(self.neighbors[trg_path])
|
|
|
|
|
if p == src_path
|
|
|
|
|
),
|
|
|
|
|
(j for j, (p, rid) in enumerate(self.neighbors[trg_path]) if p == src_path),
|
|
|
|
|
None,
|
|
|
|
|
)
|
|
|
|
|
if trg_door is None:
|
|
|
|
|
raise ExploreError(
|
|
|
|
|
f"backlink not found: {(src, trg_path, self.neighbors[trg_path])}"
|
|
|
|
|
)
|
|
|
|
|
raise ExploreError(f"backlink not found: {(src, trg_path, self.neighbors[trg_path])}")
|
|
|
|
|
trg = (trg_path, trg_door)
|
|
|
|
|
|
|
|
|
|
if (src, trg) in connected or (trg, src) in connected:
|
|
|
|
|
continue
|
|
|
|
|
print(src, trg)
|
|
|
|
|
connected.add((src, trg))
|
|
|
|
|
connections.append(
|
|
|
|
|
{
|
|
|
|
|
@ -314,7 +295,7 @@ class Explore:
|
|
|
|
|
|
|
|
|
|
layout = {
|
|
|
|
|
"rooms": [int(rooms[p]) for p in ids.keys()],
|
|
|
|
|
"startingRoom": ids[Path()],
|
|
|
|
|
"startingRoom": ids[start],
|
|
|
|
|
"connections": connections,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -329,7 +310,7 @@ class Explore:
|
|
|
|
|
return ret
|
|
|
|
|
|
|
|
|
|
for d, (q, _) in enumerate(self.neighbors[p]):
|
|
|
|
|
queue.append((q, Path([d])))
|
|
|
|
|
queue.append((q, ret + Path([d])))
|
|
|
|
|
|
|
|
|
|
assert False, "return path not found"
|
|
|
|
|
|
|
|
|
|
@ -367,75 +348,87 @@ def room_solve(problem, nrooms, plen):
|
|
|
|
|
print("score", ex.score)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_mark(rid):
|
|
|
|
|
return Path("[" + str(int(rid[0]) ^ 3) + "]")
|
|
|
|
|
def get_mark(rid, mask):
|
|
|
|
|
return Path("[" + str(int(rid[0]) ^ mask) + "]")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def mark_solve(problem, nrooms, plen):
|
|
|
|
|
ex0 = Explore(problem, [d + d + d + d + d + d for d in DOORS[:plen]])
|
|
|
|
|
api.select(ex0.problem)
|
|
|
|
|
res = ex0.explore(Path())
|
|
|
|
|
def apply_mask(rid, mask):
|
|
|
|
|
return "".join(map(lambda d: str(int(d) & ~mask), rid))
|
|
|
|
|
|
|
|
|
|
ex0.update(Path(), res)
|
|
|
|
|
ex0.dump()
|
|
|
|
|
|
|
|
|
|
while True:
|
|
|
|
|
door, unexplored = next(ex0.unexplored(), (None, None))
|
|
|
|
|
if unexplored is None:
|
|
|
|
|
break
|
|
|
|
|
def mark_solve(problem, nrooms):
|
|
|
|
|
probes = [d + d + d + d + d + d for d in DOORS[:2]]
|
|
|
|
|
api.select(problem)
|
|
|
|
|
|
|
|
|
|
print("explore", door, unexplored)
|
|
|
|
|
path = unexplored + Path([door])
|
|
|
|
|
res = ex0.explore(path)
|
|
|
|
|
ex0.update(path, res)
|
|
|
|
|
ex0.dump()
|
|
|
|
|
masks = [0, 1, 2]
|
|
|
|
|
exs = []
|
|
|
|
|
loop = Path()
|
|
|
|
|
mark_loop = Path()
|
|
|
|
|
|
|
|
|
|
ex0.unify_all()
|
|
|
|
|
ex0.dump()
|
|
|
|
|
for mask in masks:
|
|
|
|
|
print("exploration mask", mask)
|
|
|
|
|
if mask != 0:
|
|
|
|
|
for p, rid in exs[-1].rooms.items():
|
|
|
|
|
q = exs[-1].returnfrom(p)
|
|
|
|
|
loop = loop + p + q
|
|
|
|
|
mark_loop = mark_loop + p + get_mark(rid, mask) + q
|
|
|
|
|
|
|
|
|
|
print("found all rooms")
|
|
|
|
|
mark = Path()
|
|
|
|
|
for p, rid in ex0.rooms.items():
|
|
|
|
|
q = ex0.returnfrom(p)
|
|
|
|
|
mark = mark + p + get_mark(rid) + q
|
|
|
|
|
print("marked", mark_loop, loop)
|
|
|
|
|
assert exs[-1].walk(loop) == Path(), f"loop doesn't close {exs[-1].walk(loop)}"
|
|
|
|
|
|
|
|
|
|
print("marked", mark)
|
|
|
|
|
ex = Explore(problem, probes)
|
|
|
|
|
exs.append(ex)
|
|
|
|
|
|
|
|
|
|
ex1 = Explore(problem, [d + d + d + d + d + d for d in DOORS[:plen]])
|
|
|
|
|
res = ex1.explore(Path(), mark=mark)
|
|
|
|
|
ex1.update(Path(), res)
|
|
|
|
|
ex1.dump()
|
|
|
|
|
res = ex.explore(Path(), mark=mark_loop)
|
|
|
|
|
ex.update(Path(), res)
|
|
|
|
|
ex.dump()
|
|
|
|
|
|
|
|
|
|
while True:
|
|
|
|
|
door, unexplored = next(ex1.unexplored(), (None, None))
|
|
|
|
|
if unexplored is None:
|
|
|
|
|
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, mark=mark_loop)
|
|
|
|
|
ex.update(path, res)
|
|
|
|
|
ex.unify_all()
|
|
|
|
|
ex.dump()
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
print("explore", door, unexplored)
|
|
|
|
|
path = unexplored + Path([door])
|
|
|
|
|
res = ex1.explore(path, mark=mark)
|
|
|
|
|
ex1.update(path, res)
|
|
|
|
|
ex1.dump()
|
|
|
|
|
|
|
|
|
|
ex1.unify_all()
|
|
|
|
|
ex1.dump()
|
|
|
|
|
|
|
|
|
|
print("explored", ex1.is_explored())
|
|
|
|
|
if ex1.is_explored():
|
|
|
|
|
# get old markings
|
|
|
|
|
orig = {}
|
|
|
|
|
for path in ex1.rooms.keys():
|
|
|
|
|
p = ex0.walk(path)
|
|
|
|
|
rid = ex0.rooms[p]
|
|
|
|
|
orig[path] = rid[0]
|
|
|
|
|
print(path, p, rid)
|
|
|
|
|
|
|
|
|
|
ex0.dump()
|
|
|
|
|
ex1.dump()
|
|
|
|
|
print(orig)
|
|
|
|
|
print("guess", ex1.guess(orig=orig))
|
|
|
|
|
print("score", ex0.score + ex1.score)
|
|
|
|
|
assert False
|
|
|
|
|
if len(ex.rooms) != nrooms:
|
|
|
|
|
raise ExploreError(f"not all rooms could be identifed {len(ex.rooms)}/{nrooms}")
|
|
|
|
|
for e in exs:
|
|
|
|
|
e.dump()
|
|
|
|
|
|
|
|
|
|
# get old markings
|
|
|
|
|
orig = {}
|
|
|
|
|
for path in ex.rooms.keys():
|
|
|
|
|
p = exs[0].walk(path)
|
|
|
|
|
rid = exs[0].rooms[p]
|
|
|
|
|
orig[path] = rid[0]
|
|
|
|
|
print(path, p, rid)
|
|
|
|
|
print(orig)
|
|
|
|
|
# try to identify original start
|
|
|
|
|
start = apply_mask(exs[0].rooms[Path()], mask)
|
|
|
|
|
starts = []
|
|
|
|
|
all_masked = []
|
|
|
|
|
for p, rid in ex.rooms.items():
|
|
|
|
|
mrid = apply_mask(rid, mask)
|
|
|
|
|
all_masked.append(mrid)
|
|
|
|
|
if mrid == start:
|
|
|
|
|
starts.append(p)
|
|
|
|
|
print("start", start, starts, all_masked)
|
|
|
|
|
assert len(starts) > 0
|
|
|
|
|
|
|
|
|
|
print("guess", ex.guess(orig=orig, start=starts[0]))
|
|
|
|
|
print("score", sum(e.score for e in exs))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def path_solve(problem, nrooms, plen):
|
|
|
|
|
@ -498,23 +491,17 @@ if __name__ == "__main__":
|
|
|
|
|
with open(os.path.join("..", "problems.json")) as h:
|
|
|
|
|
problems = json.loads(h.read())
|
|
|
|
|
|
|
|
|
|
problems = {
|
|
|
|
|
p["problem"]: {"size": p["size"], "idx": i} for i, p in enumerate(problems)
|
|
|
|
|
}
|
|
|
|
|
problems = {p["problem"]: {"size": p["size"], "idx": i} for i, p in enumerate(problems)}
|
|
|
|
|
|
|
|
|
|
if problem not in problems:
|
|
|
|
|
raise ExploreError(f"unknown problem {problem}")
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
if problems[problem]["idx"] < 6:
|
|
|
|
|
room_solve(problem, problems[problem]["size"], int(sys.argv[2]))
|
|
|
|
|
else:
|
|
|
|
|
mark_solve(problem, problems[problem]["size"], int(sys.argv[2]))
|
|
|
|
|
|
|
|
|
|
mark_solve(problem, problems[problem]["size"])
|
|
|
|
|
api.clean_explore_cache()
|
|
|
|
|
# except ExploreError as exc:
|
|
|
|
|
# api.clean_explore_cache()
|
|
|
|
|
# raise exc
|
|
|
|
|
except ExploreError as exc:
|
|
|
|
|
api.clean_explore_cache()
|
|
|
|
|
raise exc
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
api.write_explore_cache()
|
|
|
|
|
raise exc
|
|
|
|
|
|