ナンプラー・インジケータ追加

ラインまたはボックス内で、ある数字だけ見たとき置けるマスが1箇所しかないなら、
そのマスの数字は確定します。(そのマスに入る候補がいくつあっても)
そのようなケースについても強調表示したい。
面倒なので、ラインまたはボックスの単位を勝手にエリアと呼ぶことにします。
9×9ナンプレでは、エリアは縦ライン×9、横ライン×9、ボックス×9の27個。
先ほどのチェックは、エリア単位で数字ごとにいくつの空きマスの候補になったかを
カウントし、その結果が1だったら確定とみなす、で良いはずです。
ただし、実際に数字ごとに足し算を繰り返していると、さすがにループも増えるし
計算効率も悪くなります。
 
というわけで、9個の数字の足し算を並列処理するため、マスクの持ち方を工夫します。
数字nに対応するビットは今までn番目を使っていましたが、2n番目に変更。
そして2n+1番目を特別な管理ビットに割り当てます(具体的には、複数箇所の
候補に上がっていることを示すビット)。
この2ビット分の管理情報によって エリア内でその数字が入るマスが1箇所(01)か、
無い(00)か、複数箇所ある(10)かを計算するようにします。(11は使わない)
9個分並べても18ビットで32ビット整数値に格納できます。
 
カウントのやり方は、単純な加算では2ビット分をすぐにオーバーフローして使い物に
ならないので、エリア内各マスの候補を示すマスク値を足すときに、既に結果として
「10」が設定されている数字は加算を行わないという方法を使います。
当然、IF文で判断したのでは本末転倒なので、ビット演算を駆使することになります。
合計値側の管理情報に10をANDして右シフト、ビット反転の結果を加算値にANDした後に
合計値に加算する、という方法をとります。
例えば、合計値側が00や01の場合は、10とのAND→00、シフトして00、反転すると11
これを加算値01にANDしても変化しないので、00+01→01、01+01→10となります。
合計値側が10の場合は、10とのAND→10、シフトして01、反転すると10これを加算値01
にANDすると00、つまり10+00→10で足し算が行われなかったのと同じ効果になります。
これならオーバーフローしませんので、9個分並べた値を用いれば、1度の演算式で
9個分の並列計算が行えるわけです。