Yajisan-Kazusan in the browser with five rule sets inside. An arrow
clue only has to be true when its own cell is unshaded. Shade the clue's cell
and the number may say anything at all — a clue is allowed to lie. Puzzle #51
in the solver series.
Demo: https://sen.ltd/portfolio/yajisan-kazusan/
Repo: https://github.com/sen-ltd/yajisan-kazusan
Rules
Shade some cells of an H×W grid.
- No two shaded cells are orthogonally adjacent.
- The unshaded cells form one connected region.
- Every clue is an arrow and a number written inside a cell. If that cell is unshaded, the number must equal how many shaded cells lie beyond it in the arrow's direction, out to the edge. If the cell is shaded, the clue is exempt — it may say anything.
Rule 3 is the whole puzzle. A clue is not an assertion about the grid; it is an
assertion conditional on one of the unknowns, namely its own cell. So a clue
can lie, provided it pays for the privilege by standing on a shaded cell.
Put differently, a Yajisan-Kazusan clue is a disjunction:
I am shaded, or my number is right.
The contrapositive is the engine
The useful half of a disjunction is what happens when the right-hand side dies.
A line of L cells can hold at most ⌈L/2⌉ shaded cells, because they may not
touch. So a clue whose number is bigger than that can never be true, and:
A clue carrying an unsayable number has confessed that its own cell is
shaded.
That is not a lemma, it is the solver's second rung. Measured on the shipped
boards — what fraction of the grid each rung's fixpoint settles:
| size | boards | adj |
cap |
ray |
white |
probe |
|---|---|---|---|---|---|---|
| 6×6 | 40 | 0.0% | 32.4% | 52.9% | 59.6% | 100.0% |
| 8×8 | 40 | 0.0% | 37.7% | 58.0% | 67.1% | 100.0% |
| 10×10 | 30 | 0.0% | 34.2% | 59.7% | 64.3% | 100.0% |
adj — "shaded cells never touch" — settles 0.0%, and of course it does:
nothing is shaded yet, so the adjacency rule has nothing to work from. The very
next rung, which does nothing whatsoever except catch clues lying, goes straight
to a third of the board.
So in this puzzle, everything the solver learns first, it learns from a
liar. The honest clues cannot start work until a liar has shaded a cell for
them.
A clue set always exists
The foundation first. For any legal answer there is always a clue set that pins
it down, and the proof is a two-case split that is literally the generator's
code.
Let A be the intended answer and B a rival answer we want to kill.
Case 1: some cell c is shaded in A and unshaded in B.
Put a clue in c. In A it is exempt, so its number is free. In B it is
binding, so any number other than B's actual count kills B.
Case 2: no such cell — i.e. A's shaded set is a proper subset of B's.
Take d, the last cell in raster order where the two disagree; it is shaded in
B, unshaded in A. Its right neighbour (or, at the row's end, its neighbour
below) is unshaded in B by rule 1, and it comes after d, so A and B agree
there — it is unshaded in both. Point an arrow from it back through d. Every
cell on that line other than d is a cell the two answers agree on, so the two
counts differ by exactly one. Write A's honest number and B dies.
Case 2 depends on rule 1, which is the interesting part. Without "shaded
cells never touch", there is no guarantee of a cell next to the disagreement that
is unshaded in both answers.
An all-liar clue set works exactly on maximal answers
Existence settled, now restrict the alphabet.
- Liar dialect: clues only on cells that end up shaded. Every clue is exempt.
- Honest dialect: clues only on cells that end up unshaded. Every clue is binding.
The liar dialect has a clean, exact answer.
Write an unsayable number on every shaded cell of the answer. Each one confesses,
so all those cells are forced shaded; nothing else is said at all. The answers to
that puzzle are therefore precisely the legal shadings that contain the
intended one. So:
- If no cell can be added to the answer while staying legal — the answer is ⊆-maximal — nothing else contains it, and it is unique.
- If a cell can be added, the bigger shading is a legal answer too, and every clue sits on a cell that the bigger answer also shades, where every clue is exempt. It survives. And this is not a fact about that clue set: a liar-only clue set can only ever live on the answer's shaded cells, so no liar-only clue set can work.
A liar-only clue set exists if and only if the answer is ⊆-maximal.
Both directions, on 540 answers:
| size | density | answers | maximal | of those, unique | non-maximal | of those, unique |
|---|---|---|---|---|---|---|
| 5×5 | 0.18 | 60 | 0 | 0 | 60 | 0 |
| 5×5 | 0.24 | 60 | 7 | 7 | 53 | 0 |
| 5×5 | packed | 60 | 60 | 60 | 0 | 0 |
| 6×6 | 0.18 | 60 | 0 | 0 | 60 | 0 |
| 6×6 | 0.24 | 60 | 10 | 10 | 50 | 0 |
| 6×6 | packed | 60 | 60 | 60 | 0 | 0 |
| 7×7 | 0.18 | 60 | 0 | 0 | 60 | 0 |
| 7×7 | 0.24 | 60 | 4 | 4 | 56 | 0 |
| 7×7 | packed | 60 | 60 | 60 | 0 | 0 |
All 201 maximal answers unique, none of the 339 non-maximal ones. No exceptions.
The honest dialect is the weaker one
Same greedy purchase, only the legal locations change.
Sparse answers (~20% shaded; at this density essentially none are maximal)
| size | boards | maximal | free-choice clues | liar-only works | honest-only works | honest-only clues |
|---|---|---|---|---|---|---|
| 6×6 | 40 | 0.0% | 11.9 | 0.0% | 22.5% | 14.1 |
| 8×8 | 40 | 0.0% | 21.1 | 0.0% | 10.0% | 23.0 |
Packed answers (nothing more fits, so all maximal)
| size | boards | maximal | free choice | liar-only works | liar-only clues | honest-only works | honest-only clues |
|---|---|---|---|---|---|---|---|
| 6×6 | 40 | 100% | 10.4 | 100% | 10.4 | 57.5% | 11.1 |
| 8×8 | 30 | 100% | 17.5 | 100% | 18.3 | 16.7% | 18.6 |
Read it like this:
- Where the liar dialect works at all, it costs the same as a free choice (10.4 vs 10.4 on 6×6, 18.3 vs 17.5 on 8×8). The restriction is nearly free.
- The honest dialect frequently does not work at all. On packed 8×8 answers it succeeds on 5 boards out of 30. That is not a price problem, it is an existence problem.
Earlier puzzles in this series kept landing on "both clue colours always exist,
the only question is the price". Yajisan-Kazusan breaks the pattern. The liars
are the expressive half of this puzzle's vocabulary; the honest clues are an
incomplete dialect.
Four clues in ten are liars, and not one of them is spare
Back from existence to measurement. Build the minimal clue set that buys
uniqueness, then count how many of those clues end up exempt in the answer:
| size | boards | clues | exempt | exempt share | unsayable | share | exempt but accidentally true |
|---|---|---|---|---|---|---|---|
| 6×6 | 40 | 478 | 217 | 45.4% | 90 | 18.8% | 20 |
| 8×8 | 40 | 842 | 366 | 43.5% | 184 | 21.9% | 26 |
| 10×10 | 30 | 931 | 379 | 40.7% | 206 | 22.1% | 25 |
Just over four in ten are liars, and about half of those carry a number the
line could never show — the confessions cap catches on pass one. The rest are
"sayable, but wrong here". And 7–9% of the exempt clues are accidentally
honest: nobody checks them, but their number happens to be right anyway.
Now minimality does the work. A minimal set means every clue is load-bearing, so
pull the liars out one at a time:
| size | exempt clues tried | still unique | answers after the drop (median) | max |
|---|---|---|---|---|
| 6×6 | 217 | 0 | 8 | 200+ |
| 8×8 | 366 | 0 | 10 | 200+ |
| 10×10 | 378 | 0 | 11 | 200+ |
961 liars removed one at a time, and not once did the board stay unique; the
median board sprouts 8–11 answers. A lying clue is not decoration. Removing one
collapses the board.
Look at it from the grid's side and the same thing shows up: only about a fifth
of the cells are shaded, but four tenths of the clues are sitting on them. Left
to itself, the adversarial buyer over-selects liars.
probe and uniqueness agree exactly
Two quantities this series measures every time:
- clues needed for uniqueness (unique-min)
- clues needed to be solvable without search (solve-min)
Previous entries showed a step of about 1.08×. Here:
| size | boards | unique-min | solve-min | ratio | grade histogram of the unique-min board |
|---|---|---|---|---|---|
| 6×6 | 40 | 11.9 | 11.9 | 1.00 | probe:35 white:5 |
| 8×8 | 40 | 21.1 | 21.1 | 1.00 | probe:32 white:8 |
| 10×10 | 30 | 31.0 | 31.0 | 1.00 | probe:26 white:4 |
No step at all. The moment a board becomes unique, singleton consistency can
finish it without a single guess.
The other direction, swept over 718 clue prefixes:
| size | prefixes |
probe completes |
unique | agree | probe not unique | unique not probe |
|---|---|---|---|---|---|---|
| 6×6 | 358 | 40 | 40 | 100.0% | 0 | 0 |
| 8×8 | 360 | 40 | 40 | 100.0% | 0 | 0 |
Zero disagreements in either direction, against 98.0% / 98.9% in the previous
entry. My guess at why is that this puzzle's constraints all fire from a single
cell — shade one cell and cap immediately provokes a confession, while adj
and white both propagate outward from one cell — but that is a guess, and I am
only claiming the observation.
Ablation: the row that argues with the headline
Take the full stack and drop exactly one rung.
| size | variant | fixpoint bits | boards moved | probes | search assumptions | over budget |
|---|---|---|---|---|---|---|
| 6×6 | full | 1440 | 0 | 436 | 0 | 0 |
| 6×6 | −adj | 127 | 40 | 3892 | 2,387,173 | 39 |
| 6×6 | −cap | 1421 | 1 | 2040 | 4 | 0 |
| 6×6 | −ray | 1339 | 6 | 2210 | 28 | 0 |
| 6×6 | −white | 1106 | 37 | 1652 | 4854 | 0 |
| 6×6 | −probe | 858 | 35 | 0 | 426 | 0 |
| 8×8 | full | 2560 | 0 | 800 | 0 | 0 |
| 8×8 | −adj | 244 | 40 | 7358 | 2,400,558 | 40 |
| 8×8 | −cap | 2492 | 2 | 3828 | 10 | 0 |
| 8×8 | −ray | 2324 | 8 | 4110 | 208 | 0 |
| 8×8 | −white | 2072 | 38 | 2512 | 23,674 | 0 |
| 8×8 | −probe | 1717 | 32 | 0 | 2244 | 0 |
| 10×10 | full | 3000 | 0 | 840 | 0 | 0 |
| 10×10 | −adj | 252 | 30 | 8476 | 1,800,166 | 30 |
| 10×10 | −cap | 2957 | 1 | 4642 | 2 | 0 |
| 10×10 | −ray | 2474 | 20 | 6510 | 790 | 0 |
| 10×10 | −white | 2661 | 25 | 2328 | 22,448 | 0 |
| 10×10 | −probe | 1928 | 26 | 0 | 7478 | 0 |
(The −adj rows exhaust the 60,000-node search budget on almost every board —
39 of 40 on 6×6, all of them on 8×8 and 10×10 — so those counts only mean "at
least this much".)
There is a row here that points the opposite way from this article's headline.
Dropping cap breaks almost nothing. On 6×6 the fixpoint goes from 1440 bits
to 1421, exactly one board out of forty moves, and search assumptions go from 0
to 4. On 10×10, one board.
It is not a contradiction. The ladder table measures each rung stacked from the
bottom, where cap is the only source of information there is. The ablation
measures dropping a rung from the top, with probe still switched on — and
singleton consistency rediscovers cap by itself, because "assume this cell is
unshaded → its arrow must be true → contradiction" is a single-cell probe.
So cap is a cheap shortcut, not a necessary axiom — and the cost shows up
in the probe counter rather than in the answer: dropping cap sends probe
invocations from 436 to 2040 on 6×6 and from 800 to 3828 on 8×8, about 4.7×. The
same conclusion, bought back at five times the price.
Dropping adj, on the other hand, is a collapse, and it should be: adj is what
supports the ⌈L/2⌉ bound cap rests on and the in-line adjacency the ray DP
respects. Every deduction in this puzzle is built on rule 1.
How far away is the second answer
Every entry in this series asks whether a second answer is explained by a small,
search-free certificate. Drop one clue from a minimal board to make it ambiguous,
then count how many cells the impostor moves:
| size | ambiguous boards | cells moved (avg) | ≤2 | 3–4 | ≥5 | of those cells, on a clue |
|---|---|---|---|---|---|---|
| 6×6 | 40 | 3.13 | 45.0% | 37.5% | 17.5% | 40.8% |
| 8×8 | 40 | 5.53 | 25.0% | 22.5% | 52.5% | 38.9% |
| 10×10 | 30 | 4.17 | 43.3% | 23.3% | 33.3% | 31.2% |
On 6×6, 45% of impostors move two cells or fewer; on 8×8, over half move five or
more. The bigger the board, the less a second answer looks like a local
swap.
And a third to two fifths of the moved cells are clue cells themselves, which
falls straight out of the exemption mechanic: flip a clue cell between shaded and
unshaded and you flip whether that clue is checked at all. Second answers are
usually built by switching clues on and off.
External ledgers
Internal consistency proves nothing, so the counts are nailed to numbers that
exist outside the repository. Switch off rule 2 (connectivity) and drop every
clue, and what is left is just "shade without touching" — the independent sets of
the grid graph:
| grid | counts | OEIS |
|---|---|---|
| n×n, n=1..5 | 2, 7, 63, 1234, 55447 | A006506, non-attacking princes |
| 2×n, n=1..8 | 3, 7, 17, 41, 99, 239, 577, 1393 | A001333, Pell–Lucas |
| 3×n, n=1..7 | 5, 17, 63, 227, 827, 2999, 10897 | A051736 |
Three engines produce those numbers and they share no code. bruteByRows stacks
row bitmasks and never looks at a cell. bruteByCells walks cells in raster
order and never builds a mask. independentSetCount does not enumerate at all —
it is a transfer matrix, so it still answers for 7×7 (1,280,128,950) long after
the enumerators have given up.
Switch connectivity back on and the n×n diagonal becomes 1, 5, 39, 562,
20297, which is not in OEIS as of 2026-08. That absence is not a claim about
anything, but the values are baked into the tests.
The 1×n strip has a closed form you can do by hand: on a strip, "the unshaded
cells are connected" means they are one run, so only the two ends can be shaded,
and (for n ≥ 3) the ends do not touch each other. That gives {}, {left},
{right}, {both} — 4 for every n ≥ 3 (1 for n=1, 3 for n=2). Both
enumerators and the solver agree at every n.
The five rungs
| rung | what it is |
|---|---|
adj |
the four neighbours of a shaded cell are unshaded |
cap |
a number the line could never show means the clue's own cell is shaded |
ray |
once a clue cell is known unshaded its arrow is honest: a DP along the line |
white |
connectivity of the unshaded region — unreachable cells and cut cells |
probe |
singleton consistency |
Only ray needs code shown. For a line r_1..r_L, run a DP that keeps the set of
reachable totals as a bitmask while respecting adjacency inside the line:
export function rayTotals(cells, rr, work, force = -1, forceVal = WHITE): number {
let d0 = 1; // reachable totals with the previous cell unshaded
let d1 = 0; // ... with the previous cell shaded
for (let i = 0; i < rr.length; i++) {
const s = i === force ? forceVal : cells[rr[i]];
let n0 = 0, n1 = 0;
if (s !== SHADED) n0 = d0 | d1; // leave it unshaded
if (s !== WHITE) n1 = (d0 << 1) & 0x7fffffff; // shade it: previous must be unshaded
d0 = n0; d1 = n1;
if (d0 === 0 && d1 === 0) return 0;
}
return d0 | d1;
}
One function, three uses:
-
cap— assume the clue's cell is unshaded and run it. If the number is not in the reachable set, the assumption is false: the cell is shaded. -
ray— with the clue cell known unshaded, pin each undecided line cell both ways withforce. If only one way can still reach the number, write it. - It ignores adjacency outside the line, which makes it a relaxation: it never rules out anything real, and it sharpens as the grid fills in.
The ⌈L/2⌉ bound is not implemented as a separate constant anywhere. Run
rayTotals on an empty line and the largest reachable total is ⌈L/2⌉; the
tests check that for L = 0..10. The bound is a corollary of the DP's first
pass, not a rule of its own.
Generation
Answer-first. Walk the cells in random order and shade one whenever that keeps
both "no touching" and "the unshaded cells stay connected". No rejection, no
retry — by the time you stop, you already have a legal answer. Set the density
parameter to 1 and it packs until nothing more fits (which needs a fixpoint, not
one pass), and that gives the maximal answers the liar theorem needs.
Clues are then bought adversarially by enumerating exactly the two cases from the
existence proof, then minimised by shuffling and dropping one at a time. Every
clue on a shipped board is load-bearing, and a test removes each one to prove it.
Vary the density and the price runs the opposite way to intuition:
| size | density | avg shaded | maximal | answers with no clues | clues for uniqueness |
|---|---|---|---|---|---|
| 6×6 | 0.14 | 5.0 | 0.0% | 1,646,096 | 12.8 |
| 6×6 | 0.18 | 6.0 | 0.0% | 1,646,096 | 12.9 |
| 6×6 | 0.22 | 8.0 | 0.0% | 1,646,096 | 11.8 |
| 6×6 | packed | 10.3 | 100% | 1,646,096 | 10.3 |
Twice as many shaded cells, fewer clues needed. More shaded cells means more
exempt seats to write a clue into, and a clue in an exempt seat has a free
choice of number — which is the maximum possible freedom to kill a rival. The
more places an answer lets a clue lie, the cheaper it is to make unique.
Tests
61 of them: the line DP against brute force for every length 0–10; the asymmetry
of rule 3 (rewrite an exempt clue's number to anything and the answer survives;
move a binding clue's number by one and it dies); monotonicity in both senses
(more clues never adds answers, a stronger rung never decides less); propagation
never writing a cell the answer disagrees with; three engines agreeing on both
counts and answer sets; the external ledgers; both directions of the liar
theorem; and the shipped bank being unique, honestly graded and free of spare
clues.
Layout
src/yajisan-kazusan.ts model, five rule sets, propagation, search, referee
src/brute.ts two enumerators sharing no code with the solver, plus a transfer matrix
src/generate.ts answer-first generation and adversarial clue buying
tools/stats.mts every table in this article
Demo: https://sen.ltd/portfolio/yajisan-kazusan/
Repo: https://github.com/sen-ltd/yajisan-kazusan

Top comments (0)