//XYwing is an algorithm that consists of two WeakLinks with common cells. //http://csdenpe.web.fc2.com/page42.html public bool XYwing( ) { Prepare(); CeLKMan.PrepareCellLink(2); //Generate WeakLinks if (BVCellLst == null) { BVCellLst = pBDL.FindAll(p => (p.FreeBC == 2)); //Generate BVs(BV:bivalue). } if (BVCellLst.Count < 3) { return(false); } bool XYwing = false; foreach (var P0 in BVCellLst) //Choose one BV_Cell(=>PS) { List <UCellLink> BVLKLst = CeLKMan.IEGetRcNoBTypB(P0.rc, 0x1FF, 2).Where(R => R.BVFlag).ToList(); //Extract WeakLinks starting from P0 //foreach( var P in BVLKLst ) WriteLine(P); if (BVLKLst.Count < 2) { continue; } var cmb = new Combination(BVLKLst.Count, 2); int nxt = 1; while (cmb.Successor(nxt)) //Combine two WLinks from BVLKLst { UCellLink LKA = BVLKLst[cmb.Index[0]], LKB = BVLKLst[cmb.Index[1]]; //( UCell Q = LKA.UCe2, R = LKB.UCe2; if (Q.rc == R.rc || LKA.no == LKB.no) { continue; //Two WLinks have different end and different digits } Bit81 Q81 = ConnectedCells[LKA.rc2] & ConnectedCells[LKB.rc2]; if (Q81.Count <= 0) { continue; //Two WLinks have cells connected indirectly } int noB = Q.FreeB.DifSet(1 << LKA.no) & R.FreeB.DifSet(1 << LKB.no); if (noB == 0) { continue; //Two WLinks have common digit(=>no). } 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; //cell(A)/digit(no) can be excluded if (SolInfoB) { msg2 += $" {A.rc.ToRCNCLString()}(#{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 (SolInfoB) { ResultLong = $"XY Wing\r {msg0}\r {msg1}\r Eliminated:{msg2}"; } if (__SimpleAnalizerB__) { return(true); } if (!pAnMan.SnapSaveGP()) { return(true); } XYwing = false; } } } return(false); }
//EmptyRectangle is an algorithm using cell-to-cell link and ConnectedCells. //http://csdenpe.web.fc2.com/page41.html public bool EmptyRectangle( ) { Prepare(); CeLKMan.PrepareCellLink(1); //Generate StrongLink for (int no = 0; no < 9; no++) //Focused digit { int noB = 1 << no; for (int bx = 0; bx < 9; bx++) //Focused Block { int erB = pBDL.IEGetCellInHouse(bx + 18, noB).Aggregate(0, (Q, P) => Q | (1 << P.nx)); if (erB == 0) { continue; } for (int er = 0; er < 9; er++) //Focused Cell in the Focused Block { int Lr = er / 3, Lc = er % 3; //Block local Row and Column int rxF = 7 << (Lr * 3); //7=1+2+4 (Block local Row r1c123) int cxF = 73 << Lc; //73=1+8+64 (Block local Column r123c1) if ((erB & rxF) == 0 || erB.DifSet(rxF) == 0) { continue; //Row Lr(Row Cndition Check) } if ((erB & cxF) == 0 || erB.DifSet(cxF) == 0) { continue; //Column Lc(Column Cndition Check) } if (erB.DifSet(rxF | cxF) > 0) { continue; //Row Lr and Column Lc(ER Condition Check) } int r1 = bx / 3 * 3 + Lr; //Convert to Absolute Row int c1 = (bx % 3) * 3 + Lc; //Convert to Absolute Column foreach (var P in HouseCells[9 + c1].IEGetUCeNoB(pBDL, noB).Where(Q => Q.b != bx)) { //P:cell in house(column c1), P is outside bx foreach (var LK in CeLKMan.IEGetRcNoBTypB(P.rc, noB, 1))//rc:link end, noB:digit, 1:StrongLink { UCell Elm = pBDL[r1 * 9 + LK.UCe2.c]; if (Elm.b != bx && (Elm.FreeB & noB) > 0) //There is a Digit that can be excluded { EmptyRectangle_SolResult(no, bx, LK, Elm); //solution found if (__SimpleAnalizerB__) { return(true); } if (!pAnMan.SnapSaveGP(true)) { return(true); } } } } foreach (var P in HouseCells[0 + r1].IEGetUCeNoB(pBDL, noB).Where(Q => Q.b != bx)) { //P:cell in house(row r1), P is outside bx foreach (var LK in CeLKMan.IEGetRcNoBTypB(P.rc, noB, 1))//rc:link end, noB:digit, 1:StrongLink { UCell Elm = pBDL[LK.UCe2.r * 9 + c1]; if (Elm.b != bx && (Elm.FreeB & noB) > 0) //There is a Digit that can be excluded { EmptyRectangle_SolResult(no, bx, LK, Elm); //solution found if (__SimpleAnalizerB__) { return(true); } if (!pAnMan.SnapSaveGP(true)) { return(true); } } } } } } } return(false); }