You inherit a naive solver for a hidden-graph recovery problem: a hidden maze of rooms must be reconstructed by sending route
plans to an interactive judge and reading back the 2-bit labels seen along each
walk. The starter explores once and emits an essentially random guess, so it
almost never reconstructs the map. Your objective is to reconstruct maps
correctly while minimising the query cost (each /explore call costs the
number of route plans in it, plus one). Your solver is re-run on a sealed set of
fresh hidden maps for scoring; only correct reconstructions score, and lower
total cost is better.
Hard Constraints
- Interactive stdin/stdout protocol only. Your program talks to the judge over stdin/stdout (see below). Do not try to read the hidden map, the sealed seeds, the generator, or any file outside your own working directory.
- Submit a program, not answers.
methods/main/run.shmust reconstruct any instance it is given; per-instance hard-coded maps are invalid and fail on the sealed set. - Route-plan limits. Each plan is a string over doors
0-5with optional charcoal writes[label]door(label in0-3). A single plan may be at most18 * num_roomsdoorway steps long. - CPU only, no network, no extra processes beyond your solver. Python 3 and a C/C++ toolchain are available in both the workbench and the grader.
- Whatever sits in
methods/main/at the end is graded; there is no feedback from the sealed run.
What You Have
- The maze. Rooms each have 6 doors (
0-5) and a 2-bit label (0-3). Doors are wired into an undirected 6-regular graph (self-loops and parallel edges allowed). Exploration starts from a fixed room. This is the marks variant: the maze is a base graph multiplexed into 2 layers — every "super-room" has two copies that share a label and a locally identical neighbourhood, so many rooms look alike. Charcoal (rewriting a room's label mid-walk) is the tool that tells the layers apart. - The interactive judge (
tools/judge.py) and a generator/equivalence library (tools/aedificium.py) — the exact machinery used to score you, so you can test locally against identical instances. - A weak starter at
methods/main/(run.sh->solution.py): one random walk, then a random well-formed guess. Replace it. - A local dev bench (
selfcheck.py) that runs yourrun.shon the visible instances and prints your per-case query cost next to a reference cost. - Protocol. The judge sends
<num_rooms>. You then repeatedly sendexplore <plan1> <plan2> ...(it replies one line of space-separated labels per plan, length = plan length + 1), and finallyguessfollowed by your map: a line ofnum_roomslabels, a line with the starting room index, then one line per room of 12 integers (dest_room dest_doorfor each of doors0-5). A guess is accepted iff it is observationally equivalent to the true maze (no route plan could tell them apart).
What You Submit
A directory methods/main/ containing:
run.sh(required): launched once per instance; speaks the interactive protocol on stdin/stdout. Any language.build.sh(optional): if present, run once before grading (e.g. to compile). Do compilation there andexecyour binary fromrun.sh.
How It Is Judged
- For each sealed instance the judge plays the interactive session and records
your query cost on a correct reconstruction, or a failure (wrong guess,
crash, illegal query, or timeout). Query cost = for every
/explorecall, the number of plans in that call plus one; batching many plans into one call is cheaper than many calls. - Your per-case score rises as your cost drops toward a strong reference solver's cost, and solving every case comes first — an unsolved case scores zero. The aggregate is the mean across sealed cases; lower cost is strictly better.
- The reference cost per case ships with the visible set for calibration. How raw costs map to the final reward is deliberately not disclosed — optimise the raw cost and solve every instance.
Common Pitfalls
- Ignoring the layers. A no-charcoal reconstruction cannot distinguish the two copies of a super-room and will be rejected as inequivalent. Use charcoal writes to break the symmetry.
- Too many
/explorecalls. Each call adds a+1penalty; gather everything you can in as few batched calls as possible — a strong solver needs only one or two calls total. - Malformed guesses. The guess graph must be a valid involution: if door
dof roomigoes to(j, e), then dooreof roomjmust go back to(i, d). A malformed or wrong-sized guess fails the case. - Overlong plans. A single plan may not exceed
18 * num_roomssteps.