DEV Community

SEN LLC
SEN LLC

Posted on

Tasquare: because 0 is an illegal clue, the board leaks its answer before you read a single digit

Tasquare in the browser with a five-rung solver. Shade cells so that
every connected block is a square, the unshaded cells stay in one
region
, and a number is the total area of the squares touching it. The
clause doing the work is the fifth one in the reference implementation —
every numbered cell has shading beside it — because together with the fourth
it makes a clue of 0 illegal. There is no way to write "nothing here", so
a number can only be printed on the outline of the shading, and the board
leaks its answer before you read a digit. Measured exactly: at 5×5 a clue's
position alone cuts the space to 52.6%; on a shipped 6×6 board the
positions alone cut 2,804,105 answers down to a median of 10,692 — a
262× reduction that costs the setter nothing. A profile DP counts answers
exactly (308,954,964,834 at 8×8; 79,483,030,837,772,295,689,698,468 at
12×12 in 139 s), agrees with three OEIS sequences, and prices the two clauses
nobody prints at 165,127× against 5.20×. 51 tests. Puzzle #65 in the
solver series.

Live demo: https://sen.ltd/portfolio/tasquare/
Source: https://github.com/sen-ltd/tasquare

Tasquare

The rules

  • Shade some cells.
  • Every connected block of shaded cells must be a square. Two squares may therefore never touch side by side — they would fuse into a block that is not a square.
  • The cells you leave unshaded must form one connected region.
  • A number is the total area of the squares that touch its cell by a side. A numbered cell is never shaded itself.

Before writing a line I read the reference implementation, tasquare.js from
pzprjs, as the primary source. Its answer check is a list of five:

checklist: [
  "checkShadeCellExist",   // something is shaded
  "checkSquareShade",      // every block is a square
  "checkConnectUnshade",   // the unshaded cells are one region
  "checkSumOfSize",        // a number is the total area of the squares beside it
  "checkAtLeastOne",       // a numbered cell has at least one shaded neighbour
  "doneShadingDecided",
]
Enter fullscreen mode Exit fullscreen mode

One line decides the whole genre: 0 is not a legal clue

The fifth entry, checkAtLeastOne, is the one everybody skims. Set it next to
the fourth and it starts doing work:

  • checkSumOfSize demands total = the number
  • checkAtLeastOne demands total > 0

So a clue of 0 can never be satisfied. There is no board on which both
clauses hold for a zero.

That is not merely "zero is unavailable, slightly awkward". It means the setter
has no way to write "nothing here". The negative information that Nurikabe
gets from a white cell, this genre cannot print at all.

And flipped around: the only cells that can carry a number are the outline of
the shading
. Counting on the shipped boards:

board cells cells that could carry a number share of the grid numbers actually printed
6×6 36 20 54.6% 10 (48.4% of them)
8×8 64 36 55.8% 16 (44.8%)
10×10 100 56 56.1% 25 (43.3%)

So a Tasquare board leaks its answer twice: through the numbers, and through
where the numbers were allowed to go. The second leak is information the
setter cannot withhold.

Pricing "a number may be printed here", exactly

At 5×5 the whole answer space is 29,459 boards and fits in memory, so this is
not an estimate. For every cell and every value it can carry, count how many
answers survive that one clue:

what you are told about one cell answers left (median) share sharpest bluntest
a number may be printed here 15,498 52.6% 31.6% 58.5%
…and here is its value 496 1.7% 0.0068% 35.1%

The position alone throws away nearly half of everything. Reading the digit
as well takes it another 31× down. That the value is worth more is the sensible
result; the surprise is that the position is worth anything at all, because it
is free.

Put a whole board's worth of positions together and it compounds. Take a shipped
6×6 board, rub out every digit but leave the numbers where they sit, and
count exactly how many of the 2,804,105 answers could have produced that
arrangement:

  • median 10,692 (0.38% of the space)
  • best 296, worst 101,016

The blank board has already done a 262× cut. The printed digits only have to
do the remaining 10,692-to-1.

Counting the genre to the last digit

An answer, before any number is read, is a shading where every block is a square
and the unshaded cells are one region. That is a countable object.

I wrote a row-at-a-time profile DP. Two observations make each row cheap:

  1. Squares may not touch, so a maximal run of shaded cells inside one row is exactly one square's slice, and its length is that square's side.
  2. A square that started earlier occupies the very same columns in every row it covers.

So the whole shaded structure rides on one small number per column — how many
more rows does the square above me still owe
— and the white structure on the
usual connectivity labels.

grid answers frontier states time
4×4 739 29 2 ms
6×6 2,804,105 237 22 ms
8×8 308,954,964,834 1,977 314 ms
10×10 946,392,348,293,841,287 16,631 6,764 ms
12×12 79,483,030,837,772,295,689,698,468 142,595 138,904 ms

Up to 5×5 this agrees with a full enumeration that shares no code with the sweep
beyond the row generator. Searching the OEIS in September 2026 for
1, 5, 43, 739, 29459, 2804105, 612730385 returns nothing.

Two clauses nobody prints, priced exactly

The rule has two structural clauses that appear nowhere on the board — every
block is a square
and the unshaded cells are one region. The same sweep counts
what the grid would allow without each of them.

how the rule is read 4×4 6×6 8×8 cost at 8×8
both clauses (correct) 739 2,804,105 308,954,964,834
the white cells may split 1,558 9,286,872 1,605,367,953,984 5.20×
blocks need not be squares 11,506 1,732,082,741 51,016,818,604,894,742 165,127×
neither clause 65,535 68,719,476,735 18,446,744,073,709,551,615 59,706,903×

They are not remotely the same size. Essentially all the structure in this
genre lives in the word "square"; connectivity is a rounding error beside it.

Three of those four rows are sequences somebody else already published, which
makes them a check rather than a claim:

  • neither clause → every subset of the grid, so 2^(n²) − 1.
  • square clause off, white region kept → subsets whose complement is connected, which is A059525, the connected induced subgraphs of the grid graph. The sweep matches it to 284,374,318,545,830,329,487,309,785 at 10×10.
  • squares capped at 1×1, splits allowed → exactly the independent sets of the grid graph, A006506. Matches to 660,647,962,955 at 8×8.

That last one is my favourite: cap the squares at a single cell and Tasquare
degenerates into counting independent sets on a grid.

Apply the same cap under the real rules and you learn something else. Of the
308,954,964,834 answers at 8×8, 118,930,018,897 (38.5%) use nothing but 1×1
squares
. The thing the genre is named after shows up on a bit under two thirds
of boards, and a setter who wants a big square in the picture is already fishing.

What a typical answer looks like

The DP carries two extra accumulators, so the same pass returns the exact mean
shaded count and the exact number of squares of each side across the whole
space — not a sample of it.

Across all 946,392,348,293,841,287 answers at 10×10:

  • mean shaded cells 23.69 (23.7% of the grid)
  • mean number of squares 19.44
  • per answer: 18.10 are 1×1, 1.30 are 2×2, 0.04 are 3×3

The tail is small enough to check by hand, which is the nicest part. Across
every one of those 946 quadrillion answers there are exactly 4 appearances
of a 9×9 square and exactly 1 of a 10×10. Both are obvious once said — a
9×9 has four places to sit and the leftover width-1 strip is entirely adjacent
to it, so nothing else can be shaded; a 10×10 has one place and leaves no white
at all — and both fall out of the same sweep that produced the 26-digit number.

The sampler is uniform. The shipped bank is not.

The generator does not build an answer greedily. It runs the sweep forwards to
enumerate reachable frontier states, backwards to learn how many boards each
state can still finish, then forwards again picking each row weighted by what
it leaves possible
— a uniform draw from the whole space.

The check is the mean shaded count, which the sweep already knows exactly:

board exact mean shaded sampler (draws) shipped boards shipped ÷ exact
6×6 8.495 8.485 (20,000) 9.833 1.158×
8×8 15.114 15.152 (20,000) 17.278 1.143×
10×10 23.690 23.607 (3,000) 26.917 1.136×

The sampler lands on the exact mean at all three sizes. The shipped boards do
not
, and that gap is the interesting one: they are consistently busier than a
fair draw, by 13.6% at 10×10.

Nothing in the generator prefers busy answers. The uniqueness filter does.
More shading means a longer outline; a longer outline means more cells that may
legally carry a number; more legal cells means more information available to pin
the board down. Selecting for solvable boards silently selects for crowded
answers
, and anyone eyeballing a bank of Tasquare puzzles is not looking at a
fair sample of the genre.

Which is also why the generator throws so much away. Numbering every cell that
could legally carry a number is the most informative board an answer can
produce, and it is usually still not a puzzle:

board draws unique with every legal cell numbered rate
6×6 300 105 35.0%
8×8 300 74 24.7%
10×10 120 11 9.2%

The ladder

  • shape — every block is a square, held as a list of candidate squares. A candidate dies when one of its cells is ruled white or one of its side-neighbours is shaded. A cell no surviving square covers can never be shaded; when only one candidate can still be a shaded cell's block, that block is settled and everything it touches is white.
  • clue — the numbers. A square can never touch a numbered cell from two sides at once (that would put the numbered cell inside it), so the four sides are independent and a clue is an exact four-way subset sum over the square areas still available on each side.
  • prune — that arithmetic pushed back into the candidate list. A square no adjacent number can afford is struck out, and striking squares out can leave a cell with none at all.
  • white — the unshaded cells are one region. Shading a cell that would cut the white region in two is illegal, which is exactly the articulation points of the not-yet-shaded graph, so one Tarjan pass answers it for every cell at once.
  • probe — assume a cell, run the cheaper rungs, drop the assumption if the board dies.
rung 6×6 settled 6×6 finished 8×8 settled 8×8 finished 10×10 settled 10×10 finished
shape 26.1% 0/36 24.9% 0/36 24.2% 0/36
clue 38.7% 1/36 41.5% 0/36 46.8% 0/36
prune 54.7% 2/36 58.4% 0/36 65.2% 0/36
white 56.7% 8/36 64.8% 6/36 68.3% 3/36
probe 100.0% 36/36 100.0% 36/36 100.0% 36/36

Rub every number off a board and run the full ladder including probe, and
it settles 0 cells at every size. Unlike a loop genre, an empty Tasquare
grid has no forced cells anywhere, because the all-white board satisfies every
clause except "something is shaded".

The same rungs, priced as pruning — and the order flips

Run the complete search but only let it propagate up to a given rung between
branches, and count the branch points (cap 200,000):

propagation allowed 6×6 branch points (median) 6×6 worst 8×8 (median) 8×8 worst
up to shape past the cap on 35 of 36 past the cap on 36 of 36
up to clue 8 387 37 1,062
up to prune 5 31 24 997
up to white 2 14 7 34

The shape rung knows the entire structural half of the rule and still cannot
finish a 6×6 inside 200,000 branch points on 35 of 36 boards. Add the numbers
and an 8×8 falls to a median of 37; push them back into the candidate squares
and it falls to 24; add the white-region clause and it falls to 7.

The clause that is worth the most in the answer-space table is worth the least
in this one, and the other way round.
The square clause buys a 165,127×
reduction in how many answers exist and is nearly useless as a pruner; the
white-region clause buys 5.20× and is the best pruner on the ladder. "How much
does this clause constrain the genre" and "how much does this clause help you
solve it" are different questions with different answers, and you cannot tell
which is which without measuring both.

Three ways to misread the board

misreading board intended answer still legal answers (median, cap 12) still unique
the white cells may split 6×6 36/36 4 10/36
a number counts touching cells 6×6 15/36 0 11/36
no numbers at all 6×6 36/36 12 0/36
the white cells may split 8×8 36/36 10 3/36
a number counts touching cells 8×8 5/36 0 3/36

Reading a number as the count of touching cells rather than the total area
of the squares
is the loud failure. The two readings agree only when every
block beside the number is a single cell, so the intended answer stops being
legal on 21 of 36 boards at 6×6 and 31 of 36 at 8×8 — you hit a contradiction
almost immediately and go back to the rules.

Dropping the white-region clause is the quiet one. The intended answer stays
legal on every board, because one region is a special case of several, and what
breaks instead is uniqueness. That is the mistake worth guarding, and guarding
it is exactly what the white rung does.

Implementation notes

  • Every number on the page and in the README is generated from src/counts.json and src/stats.json by npm run notes, which rewrites the marked block in index.html and the README. There is no transcription step, so no number can quietly go stale.
  • 51 tests. One of them checks all five rungs on all 108 shipped boards for soundness: 21,213 proved cells, zero of them against the intended answer.
  • Rewriting whiteRung from "flood once per candidate cell" to "one Tarjan pass" took the test suite from over seven minutes to sixteen seconds. Writing a connectivity pruner as a per-cell flood is fine on paper and fatal by the time the board is 10×10.

Takeaway

The thing I did not expect going in was that the fifth clause of the rules
decides where the clues may go
. One line saying a numbered cell must have
shading beside it makes 0 illegal, which confines every number to the outline
of the shading, which means the board leaks a 262× reduction before a single
digit is read
.

And measuring "what is this unprinted clause worth" with two different rulers
reverses the ranking. If I had only measured one, I would have written a
confident and wrong sentence about which clause carries this genre.

Puzzle #65 in the solver series.

Top comments (0)