From 4fdade25dc7704e9d4d132077ea52a29740f8b78 Mon Sep 17 00:00:00 2001 From: Harald Holtmann Date: Sat, 6 Sep 2025 08:55:03 +0200 Subject: [PATCH] use path probing --- harald/explore.py | 79 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 64 insertions(+), 15 deletions(-) diff --git a/harald/explore.py b/harald/explore.py index 3d9e112..5810489 100755 --- a/harald/explore.py +++ b/harald/explore.py @@ -5,6 +5,7 @@ import functools import json import os.path import sys +import random from collections import defaultdict @@ -15,6 +16,8 @@ class ExploreError(Exception): @functools.total_ordering class Path: def __init__(self, path=""): + if isinstance(path, list): + path = "".join(str(p) for p in path) self.path = path def __repr__(self): @@ -35,8 +38,11 @@ class Path: def __format__(self, spec): return str(self).__format__(spec) - def extend(self, door): - return Path(self.path + str(door)) + def __add__(self, other): + return Path(self.path + other.path) + + def __len__(self): + return len(self.path) def last(self): return Path(self.path[:-1]), int(self.path[-1]) @@ -48,9 +54,13 @@ class Path: return self +DOORS = [Path(str(i)) for i in range(6)] + + class Explore: - def __init__(self, problem): + def __init__(self, problem, probes): self.problem = problem + self.probes = probes self.rooms = {} self.room_ids = defaultdict(lambda: set()) self.neighbors = {} @@ -58,6 +68,8 @@ class Explore: self.unification_id = {} self.unifications = defaultdict(lambda: set()) + self.score = 0 + def _path(self, path): return self.unification_id.get(path, path) @@ -87,28 +99,36 @@ class Explore: if path in self.rooms: return self.rooms[path] - paths = [path.extend(i) for i in range(6)] - self.neighbors[path] = [(p, None) for p in paths] + paths = [path + probe for probe in self.probes] print("explore", paths) - results = api.explore([p.path for p in paths])["results"] + response = api.explore([p.path for p in paths]) + results = response["results"] + self.score = response["queryCount"] print("id", path, results) - label = results[0][-2] - neighbors = [r[-1] for r in results] + self.update(path, [res[len(path) :] for res in results]) - room_id = str(label) + "".join(str(n) for n in neighbors) + def update(self, path, results): + """ + path: path to update + probe: prob result from path. + """ + label = results[0][0] + probe_ids = [r for res in (rs[1:] for rs in results) for r in res] + print(path, results, probe_ids) + room_id = str(label) + "".join(str(p) for p in probe_ids) self.rooms[path] = room_id self.room_ids[room_id].add(path) - # update pen-ultimate room + self.neighbors[path] = [(path + d, None) for d in DOORS] + + # update penultimate room if path: pl, dl = path.last() p, _ = self.neighbors[pl][dl] self.neighbors[pl][dl] = (p, room_id) - return room_id - def dump(self): print(self.problem + " rooms:") for r, rid in self.rooms.items(): @@ -227,8 +247,36 @@ class Explore: return api.guess(layout) -def solve(problem): - ex = Explore(problem) +def room_solve(problem): + ex = Explore(problem, DOORS) + 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.unify_all() + ex.dump() + + print("explored", ex.is_explored()) + if ex.is_explored(): + print("guess", ex.guess()) + print("score", ex.score) + + +def path_solve(problem, plen): + probe = [Path([random.randrange(6) for _ in range(plen)])] + print("probe path", probe) + + ex = Explore(problem, probe) api.select(ex.problem) ex.explore() ex.dump() @@ -249,6 +297,7 @@ def solve(problem): print("explored", ex.is_explored()) if ex.is_explored(): print("guess", ex.guess()) + print("score", ex.score) if __name__ == "__main__": @@ -264,4 +313,4 @@ if __name__ == "__main__": if problem not in problems: raise ExploreError(f"unknown problem {problem}") - solve(problem) + path_solve(problem, int(sys.argv[2]))