XY-Wing
XY-Wingは、候補数字が2個のセル(bivalue cell)によるLockedの解析アルゴリズムです。
次の図で解説します。
青枠と緑枠の3セルがbivalueで互いに弱いリンクで結びついているとき、青枠セルと弱いリンクで繋がるオレンジ枠のセルの候補数字はaではありません。
解析アルゴリズムは、次のとおりです。リンクの数字は図のとおりxとyとaです。
- bivalueセルのリストを作成する
- bivalueセルのリストから軸とするセル(Pivotセル)を選ぶ
- 軸セルに接続するbivalue弱リンクのリストを作成する
- bivalue弱リンクリストから、2リンクを選ぶ(組合せ選択)
- 2リンクは、他端セルが異なり、数字組(axとay)も異なることが条件である。
- 2リンクの他端の影響圏セルXを求める
- 2リンクの他端とセルXに共通の数字(a)があることが条件である
XY-Wingの例を示します。
.1..7.69.4.6.9..1.5.9.2...87....9....9..3..8....8....41...6.8.9.8..4.7.5.67.8..4.
6..1....7..18.73...2.3...9..5.9.8641.........1482.6.3..7...2.1...64.18..8....3..4
..8..5..6.3.......6.2.4.5.7...384.59..65..2.39..7...4...4.5.8.....2.8...8.946....
XY-Wingの解析プログラム
XY-Wingの解析プログラムです。上記のアルゴリズムを順にコード化してあります。
このコードのポイントは次の4点です。後の2つは、Bit表現とBit演算を利用して効率よく求めています。
- bivalueセルのリストを作る
- 着目セルに接続するbivalue弱リンクのリストを作る
- 2つのbivalue弱リンクからlockedとなるセルを求める。
- 除外候補数字を求める。
public partial class CellLinkGen: AnalyzerBaseV2{
public bool XYwing( ){
if(BVCellLst==null) BVCellLst = pBDL.FindAll(p=>(p.FreeBC==2)); //BV:bivalue
if(BVCellLst.Count<3) return false;
CeLKMan.PrepareCellLink(2); //weak Link生成
bool XYwing=false;
foreach( var P0 in BVCellLst ){
List<UCellLink> BVLKLst =CeLKMan.IEGetRcNoBTypB(P0.rc,0x1FF,2).Where(R=>R.BVFlag).ToList();
//foreach( var P in BVLKLst ) Console.WriteLine(P);
if(BVLKLst.Count<2) continue;
var cmb = new Combination(BVLKLst.Count,2);
int nxt=1;
while(cmb.Successor(nxt)){
UCellLink LKA=BVLKLst[cmb.Cmb[0]], LKB=BVLKLst[cmb.Cmb[1]];
UCell Q=LKA.UCe2, R=LKB.UCe2;
if( Q.rc==R.rc || LKA.no==LKB.no ) continue;
Bit81 Q81 = ConnectedCells[LKA.rc2]&ConnectedCells[LKB.rc2];
if(Q81.Count<=0) continue;
int noB = Q.FreeB.DifSet(1<<LKA.no) & R.FreeB.DifSet(1<<LKB.no);
if(noB<0) continue;
int no=noB.BitToNum();
string msg2="";
foreach( var A in Q81.IEGetUCeNoB(pBDL,noB) ){
if( A==P0 || A==Q || A==R ) continue;
A.CancelB=noB; XYwing=true;
if(SolInfoDsp) msg2+=" "+A.rc.ToRCString()+"(#"+(no+1)+")";
}
if( XYwing ){
SolCode=2;
P0.SetNoBColor(P0.FreeB,AttCr);
P0.SetCellBgColor(SolBkCr);
Q.SetCellBgColor(SolBkCr);
R.SetCellBgColor(SolBkCr);
string msg0= " Pivot: "+_XYwingResSub(P0);
string msg1= " Pin: "+_XYwingResSub(R) +" ,"+_XYwingResSub(Q);
Result="XY Wing"+msg0;
if( SolInfoDsp ){
ResultLong="XY Wing\r "+msg0+"\r "+msg1+"\r Eliminated:"+msg2;
}
if( !AnMan.SnapSaveGP() ) return true;
XYwing=false;
}
}
}
return false;
}
private string _XYwingResSub( UCell P ){
string st=P.rc.ToRCString()+"(#"+P.FreeB.ToBitString(9).Replace(".","")+")";
return st;
}
}