//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);
        }
示例#2
0
        //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);
        }