さしがね(Sashigane)を、4 段のソルバー内蔵でブラウザに実装した。このパズルには、他のニコリ系にはあまり無い性質がある——丸は全部与えられている。丸は必ず曲がり角に乗るので、盤に印刷された丸の集合はそのまま「答えの角の集合」で、ピースの個数も角の位置も、1 手も指す前に分かっている。残る未知は腕の長さだけだ。では手掛かりは何をしているのか。測ったら、いちばん効いているのは矢印がどのマスに乗っているかで、矢印がどっちを向いているかはその 10 分の 1 しか効いていなかった。そして作者に残された唯一の自由——2 つある端のどちらに矢印を置くか——は、12×12 で一意化率を 11.3% と 29.8% の間で動かす。ソルバー内蔵パズル第 55 弾。
デモ: https://sen.ltd/portfolio/sashigane/
リポジトリ: https://github.com/sen-ltd/sashigane
ルール
- 盤を幅 1 の L 字に分割する。長さ 1 以上の直線の腕 2 本が直角に出会う形なので、最小ピースは 3 マス
- 各ピースには丸がちょうど 1 個あり、それは曲がり角に乗っている
- 各ピースには矢印がちょうど 1 個あり、それは 2 つある端のどちらかに乗って、自分の腕をたどって曲がり角のほうを向いている
- 丸の中の数字は、そのピースのマス数。数字の無い丸(空丸)があってよい
ルール 2 が効く。丸は必ずあって必ず角に乗るのだから、印刷された丸の集合 = 答えの角の集合。ピース数も角の位置も全部タダで手に入る。
そして矢印には、他の多くのパズルの矢印には無い性質がある。矢印は端に乗り、かつ角のほうを向いている。ということは、その矢印は腕を 1 本まるごと確定させている——腕の向きは矢印の逆、腕の長さは矢印から角までの距離。つまり矢印は「向き」という 1 ビットの情報ではなく、腕 1 本の完全な指定なのだ。
この 2 つを合わせると、さしがねという問題の形がはっきりする。角は全部既知、腕の片方は矢印で既知。残っているのは「もう 1 本の腕が、直角な 2 方向のどちらに、どれだけ伸びるか」だけである。
1. 白紙の盤ですら解けないことがある
手掛かりを 1 個も置かず、ただ「空の格子を L 字に分割する方法は何通りか」を数えてみる。
1 マス幅の帯は 0 通り——L 字は 2 次元を要求する。2×2 も 0。そして 3×3 も 0 だ。9 マスを L 字に割るには 3+3+3 か 4+5 しかないが(3×3 に入る最大の L は 5 マス)、どちらも組めない。正方形で唯一の穴で、しかも 2×3(2 通り)と 3×4(20 通り)の間に挟まっている。
| 2×n | 0 | 0 | 2 | 2 | 2 | 6 | 10 | 14 | 26 | 46 | 74 | 126 | 218 | 366 |
| 3×n | 0 | 2 | 0 | 20 | 64 | 234 | 664 | 2220 | 7476 | 25882 | ||||
| 4×n | 0 | 2 | 20 | 110 | 752 | 4522 | 27380 | 167078 | ||||||
| 5×n | 0 | 2 | 64 | 752 | 7720 | 84846 | 908020 | |||||||
| 6×n | 0 | 6 | 234 | 4522 | 84846 | 1557970 |
帯には線形漸化式がある。4 項目以降のすべての項が
a(n) = a(n−1) + 2·a(n−3)
を満たす。これは OEIS A052537、母関数 (1−x)/(1−x−2x³) そのもの。全単射的な証明は持っていないので、恒等式としてテストで毎回全項を検算するという形で書いた。3×n, 4×n, 5×n, 6×n と正方対角 0, 0, 0, 110, 7720, 1557970 は、いずれも OEIS に無い(2026-09-05 検索)。4×6 より大きい値は全部、転置を計算して突き合わせてある(スキャナは全く違う順序で盤を歩くので、独立な検算になる)。
ピースは 3 マス以上なので、盤に乗る丸は最大 ⌊h·w/3⌋ 個。この上限は到達可能で、4×6 は 8 ピースへの分割を実際に持つ。
2. 数字を全部書くと、パズルでなくなる
冒頭に書いたとおり、矢印は腕を 1 本まるごと決めている。ここに数字を足すと、もう 1 本の腕の長さも決まる。残るのは「その腕がどちらの側に出るか」の 2 択だけ。
つまり 数字まで全部書かれた丸の候補は、たかだか 2 形しかない。3×5・4×4・4×5 の全分割から作った 136,576 個の「フル手掛かり丸」を数えると、80.3% がちょうど 1 形、19.7% が 2 形。3 形は一度も現れない。
そして残りの 2 択は、敷き詰めの条件がいつも決着させてしまう。盤の全分割 × 矢印の置き方全 2^k 通り × 数字全部印刷、で総当たりすると:
| 盤 | (分割, 矢印マスク) の組 | 解がちょうど 1 個 |
|---|---|---|
| 2×6 | 72 | 100.0% |
| 3×4 | 192 | 100.0% |
| 3×5 | 896 | 100.0% |
| 3×6 | 6,432 | 100.0% |
| 4×4 | 1,888 | 100.0% |
| 4×5 | 24,416 | 100.0% |
33,896 盤で曖昧なものが 1 枚も無い。さらに 5×5 から 10×10 までのランダム探索でも反例ゼロ。証明は持っていないので定理とは呼ばないが、この測定が言っているのは「面白いさしがねの盤は、数字を落とした盤のほうだ」ということで、だから本実装の生成器は数字を消せるだけ消す。
3. 数字を消すと、矢印の端の選択が効き始める
同じ総当たりを、丸を全部空丸にして回す。
| 盤 | 組 | 一意 | どう矢印を置いても一意化できない答え |
|---|---|---|---|
| 2×6 | 72 | 100.0% | 6 個中 0 |
| 3×4 | 192 | 87.5% | 20 個中 0 |
| 3×5 | 896 | 81.3% | 64 個中 0 |
| 3×6 | 6,432 | 73.5% | 234 個中 0 |
| 4×4 | 1,888 | 87.3% | 110 個中 0 |
| 4×5 | 24,416 | 74.8% | 752 個中 0 |
| 4×6 | 284,000 | 70.9% | 4,522 個中 0 |
右端の列が安心できるほうの結果だ。印刷できない答えは 1 つも無い——ここで数えたどの分割にも、それを一意化する矢印の置き方が最低 1 通りある。だが 4 分の 1 以上の選択は外れで、作者は当たりを引かないといけない。
4. 作者が本当に選べるのは矢印の端だけで、それが 2.6 倍を動かす
丸は角に強制され、数字は消される。だからさしがねの作者が実際に決めているのは
ピースの 2 つある端のどちらに矢印を置くかだけ——答えの側からは完全に見えない選択だ。
同じランダムな答えを 3 通りに描き分けて測る: 全部の矢印を長いほうの腕の端に、全部を短いほうの腕の端に、
そしてピースごとにコイン投げ。
| 盤 | ピース数 | 全部長い腕 | 全部短い腕 | コイン投げ |
|---|---|---|---|---|
| 6×6 | 中央値 6 | 57.9% | 49.8% | 49.9% |
| 8×8 | 中央値 9 | 41.8% | 44.8% | 30.4% |
| 12×12 | 中央値 14 | 20.8% | 29.8% | 11.3% |
左 2 列は 1200・1200・400 個の答え、コイン投げ列は答えごとに独立 8 マスクなので 9,600・9,600・3,200 盤。
出てきたのは 2 つで、予想していたのは片方だけだった。
一貫した規約は、一貫しない置き方に必ず勝つ。 12×12 では短い腕規約が 29.8%、コイン投げが 11.3%。
同じ答え、同じ丸、同じ本数の矢印で、違うのは「各矢印がどっちの端に乗ったか」だけ。
機構は分かっていない。曖昧かどうかは印刷された盤だけの性質で、ソルバーは規約を一切知らない。
規約にできるのはどの盤に着地するかの分布を変えることだけのはずで、実際それがましな盤に着地している。
そしてどちらの規約が良いかは盤のサイズで裏返る。 6×6 では長い腕が 8 ポイント勝ち、12×12 では短い腕が 9 ポイント勝つ。
8×8 では両者の差は数ポイントで、ここでのサンプル誤差の中に収まる。
つまり作者に渡せる経験則は無い——確実に間違っているのは「適当に決めること」だけ、という事実しか無い。
5. 数字は本当にほぼ無料
生成器は、数字を全部印刷 → 一意を確認 → 数字を 1 個ずつ消して一意のままなら消す、という順で削る。出荷盤に残る数字はほとんど無い。
| バンク | ピース数 | 残った数字 | 数字ゼロでも一意 |
|---|---|---|---|
| 8×8, 40 盤 | 中央値 9 | 0〜2、中央値 0 | 40 盤中 22 |
| 12×12, 32 盤 | 中央値 17 | 0〜4、中央値 1 | 32 盤中 10 |
8×8 の出荷盤の半分以上は、盤上に数字が 1 つも無い。丸と矢印だけがパズルになっている。
6. どの節が骨組みか — 位置は向きの 10 倍
ルールの節を 1 つずつ落として、出荷盤 72 枚で測る。
| 落とした節 | 一意でなくなる盤 | そのとき湧く解の中央値 | 分岐数 |
|---|---|---|---|
| なし(フルルール) | 0 / 72 | — | 0 |
| 矢印が角のほうを向く | 5 / 72 | 2 | 12 |
| 矢印が端に乗る | 52 / 72 | 6 | 1,006 |
| 丸が角に乗る | 22 / 72 | 2.5 | 146 |
| 数字がマス数と一致 | 40 / 72 | 5 | 386 |
矢印の「位置」は矢印の「向き」の 10 倍効いている。これはルール文の重心と逆だ。「端にあって丸のほうを向く矢印」と読むと、情報の本体は向きで、位置はそれをぶら下げる釘に見える。実際は逆で、「このマスは端である」がほぼ全部、向きはその上に少し乗るだけだった。
最下行は発見ではなく自己整合チェックで、数字は最小化してあるから残った数字は定義上すべて骨組み——数字を持つ盤がちょうど 40 枚あり、その 40 枚が落ちる。
7. ラダーと、ほとんど発火しない上の段
| 段 | やること |
|---|---|
fit |
各丸の候補 L を作る(自分の丸が角、他の丸を含まない、矢印ちょうど 1 個、端、角向き、マス数一致) |
cover |
各マスの持ち主はちょうど 1 人。あるマスに届く丸が 1 個しか無ければそのピースが取る。ある丸の生存候補が全部あるマスを覆うなら、他の丸はそのマスを取れない |
area |
サイズの総和は h·w。残りに不可能な余りを押しつける候補は死ぬ |
probe |
生存候補を 1 個ずつ仮置きして下の段を回す |
出荷盤全部について、一意性を証明するのに要った分岐数:
fit |
cover |
area |
probe |
|
|---|---|---|---|---|
| 8×8, 40 盤 | 4,053,280* | 0 | 0 | 0 |
| 12×12, 32 盤 | 9,600,032* | 0 | 0 | 0 |
* 8×8 は 5 盤、12×12 は全盤が 30 万分岐の上限に当たったので、この 2 マスは下界。
cover だけで全盤が推測ゼロで終わるので、area と probe はこのバンクでは一度も本気を出していない。それでも置いてあるのは、area が「数字が足し算として成り立たない盤」を弾く段で、probe は生成器が「この草稿は一意か」を判定している最中に使う段だからだ。
fit 単独——伝播なしの純粋な完全被覆——は 8×8 の 94.4% を構成だけで確定させ、そこから先に数百万の分岐を要する。1 段足すと、残り 5.6% と探索全部が消える。
8. 探索がまったく要らないサイズ予算
ピースは盤を覆うので、サイズの総和は h·w。印刷された数字はその分を先取りする。数字の無いピースは最低 3 マス、最大 h+w−1 マス。だから残りは
[3·(数字なしピース数), (h+w−1)·(数字なしピース数)]
に入っていなければならず、入らなければその盤に答えは無い。部分解も巻き戻しも要らない。src/sashigane.ts の budgetOf がその全実装で、デモの盤の横のパネルでリアルタイムに動いている。
9. 2 つ目のエンジンが捕まえたバグ
ソルバーは 2 本あって、1 行も共有していない。1 本目は各丸を「まだあり得る L 字の集合」を定義域とする変数にして、被覆と面積を不動点まで伝播する。2 本目は丸を変数として一切扱わず、盤を行優先で歩いて、誰にも取られていないマスに出会うたびにそのマスを覆う L 字を全部試す。
開発中、生成器が出したばかりの盤で 2 本が食い違った——伝播器は解 1 個、スキャナは解 2 個。原因は古くなった索引だった。cover 段は「各丸の生存候補のうち何個がこのマスに届くか」の表を作り、それからマスを走査して候補を殺していく。初版は殺したあとも、殺す前に作った表のまま走査を続けていた。古いカウントを最新の生存数と比べると「この丸の生存候補は全部このマスを覆っている」と読めてしまい、本来そのマスを取れたはずの他の丸を追い出し、本物の解を静かに消す。今はこの段は何か殺した瞬間に return して、呼び出し側に表を作り直させる。
テストにはこれ用の健全性プロパティが入っている: ランダム盤について、伝播器が持ち主を確定したマスは、スキャナが見つける全部の解でその持ち主でなければならない。
まとめ
- 丸が全部与えられているので、さしがねの未知は「腕の長さ」だけ
- 矢印は端に乗って角を向くので、腕を 1 本まるごと確定させる。数字を足すともう 1 本の長さも決まり、候補は最大 2 形に潰れる
- だから数字を全部書いた盤は(測った範囲で)必ず一意。33,896 盤で反例ゼロ
- 数字を消すと矢印の端の選択が効きはじめ、置き方によっては 4 分の 1 以上が曖昧になる
- ablation では矢印の位置が向きの 10 倍効く。ルール文の重心と逆
- 作者に残る唯一の自由(各矢印をどっちの端に置くか)は 12×12 で一意化率を 11.3% → 29.8% に動かす。一貫した規約はコイン投げに必ず勝ち、どちらの規約が良いかは盤サイズで裏返る
- 白紙の 3×3 は L 字に割れない。2×n の分割数は OEIS A052537
TypeScript、ランタイム依存ゼロ、全 68 テスト。数値は全部 npm run stats で再現できる。
デモ: https://sen.ltd/portfolio/sashigane/
リポジトリ: https://github.com/sen-ltd/sashigane
