コージュン (Kojun) を、5 つのルールセット内蔵でブラウザに実装した。盤面は領域に分割されていて、サイズ k の領域には 1〜k がちょうど 1 個ずつ入る。辺で接する 2 マスは領域境界をまたいでも同じ数字にならず、同じ領域内で縦に接する 2 マスは上が大きい。ソルバー内蔵パズル第 46 弾。
デモ: https://sen.ltd/portfolio/kojun/
リポジトリ: https://github.com/sen-ltd/kojun
最初の手がかりは、書かれるのではなく描かれる
この連作で測ってきた手がかりは、いつも印刷された数字だった。コージュンにも数字ヒント(given)はある。だがその前に、作者はすでに 1 つ手がかりを盤面に置いている。分割そのものだ。
領域の輪郭は 3 つのことを言う。数字の範囲(サイズ k なら 1〜k)、内部の勾配(領域内の縦の辺はすべて下り坂)、そして時々、中身の全部。高さ k の縦 1 列の領域は、上から k, k−1, …, 1 と読めてしまう——上のマスは下のマスの最小値より大きく、という区間の連鎖が、given ゼロで全マスを確定させる。
デフォルトの分割ストリーム(領域サイズ 4〜7)では、数字を 1 個も印刷する前に、形だけで盤面の 9〜11% のマスが確定する。しかもその仕事はほぼ全部が order(縦の辺の区間伝播)のものだ:
| n | neigh |
once |
order |
region |
probe |
|---|---|---|---|---|---|
| 6×6 | 1.6% | 1.7% | 9.3% | 9.3% | 9.9% |
| 10×10 | 1.6% | 1.6% | 11.1% | 11.1% | 11.5% |
共存できない領域 — 粒度の軟らかい壁
分割を手がかりとして強くしようとすると、このパズルは奇妙な抵抗をする。盤面そのものが存在しなくなるのだ。
完成盤の「v が入ったマス全体」は、領域を問わず同じ数字が辺で接しないから、盤面全体にわたる独立集合になる。そしてサイズ ≥ v の領域は必ず v を 1 個含む。つまり領域が小さいほど盤面は 1 と 2 で埋まり、やがて独立集合が幾何的に詰めなくなる。全マス単独領域の分割はその極限で、全マスが 1 → 隣接する 1 のペアが必ずある → 合法盤面ゼロが定理として言える(n ≥ 2)。
測ると、崩壊は定理の壁よりずっと手前から始まっていた。分割 1 個につき充填 1 回勝負(引き直しなし)で:
| 8×8, 領域サイズ | 盤面が存在 | 平均領域サイズ | 形だけで確定(order) |
|---|---|---|---|
| 1–1(全部単独) | 0.0% | 1.00 | — |
| 2–3 | 0.0% | 2.40 | — |
| 2–5 | 2.5% | 3.26 | 56.3% |
| 3–6 | 28.8% | 4.00 | 24.2% |
| 4–7(デフォルト) | 51.3% | 4.70 | 11.4% |
| 5–9 | 75.0% | 5.91 | 7.0% |
緊張関係が作者の逆を向いている。いちばん多くを語る形(サイズ 2〜5 で形だけで 56% 確定)は、いちばん存在しない形だ。
縦ダイヤルと、第二の壁
縦ルールは領域内の縦の辺しか読まないから、同じ 4〜7 マスの予算でも、領域を縦長に育てるほど形は雄弁になる。成長バイアス vbias を掃引した:
| 8×8, vbias | 盤面が存在 | 縦 1 列領域のマス | 形だけで確定(order) |
region 級を買う最小 given(6×6 中央値) |
|---|---|---|---|---|
| 0.00(平坦) | 98.8% | 0.7% | 0.9% | 18 |
| 0.50 | 60.0% | 6.9% | 10.8% | 12 |
| 0.75 | 25.0% | 24.5% | 25.2% | 9 |
| 1.00(縦長) | 0.0% | 74.6% | — | 3 |
確定力は 0.9% → 25% と上がり続け、そして端で盤面が消える。理由は自己解決性そのものだ。高さ k の縦列領域が 2 本隣り合うと、両方が k…1 に強制され、同じ数字が横に並んでしまう。自分を解いてしまう形は、隣に座れない。
最後の列は「インク代」だ。region 級(roof まで使って完答)の一意盤を作るのに必要な最小 given は、平坦な分割で中央値 18 個(36 マスの半分)、生き残った縦長分割ではたった 3 個。手がかりの過半を、数字ではなく輪郭で払えるようになる——払えるのは、そのような分割がほぼ存在しないという価格でだが。
ランダムな given は、ほぼ無価値
given の側にも一言ある。マスの 30% をランダムに開示しても、6×6 の一意率は 0.0% だった(50% 開示でやっと 6%、8×8 では 50% でも 0%)。一方、生成器の敵対的な間引き(追加→貪欲削除)は中央値 12 個で一意性を買う。何個置くかより、どこに置くかがほぼ全て。ナンロー (#326) で見た「敵対的 19 個 vs ランダム 19 個で 0/30」の法則が、given の置き場所を作者が完全に選べるパズルでも再現した。
1 枚の屋根がラダー全体を覆う — そして裸の盤面では屋根も黙る
ラダーは 5 段。neigh(確定した隣のマスがその数字を消す)、once(領域を順列として読む: 確定マスの排除と、行き場が 1 つの数字の確定)、order(縦の辺の区間伝播)、region(領域 1 個の全割当を列挙して、支持されない候補を全部消す屋根)、probe(仮定→矛盾で削除)。
once(数字ごとの家の census)と order(辺の幾何)は比較不能な中段だ。だが下段 3 本が正当化できる削除は、すべて単一領域の内側か、確定した外隣への境界辺 1 本に完結する——それはまさに region の列挙が検査する範囲だ。つまり屋根が下段 3 本を包摂することは定理で、ablation はそれをビット単位で確認した:
| 10×10 | 確定率 | fixpoint が動いた盤 | 領域列挙 | probe 回数 |
|---|---|---|---|---|
| full | 12.7% | — | 8,196 | 706 |
| −neigh | 12.7% | 0 / 20 | 11,129 | 706 |
| −once | 12.7% | 0 / 20 | 9,914 | 706 |
| −order | 12.7% | 0 / 20 | 9,413 | 706 |
| −region | 12.7% | 0 / 20 | 975 | 706 |
| −probe | 11.7% | 18 / 20 | 975 | 0 |
安い 3 本はどれを抜いても fixpoint が 1 ビットも動かない。動くのは請求書で、neigh を抜くと屋根の列挙仕事が 3 分の 1 増える。ここまでは連作の既視感どおり——だが 5 行目が新しい。このストリームでは屋根を抜いても何も変わらない。given ゼロの裸盤面では、屋根が消せる候補は probe が全部再導出できてしまい、order より上のラダーが丸ごと沈黙する。
中段が起きるのは given が入ってからだ。出荷バンク(80 盤)は全サイズで 5 グレードすべてが埋まった: neigh 級から probe 級まで、給された数字が中段のルールを 1 本ずつ順番に目覚めさせる。裸の盤面はラダーを 2 段に潰し、given がそれを 5 段に展開する。
多項係数の国勢調査
健全性は、ラダーとコードを共有しない生エンジンで固定した。こちらは領域を丸ごと 1 個ずつ配る——探索空間は文字通り Π kᵢ! で、置いた数字が隣接・縦順・given に生に反しないかだけ見て、葉を validate で採点する。伝播探索との解数一致は 482/482。
生エンジンにはもう 1 つ、外部の恒等式がある。孤立した p×q 長方形領域(p 行 q 列、given なし)では、縦ルールが各列を「上から狭義単調減少」に強制する以外に制約がない。だから盤面数は多項係数になる:
(pq)! / (p!)^q — 各列にどの数字を配るかを選べば、列内の並びは強制される
多項係数など知らない生エンジンが、1×5 = 120、3×2 = 20、4×2 = 70、3×3 = 1,680、2×5 = 113,400 まで、頼んだ全項に正確に着地した。縦 1 列(k×1)はもちろん 1 通り——「列は自分の解」の数え上げ版だ。
第 2 解を答えから直読する — 説明率 98〜100%
マス 1 個は決して黙って値を変えられない。変えた瞬間、その領域は数字を 1 個失い、1 個重複させる(テストが全マス×全代替値で網羅的に証明する)。だから最安の曖昧さはスワップ——同じ領域の given でない 2 マスが数字を交換して、全ルールが無傷で残る配置だ。答えの盤面を 1 回走査するだけで見つかる(探索ゼロ)。
| n | 非一意盤 | 1 スワップで説明 | 一意盤での誤検出 |
|---|---|---|---|
| 4×4 | 296 | 291 (98.3%) | 0 |
| 6×6 | 200 | 200 (100.0%) | 0 |
| 8×8 | 240 | 240 (100.0%) | 0 |
マグネット (#328) のペア証明書は非一意盤の 4 割を説明した。コージュンはほぼ全部だ。領域という小さな全単射の内側に曖昧さが閉じ込められていて、複数領域にまたがる値の玉突きが最安になることが滅多にない。そして probe ⇔ 一意は、ストリーム全体 680 盤で両方向とも例外なしだった。
まとめ
- コージュンの最初の手がかりは分割そのもの。縦 1 列の領域は given ゼロで自分を解き、デフォルト分割でも形だけで盤面の 9〜11% が確定する(仕事はほぼ全部
order) - 数字クラスは盤面大の独立集合なので、小さい領域ほど雄弁で、かつ存在しない。8×8 はサイズ 2–3 で存在率 0%、5–9 で 75%。全単独マス分割は定理として空
- 縦ダイヤルは確定力を 0.9% → 25% に上げながら存在率を 98.8% → 0% に下げる。自分を解く形は隣に座れない。インク代は平坦 18 個 → 縦長 3 個
- ランダム given はほぼ無価値(30% 開示で一意率 0%)。敵対的な 12 個が同じ仕事をする
- 屋根
regionが下段 3 本を包摂することは定理で、ablation は全サイズ fixpoint ビット単位不変。裸の盤面では屋根さえ沈黙し、given だけが中段を起こす(バンクは全サイズ 5 グレード充足) - 生エンジン(Π kᵢ! を丸ごと配る)と 482/482 一致、孤立長方形で多項係数 (pq)!/(p!)^q を全項再現
- 領域内スワップ証明書が非一意盤の 98〜100% を無探索で説明、誤検出 0。probe ⇔ 一意は 680 盤無例外
全 27 テスト。TypeScript、ランタイム依存ゼロ。
デモ: https://sen.ltd/portfolio/kojun/
リポジトリ: https://github.com/sen-ltd/kojun
