← all problems

Find the seeds

The problem

Six colours grew outwards across a 7 by 7 grid, one step at a time, each from a single hidden starting cell. Walls block growth. Every cell went to whichever colour reached it first, and a tie went to the lower colour number. You are given the finished map and nothing else. Name the six starting cells.

Formally, the owner of an open cell is the colour minimising (distance from its seed, colour number), with distance measured on 4-neighbour paths through open cells. Every instance has exactly one six-tuple of seeds that reproduces its map.

Instance and solver

wall proposed seed correct wrong the true seed

Run

Another instance

Or edit the map

Seven rows of seven characters. 1 to 6 are territories, # is a wall. Eight walls, the open cells connected, at least three cells per colour. Any map is accepted; the page reports how many seed tuples reproduce it.

Symbols

The board is 56 cells. Rows 0 to 6 are the map and are never written. Row 7 holds the six answer cells, one per colour in colour order, plus one padding cell that carries nothing. The model does not see row 7 as indices. It sees the current guess drawn on the map as six rings, and row 7 recoded as how many cells each colour currently gets wrong. Both directions are exact code in this page, not inference.

The model

RoleStatusTest exactOOD exact OOD ratioParametersONNX bytes

Export and board

Parity of the exported graph

How the page runs the model

Two graphs ship. seed-placer_init.onnx maps the board to the starting answer state. seed-placer_step.onnx runs one supervision step and returns the predicted board, the next state, and a halting probability. The loop is not in the graph. This page drives it:

let {y0: y, z0: z} = await init.run({x});
for (let s = 0; s < sup_steps; s++) {
  const out = await step.run({x, y, z});
  render(out.pred);
  y = out.y_out; z = out.z_out;
  if (out.halt.data[0] > halt_threshold) break;
}

Every step is drawn, including the ones that are still wrong. Around that inner loop is an outer one. The board is a tandem board: after each pass the page recomputes the six rings and the wrongness row from whatever tuple is now persisted, and hands the model the refreshed view. A pass is written to the board only if regrowing its tuple gets strictly fewer of the 41 open cells wrong than the tuple already there. Ties and regressions keep the incumbent, so the persisted answer walks a bounded integer downwards and the loop cannot oscillate. It stops at a fixpoint or after six rounds.

The instance generator and the reference solver are reimplemented in JavaScript here from the same construction the training data used. The solver is exact: each constraint the map imposes mentions at most two colours, so the seeds are the solutions of a six-variable binary constraint problem, solved by arc consistency and then a small search. The generator uses a different random source from the Python one, so the same seed number gives a different instance.