|
|
|
|
@ -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]))
|
|
|
|
|
|