Exemplo n.º 1
0
//============================================================================================================
        public bool GenMessage2(USuperLink USLK, UCell P, int no)
        {
            var pQtrue  = USLK.Qtrue;
            var pQfalse = USLK.Qfalse;

            if (!pQfalse[no].IsHit(P.rc) || !pQtrue[no].IsHit(P.rc))
            {
                return(false);
            }

            var pchainDesLKT = USLK.chainDesLKT;                    //■
            var pchainDesLKF = USLK.chainDesLKF;                    //□

            GroupedLink Pdes = (GroupedLink)pchainDesLKT[P.rc, no]; //■
            string      st   = "";

            if (Pdes != null)
            {
                st += "   " + _chainToString2(P, Pdes, -(no + 1)); //■_chainToString2
            }
            Pdes = (GroupedLink)pchainDesLKF[P.rc, no];            //□
            if (Pdes != null)
            {
                if (st.Length > 4)
                {
                    st += "\r";
                }
                else
                {
                    st = "";
                }
                st += "   " + _chainToString2(P, Pdes, no + 1);                             //■_chainToString2
            }
            USLK.stMsg = st;
            return(true);
        }
        private void _LinkSearch(bool printSW = false)
        {
            int IDx = -1;

            // *==* cell-cell link
            for (int no = 0; no < 9; no++)
            {
                for (int tfx = 0; tfx < 27; tfx++)
                {
                    int          noB  = 1 << no;
                    List <UCell> PLst = pBDL.IEGetCellInHouse(tfx, noB).ToList();
                    int          szL  = PLst.Count;
                    if (szL <= 1)
                    {
                        continue;
                    }
                    int SW = (szL == 2)? 0: 1;
                    IDx++;
                    var LK1 = new UGLink_unit(IDx, SW, tfx, no, PLst);
                    GLK_UList_All.Add(LK1);
                    Combination cmb = new Combination(szL, 2);
                    while (cmb.Successor())
                    {
                        UCell UC1 = PLst[cmb.Index[0]], UC2 = PLst[cmb.Index[1]];
                        __SetGLinkLstSet(LK1, SW, tfx, no, UC1, UC2);
                    }
                }
            }

            // *==* in-cell link
            foreach (var P in pBDL.Where(p => p.No == 0))
            {
                int   rc    = P.rc;
                int[] noLst = P.FreeB.IEGet_BtoNo().ToArray();
                int   szL   = noLst.Length;
                if (szL <= 1)
                {
                    continue;
                }
                int SW = (szL == 2)? 0: 1;
                IDx++;
                var LK2 = new UGLink_unit(IDx, SW, rc, P.FreeB);
                GLK_UList_All.Add(LK2);

                Combination cmb = new Combination(szL, 2);
                while (cmb.Successor())
                {
                    int no1 = noLst[cmb.Index[0]], no2 = noLst[cmb.Index[1]];
                    __SetGLinkLstSet(LK2, SW, rc, no1, no2);
                }
            }

            if (printSW)
            {
                WriteLine($"============================ stage:{stageNo} GLK_UList_All");
                foreach (var P in GLK_UList_All)
                {
                    WriteLine(P);
                }
                WriteLine($"============================ stage:{stageNo} GLK_connection");
                foreach (var rc in Enumerable.Range(0, 81))
                {
                    foreach (var no in Enumerable.Range(0, 9))
                    {
                        if (GLK_connection[rc, no] != null)
                        {
                            GLK_connection[rc, no].ForEach(P => WriteLine(P.ToString_rcno(rc, no)));
                        }
                    }
                }
            }
        }
        //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);
        }
        private int _GroupedNL_CheckSolution(GroupedLink GLK0, GroupedLink GLKnxt,
                                             Stack <GroupedLink> SolStack, Bit81 UsedCs)
        {
            bool SolFound = false;
            int  SolType  = pSprLKsMan.Check_SuperLinkSequence(GLKnxt, GLK0)? 1: 2; //1:Continuous 2:DisContinuous

            if (SolType == 1)                                                       //<>continuous
            {
                List <GroupedLink> SolLst = SolStack.ToList();
                //___Debug_Print_GNLChain(SolStack);

                SolLst.Reverse();
                SolLst.Add(GLK0);

                Bit81 UsedCsTmp = new Bit81(UsedCs);
                SetUsed(ref UsedCsTmp, GLKnxt);

                foreach (var LK in SolLst.Where(P => (P.type == W)))
                {
                    int   noB   = 1 << LK.no;
                    Bit81 SolBP = new Bit81();

                    LK.UGCellsA.ForEach(P => { if ((P.FreeB & noB) > 0)
                                               {
                                                   SolBP.BPSet(P.rc);
                                               }
                                        });
                    LK.UGCellsB.ForEach(P => { if ((P.FreeB & noB) > 0)
                                               {
                                                   SolBP.BPSet(P.rc);
                                               }
                                        });
                    if (SolBP.BitCount() <= 1)
                    {
                        continue;
                    }
                    foreach (var P in pBDL.Where(p => (p.FreeB & noB) > 0))
                    {
                        if (UsedCsTmp.IsHit(P.rc))
                        {
                            continue;
                        }
                        if (!(SolBP - ConnectedCells[P.rc]).IsZero())
                        {
                            continue;
                        }
                        if ((P.FreeB & noB) == 0)
                        {
                            continue;
                        }
                        P.CancelB |= noB;   //exclusion digit
                            SolFound = true;
                    }
                }

                var LKpre = SolLst[0];
                foreach (var LK in SolLst.Skip(1))
                {
                    if (LKpre.type == S && LK.type == S && LK.UGCellsA.Count == 1)
                    {
                        var P    = pBDL[LK.UGCellsA[0].rc]; //(for MultiAns code)
                        int noB2 = P.FreeB - ((1 << LKpre.no2) | (1 << LK.no));
                        if (noB2 > 0)
                        {
                            P.CancelB |= noB2; SolFound = true;
                        }
                    }
                    LKpre = LK;
                }
                if (SolFound)
                {
                    SolCode = 1;
                }
            }
            else
            {
                                                         //<>discontinuous
                int   dcTyp = GLK0.type * 10 + GLKnxt.type;
                UCell P     = pBDL[GLK0.UGCellsA[0].rc]; //(for MultiAns code)
                switch (dcTyp)
                {
                case 11:
                    P.FixedNo = GLK0.no + 1;        //Cell number determination
                    P.CancelB = P.FreeB.DifSet(1 << (GLK0.no));
                    SolCode   = 1; SolFound = true; //(1:Fixed)
                    break;

                case 12: P.CancelB = 1 << GLKnxt.no; SolCode = 2; SolFound = true; break;//(2:Exclude from candidates)

                case 21: P.CancelB = 1 << GLK0.no; SolCode = 2; SolFound = true; break;

                case 22:
                    if (GLK0.no == GLKnxt.no)
                    {
                        P.CancelB = 1 << GLK0.no; SolFound = true; SolCode = 2;
                    }
                    break;
                }
            }

            if (SolFound)
            {
                return(SolType);
            }
            return(-1);
        }
 public readonly int nRCC = -1; //no:0...8(In the case of doubly, make links individually)
 public LinkCellALS(UCell UC, UALS ALS, int nRCC)
 {
     this.UC = UC; this.ALS = ALS; this.nRCC = nRCC;
 }
Exemplo n.º 6
0
        public IEnumerable <GroupedLink> IEGet_SuperLink(GroupedLink GLKpre)
        {
            int  SWCtrl = GLKpre.type;
            bool ALSpre = GLKpre is ALSLink;

            if (GLKpre.UGCellsB.Count == 1)
            {
                UCell            U    = GLKpre.UGCellsB[0];
                List <UCellLink> Plst = CeLKMan.CeLK81[U.rc];
                if (Plst != null)
                {
                    foreach (var LK in Plst)
                    {
                        if (ALSpre && LK.type != W)
                        {
                            continue;
                        }
                        GroupedLink GLK = new GroupedLink(LK);
                        if (Check_SuperLinkSequence(GLKpre, GLK))
                        {
                            yield return(GLK);
                        }
                    }
                }
            }

            if (GNPXApp000.GMthdOption["GroupedCells"] == "1")
            {
                foreach (var GP in GLKMan.GrpCeLKLst)
                {
                    if (ALSpre && GP.type != W)
                    {
                        continue;
                    }
                    if (!GLKpre.UGCellsB.EqualsRC(GP.UGCellsA))
                    {
                        continue;
                    }
                    if (GLKpre.no2 != GP.no)
                    {
                        continue;
                    }
                    if (Check_SuperLinkSequence(GLKpre, GP))
                    {
                        yield return(GP);
                    }
                }
            }

            if (GNPXApp000.GMthdOption["ALS"] == "1" && ALSMan.AlsInnerLink != null)
            {
                if (GLKpre.type == W)
                {
                    foreach (var GP in ALSMan.AlsInnerLink.Where(p => (p.ALSbase.Level == 1)))
                    {
                        if (GLKpre.no2 != GP.no)
                        {
                            continue;
                        }
                        if (GLKpre.UGCellsB.Equals(GP.UGCellsA))
                        {
                            yield return(GP);
                        }
                    }
                }
            }

            if (ALSpre)
            {
                ALSLink ALK   = GLKpre as ALSLink;
                int     noB   = 1 << ALK.no2;
                Bit81   BPnoB = new Bit81(pBDL, noB);

                Bit81 BP = BPnoB & ALK.UGCellsB.B81;
                //      ALK.UGCellsB.ForEach(P=>{ if((P.FreeB&noB)>0) BP.BPSet(P.rc); });

                Bit81 UsedCs = GLKpre.UsedCs;
                for (int tfx = 0; tfx < 27; tfx++)
                {
                    Bit81 HS = BPnoB & pHouseCells[tfx];
                    if (!(BP - HS).IsZero())
                    {
                        continue;
                    }
                    if ((HS - BP).IsZero())
                    {
                        continue;
                    }

                    Bit81 NxtBP = HS - BP - UsedCs;
                    if (NxtBP.IsZero())
                    {
                        continue;
                    }

//C                        WriteLine("\n tfx:"+tfx );
//C                        WriteLine( "   BP:"+BP );
//C                        WriteLine( "   HS:"+HS );
//C                        WriteLine( "HS-BP:"+(HS-BP) );
//C                        WriteLine( "NxtBP:"+NxtBP );

                    List <UCell> NxtCs = NxtBP.ToList().ConvertAll(rc => pBDL[rc]);
                    for (int k = 1; k < (1 << NxtCs.Count); k++)
                    {
                        UGrCells NxtGrpdCs = new UGrCells(tfx, ALK.no2);
                        int      kb        = k;
                        for (int n = 0; n < NxtCs.Count; n++)
                        {
                            if ((kb & 1) > 0)
                            {
                                NxtGrpdCs.Add(new UGrCells(NxtCs[n], ALK.no2));
                            }
                            kb >>= 1;
                        }
                        GroupedLink GP = new GroupedLink(GLKpre.UGCellsB, NxtGrpdCs, tfx, W);
//C                        WriteLine( GP );
                        yield return(GP);
                    }
                }
            }
            yield break;
        }
        private int _NL_CheckSolution(UCellLink LK0, UCellLink LKnxt, Stack <UCellLink> SolStack, Bit81 UsedCells)
        {
            bool SolFound = false;
            int  SolType  = CeLKMan.Check_CellCellSequence(LKnxt, LK0)? 1: 2; //1:Continuous 2:DisContinuous

            if (SolType == 1)                                                 //===== continuous =====
            //=== Change WeakLink to StrongLink
            {
                List <UCellLink> SolLst     = SolStack.ToList();
                Bit81            UsedCellsT = UsedCells | (new Bit81(LK0.rc1));
                foreach (var L in SolLst)
                {
                    int noB = 1 << L.no;
                    foreach (var P in pBDL.IEGetCellInHouse(L.tfx, noB))
                    {
                        if (UsedCellsT.IsHit(P.rc))
                        {
                            continue;
                        }
                        P.CancelB |= noB;
                        SolFound   = true;
                    }
                }

                //=== S-S (There are no other numbers)
                SolLst.Reverse();
                SolLst.Add(LK0);
                var LKpre = SolLst[0];
                foreach (var LK in SolLst.Skip(1))
                {
                    if (LKpre.type == 1 && LK.type == 1) //S-S
                    {
                        UCell P   = pBDL[LK.rc1];
                        int   noB = P.FreeB.DifSet((1 << LKpre.no) | (1 << LK.no));
                        if (noB > 0)
                        {
                            P.CancelB = noB; SolFound = true;
                        }
                    }
                    LKpre = LK;
                }
                if (SolFound)
                {
                    SolCode = 2;
                }
            }
            else if (SolType == 2)               //===== discontinuous =====
            {
                UCell P     = pBDL[LK0.UCe1.rc]; //(for MultiAns code)
                int   dcTyp = LK0.type * 10 + LKnxt.type;
                switch (dcTyp)
                {
                case 11:
                    P.FixedNo = LK0.no + 1;         //Cell number determination
                    P.CancelB = P.FreeB.DifSet(1 << (LK0.no));
                    SolCode   = 1; SolFound = true; //(1:Fixed)
                    break;

                case 12: P.CancelB = 1 << LKnxt.no; SolCode = 2; SolFound = true; break;//(2:Exclude from candidates)

                case 21: P.CancelB = 1 << LK0.no; SolCode = 2; SolFound = true; break;

                case 22:
                    if (LK0.no == LKnxt.no)
                    {
                        P.CancelB = 1 << LK0.no; SolFound = true; SolCode = 2;
                    }
                    break;
                }
            }
            if (SolFound)
            {
                return(SolType);
            }
            return(-1);
        }
        public string SDK_Nomalize(bool DspSolB, bool NrmlNum)
        {
            int[]        TPw   = new int[18];
            List <int[]> TPLst = new List <int[]>();

            if (pGP.AnsNum == null)
            {
                Initialize();                  //Solve
            }
            #region Standardization(Pattern)
            RCX = new int[4, 12];
            for (int k = 0; k < 9; k++)
            {
                RCX[0, k] = RCX[1, k] = k;
            }
            for (int k = 0; k < 3; k++)
            {
                RCX[0, k + 9] = RCX[1, k + 9] = k * 3;
            }

            int minV = int.MaxValue;
            //===== step1 =====
            for (int tx = 0; tx < 2; tx++)
            {
                TPw[8] = tx;
                for (int rx0 = 0; rx0 < 6; rx0++)
                {
                    TPw[0] = rx0; SetRCX(0, TPw);
                    for (int rx1 = 0; rx1 < 6; rx1++)
                    {
                        TPw[1] = rx1; SetRCX(1, TPw);

                        for (int cx4 = 0; cx4 < 6; cx4++)
                        {
                            TPw[4] = cx4; SetRCX(4, TPw);
                            for (int cx5 = 0; cx5 < 6; cx5++)
                            {
                                TPw[5] = cx5; SetRCX(5, TPw);
                                SDK_TransIX(TPw);

                                if (TPw[9] > minV)
                                {
                                    continue;
                                }
                                minV = TPw[9];
                                int[] TPtmp = new int[18];
                                TPw.CopyTo(TPtmp, 0);
                                TPLst.Add(TPtmp);
                            }
                        }
                    }
                }
            }
            TPLst.Sort((A, B) => (A[9] - B[9]));

            //===== step2 =====
            minV  = TPLst[0][9];
            TPLst = TPLst.FindAll(P => P[9] == minV).ToList();
            int TPLstCount = TPLst.Count;
            for (int hx = 0; hx < TPLstCount; hx++)
            {
                TPw[8] = TPLst[hx][8]; SetRCX(8, TPw);
                for (int mx = 0; mx < 18; mx++)
                {
                    TPw[mx] = TPLst[hx][mx];
                    if (mx < 9)
                    {
                        SetRCX(mx, TPw);
                    }
                }
                for (int cx6 = 0; cx6 < 6; cx6++)
                {
                    TPw[6] = cx6; SetRCX(6, TPw);
                    for (int cx7 = 0; cx7 < 6; cx7++)
                    {
                        TPw[7] = cx7; SetRCX(7, TPw);
                        SDK_TransIX(TPw);

                        if (TPw[9] > minV)
                        {
                            continue;
                        }
                        minV = TPw[9];
                        int[] TPtmp = new int[18];
                        TPw.CopyTo(TPtmp, 0);
                        TPLst.Add(TPtmp);
                    }
                }
            }
            TPLst.Sort((A, B) => (A[9] - B[9]));

            //===== step3 =====
            minV       = TPLst[0][9];
            TPLst      = TPLst.FindAll(P => P[9] == minV).ToList();
            minV       = TPLst[0][10];
            TPLstCount = TPLst.Count;
            for (int hx = 0; hx < TPLstCount; hx++)
            {
                TPw[8] = TPLst[hx][8]; SetRCX(8, TPw);
                for (int mx = 0; mx < 18; mx++)
                {
                    TPw[mx] = TPLst[hx][mx];
                    if (mx < 9)
                    {
                        SetRCX(mx, TPw);
                    }
                }
                for (int rx2 = 0; rx2 < 6; rx2++)
                {
                    TPw[2] = rx2; SetRCX(2, TPw);
                    for (int rx3 = 0; rx3 < 6; rx3++)
                    {
                        TPw[3] = rx3; SetRCX(3, TPw);
                        SDK_TransIX(TPw);

                        if (TPw[10] > minV)
                        {
                            continue;
                        }
                        minV = TPw[10];
                        int[] TPtmp = new int[18];
                        TPw.CopyTo(TPtmp, 0);
                        TPLst.Add(TPtmp);
                    }
                }
            }
            TPLst.Sort((A, B) => {
                if (A[10] != B[10])
                {
                    return(A[10] - B[10]);
                }
                return(A[11] - B[11]);
            });
            minV = TPLst[0][10];
            int minV1 = TPLst[0][11];
            TPLst = TPLst.FindAll(P => (P[10] == minV && P[11] == minV1)).ToList();

            string[] stLst = new string[TPLst.Count];
            for (int k = 0; k < TPLst.Count; k++)
            {
                TPLst[k].CopyTo(TrPara, 0);
                SetRCX(8, TPw);
                for (int mx = 0; mx < 9; mx++)
                {
                    SetRCX(mx, TrPara);
                }
                SDK_TransIX(TrPara, TransB: true, DspSolB: DspSolB);

                string st = pGNP.SDKCntrl.Get_SDKNumPattern(TrPara, pGP.AnsNum);//Latin square
                st        += TransToString(TrPara);
                stLst[k]   = st;
                TrPara[17] = k;
                for (int n = 0; n < TrPara.Count(); n++)
                {
                    TPLst[k][n] = TrPara[n];
                }

                /*
                 *      string st="RCX:";
                 *      for(int j=0; j<4; j++ ){
                 *          for(int m=0;m<12; m++ ) st+=" "+RCX[j,m];
                 *          st+=" / ";
                 *      }
                 *
                 *      for(int m=0; m<9; m++ ) st+=" "+TrPara[m];
                 *      st+="//";
                 *      int[] IDC=new int[4];
                 *      for(int m=9; m<13; m++ ){ IDC[m-9]=TrPara[m]; st+=" "+TrPara[k]; }
                 *      WriteLine(st);
                 *   // Bit81 BP=new Bit81(IDC);
                 *   // WriteLine(BP);
                 */
            }

            TPLst.Sort((A, B) => {
                for (int k = 9; k < A.Count(); k++)
                {
                    if (A[k] != B[k])
                    {
                        return(A[k] - B[k]);
                    }
                }
                return(0);
            });

            TrPara = TPLst[0];
            SetRCX(8, TrPara);
            for (int mx = 0; mx < 8; mx++)
            {
                SetRCX(mx, TrPara);
            }
            #endregion

            //Standardization(Latin square)
            SDK_TransIX(TrPara, TransB: true, DspSolB: DspSolB);

            if (NrmlNum)
            {
                int[] chgNum = new int[10];
                int   NN     = TrPara[15];
                for (int k = 0; k <= 9; k++)
                {
                    chgNum[9 - k] = NN % 10; NN /= 10;
                }
                for (int rc = 0; rc < 81; rc++)
                {
                    int   No = pGP.AnsNum[rc];
                    UCell P  = pGP.BDL[rc];
                    if (P.No > 0)
                    {
                        pGP.AnsNum[rc] = P.No = chgNum[No];
                    }
                    else
                    {
                        pGP.AnsNum[rc] = P.No = -chgNum[-No];
                    }
                }
            }

            /*
             *          string po="◆";
             *          for(int k=0; k<18; k++ ) po+=" "+TrPara[k];
             *          WriteLine(po);
             */
            return(stLst[TrPara[17]]);
        }
        //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);
        }
        private string _XYwingResSub(UCell P)
        {
            string st = P.rc.ToRCNCLString() + "(#" + P.FreeB.ToBitStringNZ(9) + ")";

            return(st);
        }
Exemplo n.º 11
0
        //Search for groupedLink_sequence starting from rc0#no0 as true.
        public USuperLink Eval_SuperLinkChainEx(int rc0, int no0, bool DevelopB)
        {
            try{
                int dbX = 0;
                _dbCC = 0;

                USuperLink GNL_Result  = new USuperLink(rc0, no0);
                var        Qtrue       = GNL_Result.Qtrue;
                var        Qfalse      = GNL_Result.Qfalse;
                var        chainDesLKT = GNL_Result.chainDesLKT;
                var        chainDesLKF = GNL_Result.chainDesLKF;

                var rcQue = new Queue <GroupedLink>();

                UCell P0   = pBDL[rc0];                 //Origin Cell
                int   no0B = 1 << no0;                  //Origin Digit
                Qtrue[no0].BPSet(rc0);

                //P is Cell.  R,RR,RRR is GroupedLink
                {//====================== Start with WeakLink(origin:rc#no0) ======================
                    foreach (var R in IEGet_SuperLinkFirst(P0, no0).Where(X => X.type == W))
                    {
                        if (DevelopB)
                        {
                            Write("*1st:" + R.GrLKToString()); __Debug_ChainPrint(R);
                        }

                        R.UsedCs       = R.UGCellsA.B81;            //set usedcells(accumulate)
                        R.preGrpedLink = null;                      //GLKnoR0;                              //set pre-GLink
                        rcQue.Enqueue(R);                           //enqueue next-GLink to RadiationSearchQueue

                        foreach (var P in R.UGCellsB.Where(p => (p.FreeB & no0B) > 0))
                        {
                            int no2 = R.no2;
                            Qfalse[no2].BPSet(P.rc);                              //set p.rc#no2 to false
                            chainDesLKF[P.rc, no2] = R;                           //��                              //record in retroactive chain
                            if (DevelopB)
                            {
                                WriteLine($"        12 W *Rad->{P}  --#{no2} is false.");
                            }
                        }
                    }
                    foreach (var nox in pBDL[rc0].FreeB.IEGet_BtoNo().Where(p => p != no0))
                    {
                        Qfalse[nox].BPSet(rc0);
                    }
                }

                //====================== Radiation Search ===============================
                while (rcQue.Count > 0)
                {
                    {   //----- Distinct -----
                        var Q2 = rcQue.ToList().Distinct();
                        rcQue.Clear();
                        foreach (var X in Q2)
                        {
                            rcQue.Enqueue(X);
                        }
                        //if(DevelopB){ WriteLine("\r"); foreach(var P in rcQue) WriteLine($"--rcQue---{P.GrLKToString()}"); WriteLine("\r"); }
                    }

                    GroupedLink R = rcQue.Dequeue();                                                         //dequeue next element
                    if (DevelopB)
                    {
                        WriteLine($"\r{dbX++}---Queue:" + R.GrLKToString());
                    }

                    foreach (var RR in IEGet_SuperLink(R).Where(p => p.AvailableF)) //foreach next GLink
                    {
                        RR.preGrpedLink = R;                                        //set preLink
                        if (!(R.UsedCs & RR.UGCellsB.B81).IsZero())
                        {
                            continue;                                                    //Skip by used Cells
                        }
                        if (DevelopB)
                        {
                            WriteLine($"\r   {dbX++}--RR:" + RR.GrLKToString());
                        }

                        RR.UsedCs = R.UsedCs | RR.UGCellsA.B81;
                        if (DevelopB)
                        {
                            __Debug_ChainPrint(RR); WriteLine($"��   {dbX++}-{++chkX}--RR:" + RR.GrLKToString());
                        }

                        int no2 = RR.no2;                               //no2:next digit
                        if (RR.type == S)                               // F->T   *=*=* Check connection conditions. case StrongLink *=*=*
                        {
                            if (RR.UGCellsB.Count == 1)                 //if the link's next element is a single cell
                            {
                                var P = RR.UGCellsB[0];                 //P:next cell
                                if (Qtrue[no2].IsHit(P.rc))
                                {
                                    continue;                                            //Already setted. Eliminate unnecessary trials and speed up.
                                }
                                Qtrue[no2].BPSet(P.rc);                                  //set P.rc#no2 is true
                                chainDesLKT[P.rc, no2] = RR;                             //record in retroactive chain
                                if (DevelopB)
                                {
                                    WriteLine($"        31S ->P:{P}  ++#{no2} is true.");
                                }

                                foreach (var nox in P.FreeB.IEGet_BtoNo().Where(q => (q != no2)))
                                {
                                    Qfalse[nox].BPSet(P.rc);                                                                 //set p.rc#nox to false
                                    if (DevelopB)
                                    {
                                        WriteLine($"        32S ->P:{P}  --#{nox} is false.");
                                    }
                                }
                            }
                        }

                        else if (RR.type == W)                          // T->F   *=*=* Check connection conditions. case WeakLink *=*=*
                        {
                            foreach (var P in RR.UGCellsB)              //foreach next GLink
                            {
                                Qfalse[no2].BPSet(P.rc);                //set P.rc#no2 is false
                                if (DevelopB)
                                {
                                    WriteLine($"        40W ->P:{P}  ++#{no2} is false.");
                                }
                                chainDesLKF[P.rc, no2] = RR;                                                             //record in retroactive chain
                            }

                            if (RR.UGCellsB.Count == 1)                                                              //if the link's next element is a single cell
                            {
                                var P = RR.UGCellsB[0];
                                if (P.FreeBC == 2)                                                                       //If the next is a binary cell
                                {
                                    int nox = P.FreeB.DifSet(1 << no2).BitToNum();
                                    if (Qtrue[nox].IsHit(P.rc))
                                    {
                                        continue;                                        //Already setted. Eliminate unnecessary trials and speed up.
                                    }
                                    Qtrue[nox].BPSet(P.rc);                              //set P.rc#no2 is true
                                    if (DevelopB)
                                    {
                                        WriteLine($"        41W ->P:{P}  ++#{nox} is true.");
                                    }

                                    GroupedLink RRR = new GroupedLink(P, no2, nox, S);                                       //GLKbv:GLink in cell(P#no2 StrongLink)
                                    RRR.preGrpedLink       = RR;                                                             //set preLink
                                    chainDesLKT[P.rc, nox] = RRR;                                                            //record in retroactive chain
                                }
                            }
                        }
                        rcQue.Enqueue(RR);                                                                       //enqueue next-GLink to RadiationSearchQueue                                              //enqueue next-GLink to RadiationSearchQueue
                    }
                }

                GNL_Result.SolFound = true;                                                              //Solution found
                return(GNL_Result);
            }
            catch (Exception ex) {
                WriteLine($"{ex.Message}+\r{ex.StackTrace}");
            }
            return(null);
        }
        public USuperLink GNL_EvalSuperLinkChain(GroupedLink GLK_000, int rc0, bool DevelopB = false)
        {
            try{
                if (DevelopB)
                {
                    WriteLine("\r\r10 *1st:" + GLK_000.GrLKToString()); __Debug_ChainPrint(GLK_000);
                }
                int dbX = 0;
                _dbCC = 0;

                int        no0        = GLK_000.no;
                USuperLink GNL_Result = new USuperLink(rc0, no0);
                var        Qtrue      = GNL_Result.Qtrue;
                var        Qfalse     = GNL_Result.Qfalse;
                Qtrue  = GNL_Result.Qtrue;
                Qfalse = GNL_Result.Qfalse;
                var rcQue = new Queue <GroupedLink>();

                GLK_000.preGrpedLink = null;                                            //sentinel(right GroupedLink's preGrpedLink is null)
                GLK_000.UsedCs       = GLK_000.UGCellsB.B81;                            //Set Used

                int contDiscontF = 0;
                rcQue.Enqueue(GLK_000); //Enqueue first GLK

                {                       //====================== First GLK Process ==============================================================
                    GroupedLink RR = GLK_000;
                    int         no2 = RR.no2, no2B = 1 << no2;
                    if (RR.type == S)                       //---------- Check connection conditions. case StrongLink(F->T) ----------
                    {
                        if (RR.UGCellsB.Count == 1)         //if the link's next element is a single cell
                        {
                            UCell RRnxtC = RR.UGCellsB[0];  //RRnxtC:next cell
                            Qtrue[no2].BPSet(RRnxtC.rc);    //set RRnxtC.rc#no2 is true
                            foreach (int nox in RRnxtC.FreeB.IEGet_BtoNo().Where(q => (q != no2)))
                            {
                                Qfalse[nox].BPSet(RRnxtC.rc);                             //set RRnxtC.rc#no2 to false
                                GroupedLink RRR = new GroupedLink(RRnxtC, no2, nox, W);   //GLK_ViVal:GLink in cell(RRnxtC#no2 WeakLink)
                                RRR.preGrpedLink = RR;                                    //set preLink
                                rcQue.Enqueue(RRR);                                       //enqueue next-GLink to RadiationSearchQueue
                                if (DevelopB)
                                {
                                    WriteLine($"        11 S ->RRnxtC[rc:{RRnxtC.rc}]#{nox} is false."); __Debug_ChainPrint(RRR);
                                }
                            }
                        }
                    }
                    else if (RR.type == W)               //---------- Check connection conditions. case WeakLink(T->F) ----------
                    {
                        foreach (UCell P in RR.UGCellsB) //foreach next GLink
                        {
                            if ((P.FreeB & no2B) > 0)
                            {
                                Qfalse[no2].BPSet(P.rc);                                //set P.rc#no2 is true
                                if (DevelopB)
                                {
                                    WriteLine($"        12 W *Rad->{P}   #{no2} is false.");
                                }
                            }
                        }
                    }
                }

                //====================== Radiation Search ==============================================================
                while (rcQue.Count > 0)
                {
                    {   //----- Distinct -----
                        var Q2 = rcQue.ToList().Distinct();
                        rcQue.Clear();
                        foreach (var X in Q2)
                        {
                            rcQue.Enqueue(X);
                        }
                        //if(DevelopB){ WriteLine("\r"); foreach(var P in rcQue) WriteLine($"--rcQue---{P.GrLKToString()}"); WriteLine("\r"); }
                    }

                    GroupedLink R = rcQue.Dequeue();                                                            //dequeue next element(pre-GLink)
                    if (DevelopB)
                    {
                        WriteLine($"\r20�� {dbX++}---Queue:" + R.GrLKToString()); __Debug_ChainPrint(R);
                    }

                    foreach (GroupedLink RR in IEGet_SuperLink(R).Where(p => p.AvailableF))
                    {
                        if (_IsLooped(RR))
                        {
                            continue;
                        }
                        if (R.type != RR.type && R.UGCellsA.Equals(RR.UGCellsB))
                        {
                            continue;                                                                               //Skip back_links
                        }
                        if (!(R.UsedCs & RR.UGCellsB.B81).IsZero())
                        {
                            continue;
                        }
                        RR.preGrpedLink = R;                                                //set preLink
                        RR.UsedCs       = R.UsedCs | RR.UGCellsB.B81;
                        rcQue.Enqueue(RR);                                                  //enqueue next-GLink to RadiationSearchQueue
                        if (DevelopB)
                        {
                            __Debug_ChainPrint(RR); WriteLine($"��   {dbX++}-{++chkX}--RR:" + RR.GrLKToString());
                        }

                        int no2 = RR.no2; //no2:next digit
                        if (RR.type == S) //========== Check connection conditions. case StrongLink(F->T) ==========
                        //if(!(RR.UGCellsB.B81&Qtrue[RR.no2]).IsZero() )  continue;   //xxx if the next element is already setted true, go to the next process
                        {
                            if (RR.UGCellsB.Count == 1)                                        //if the link's next element is a single cell
                            {
                                UCell P = RR.UGCellsB[0];                                      //RRnxtC:next cell

                                if (P.rc == rc0)                                               //Check Loop completion
                                {
                                    GNL_Result.resultGLK = RR;
                                    SolCode = GroupedNLEx_CheckSolution(GNL_Result, ref contDiscontF);  //There are cells/#n that can be excluded.
                                    if (SolCode > 0)
                                    {
                                        goto  LoopCompletion;                               //Established Sudoku solution
                                    }
                                    goto ErrorTrial;                                        //Failed
                                }

                                if (Qtrue[no2].IsHit(P.rc))
                                {
                                    RR.AvailableF = false; continue;
                                }                                                           //AvailableF=false
                                Qtrue[no2].BPSet(P.rc);                                     // set P.rc#no2 is true
                                if (DevelopB)
                                {
                                    WriteLine($"        30S ->P:{P}  +#{no2} is true.");
                                }

                                foreach (int nox in P.FreeB.IEGet_BtoNo().Where(q => (q != no2)))                               // P.rc#no2:True => #nox(!=no2):False
                                {
                                    if (Qfalse[nox].IsHit(P.rc))
                                    {
                                        continue;
                                    }
                                    Qfalse[nox].BPSet(P.rc);                                //set P.rc#no2 to false
                                    if (DevelopB)
                                    {
                                        WriteLine($"        31S ->P:{P}  -#{nox} is false.");
                                    }
                                }
                            }
                        }

                        else if (RR.type == W)                         //========== Check connection conditions. case WeakLink(T->F) ==========
                        {
                            if (!(RR.UGCellsB.B81 & Qfalse[RR.no2]).IsZero())
                            {
                                continue;                                                                               //if the next element is setted false, go to the next process
                            }
                            foreach (UCell P in RR.UGCellsB)                                                            //foreach next GLink
                            {
                                if (Qfalse[no2].IsHit(P.rc))
                                {
                                    continue;
                                }
                                Qfalse[no2].BPSet(P.rc);                                                                    //set P.rc#no2 is true
                                if (DevelopB)
                                {
                                    WriteLine($"       -40W *RR:{P}  -#{no2} is false.");
                                }
                            }
                            rcQue.Enqueue(RR);                                              //enqueue next-GLink to RadiationSearchQueue

                            if (RR.UGCellsB.Count == 1)                                     //if the link's next element is a single cell
                            {
                                UCell P = RR.UGCellsB[0];
                                if (P.FreeBC == 2)                                                                          //If the next is a binary cell
                                {
                                    int nox = P.FreeB.DifSet(1 << no2).BitToNum();
                                    //if(!_Check_LogicalError_GNL(no2,P.rc,Qtrue) )  goto ErrorTrial; //No check required!
                                    //if(Qtrue[nox].IsHit(P.rc)){ RR.AvailableF=false; continue; }//AvailableF=false. No check required!
                                    Qtrue[nox].BPSet(P.rc);                                   //set P.rc#no2 is true

                                    GroupedLink RRR = new GroupedLink(P, no2, nox, S);        //GLK_ViVal:GLink in cell(P#no2 StrongLink)
                                    RRR.preGrpedLink = RR;                                    //set preLink
                                    if (DevelopB)
                                    {
                                        WriteLine($"       +41W *RR:{P}  -#{nox} is true. :{RRR.GrLKToString()}");
                                    }

                                    if (P.rc == rc0)
                                    {
                                        GNL_Result.resultGLK = RR;
                                        SolCode = GroupedNLEx_CheckSolution(GNL_Result, ref contDiscontF);
                                        if (SolCode > 0)
                                        {
                                            goto  LoopCompletion;                          //Solution found
                                        }
                                        goto ErrorTrial;
                                    }
                                }
                            }
                        }
                    }
                }
                return(null);

ErrorTrial:
                return(null);

LoopCompletion:
                GNL_Result.contDiscontF = contDiscontF;

                if (DevelopB)
                {
                    L2SprLkB81[no0].BPSet(rc0);                                                        // Set the searched flag
                    if (DevelopB)
                    {
                        developDisp(rc0, no0, GNL_Result, DevelopB);
                    }
                    L2SprLK[rc0, no0] = GNL_Result;
                }

                return(GNL_Result);
            }
            catch (Exception ex) {
                WriteLine($"{ex.Message}+\r{ex.StackTrace}");
            }
            return(null);
        }
 public UCellLink(UCell UCe1, UCell UCe2, int no, int type)
 {
     this.UCe1 = UCe1; this.UCe2 = UCe2; this.no = no; this.type = type;
 }
        private void __SetGLinkLstSet(UGLink_unit LKx, int SW, int tfx, int no, UCell UC1, UCell UC2)       // cell-cell link
        {
            int rc1 = UC1.rc, rc2 = UC2.rc;

            UGLink_pair LK1 = new UGLink_pair(LKx, SW, rc2, no);

            if (GLK_connection[rc1, no] == null)
            {
                GLK_connection[rc1, no] = new List <UGLink_pair>();
            }
            GLK_connection[rc1, no].Add(LK1);

            UGLink_pair LK2 = new UGLink_pair(LKx, SW, rc1, no);

            if (GLK_connection[rc2, no] == null)
            {
                GLK_connection[rc2, no] = new List <UGLink_pair>();
            }
            GLK_connection[rc2, no].Add(LK2);
        }
Exemplo n.º 15
0
        public IEnumerable <UBasCov> IEGet_BaseSet(int sz, int rnk)
        {
            if (UGLLst == null)
            {
                yield break;
            }

            BSstatus = new BaseSet_Status(sz, rnk);

            List <UGLink> basUGLs   = BSstatus.basUGLs;                                     //BaseSet List
            Bit981        HB981     = BSstatus.HB981;                                       //BaseSet bitPattern
            Bit324        usedLK    = BSstatus.usedLK;                                      //usedLink(by serial number)
            List <int>    usedLKLst = BSstatus.usedLKLst;

            long RCBN_frameA = 0;

            _jkc_ = 0;
            var cmbBas = new Combination(UGLLst.Count, sz);
            int nxt    = int.MaxValue; //(skip function)

            while (cmbBas.Successor(nxt))
            {
                GeneralLogicGen.ChkBas0++;   //*****

                _jkc_++;
                //  sz=1  *==*==*==*==*==*==*==*==*==*==*==*==*==*==*==*==*==*==*==*==*==*==*==*
                if (sz == 1)
                {
                    UGLink UGL = UGLLst[cmbBas.Index[0]];
                    if (UGL.UC is UCell)
                    {
                        goto LNextSet;                                                      //only row/column/block link.
                    }
                    HB981.Clear(); HB981.BPSet(UGL.rcBit81.no, UGL.rcBit81, tfbSet: false); //accumulate rcbn info. in HB981.
                    basUGLs.Clear(); basUGLs.Add(UGL);                                      //set UGL in BaseSet

                    GeneralLogicGen.ChkBas1++;                                              //*****
                    goto LBSFound;                                                          //possibility of solution
                }
                //===================================================================================================================

                //  sz>=2  *==*==*==*==*==*==*==*==*==*==*==*==*==*==*==*==*==*==*==*==*==*==*==*
                HB981.Clear();
                basUGLs.Clear();
                usedLKLst.Clear();
                BSstatus.Clear();

                RCBN_frameA = 0;
                int[] _RCB_frameB = new int[9];
                for (int k = 0; k < sz; k++)                                                   //(r:row c:column b:block n:digit => rcbn)
                {
                    nxt = k;
                    UGLink UGL = UGLLst[cmbBas.Index[k]];
                    RCBN_frameA |= UGL.RCBN_frameB;                                         //bit expression of rcbn

                    if (!Check_rcbnCondition(sz, rnk, k, RCBN_frameA))
                    {
                        goto LNextSet;                                   //### extremely efficient
                    }
                    if (UGL.rcBit81 is Bit81)                            // ........................ rcb link  ........................
                    {
                        int no = UGL.rcBit81.no;
                        if (k > 0 && HB981.IsHit(no, UGL.rcBit81))
                        {
                            goto LNextSet;                          //elements already included in HB981
                        }
                        HB981.BPSet(no, UGL.rcBit81, tfbSet: true); //accumulate rcbn info. in HB981.
                        usedLKLst.Add(UGL.rcBit81.ID);              //(ID=tfx<<4 | no)              //[rcb_link type]register ID to used list.
                        _RCB_frameB[no] |= (int)UGL.RCBN_frameB & 0x3FFFFFF;
                    }
                    else                                                // ....................... Cell link ........................
                    {
                        UCell UC = UGL.UC;
                        int   rc = UC.rc;
                        //In UGLLst, rcb-Links is first, and cell-Links is second.
                        //Even in combination, this order is maintained.
                        //Therefore, the condition "cell-links have common parts with rcb-Links?" is satisfied.
                        foreach (var no in UC.FreeB.IEGet_BtoNo(9))
                        {
                            if (k > 0 && HB981.IsHit(no, rc))
                            {
                                goto LNextSet;                                              //Not BaseSet as it has no intersection.
                            }
                            HB981.BPSet(no, rc, tfbSet: true);                              //accumulate rcbn info. in HB981.
                            _RCB_frameB[no] |= rc.ToRCBitPat();
                        }
                        int IDrc = rc << 4 | 0xF; //( 0xF:Cell type identification flag )
                        usedLKLst.Add(IDrc);      //(ID=rc<<4| no)               //[cell type]register ID to used list.
                    }
                    basUGLs.Add(UGL);             //set UGL in BaseSet
                                                  // ...........................................................
                }
                BSstatus.RCB_frameB = _RCB_frameB;
                __UsedLinkToFrame(HB981, usedLKLst, BSstatus);

////                if(SDK_Ctrl.UGPMan.stageNo==8 && _usedLKLst_ToRCBString("",usedLKLst)==" c1#3 c1#6"){
////                    Board_Check("*** Check_6 ?");
////                }

                if (SDK_Ctrl.UGPMan.stageNo == 20 && _usedLKLst_ToRCBString("", usedLKLst) == " r3#2 r4#2 r3#8")
                {
                    WriteLine(_usedLKLst_ToRCBString($"usedLKLst:{_jkc_}", usedLKLst, addFreeBB: true));
                    Board_Check();
                }

                //*==*==*==*==*==*==*==*==*==*==*==*==*==*==*==*==*==*==*==*==*==*==*==*
//                Board_Check();
                //1..4....8.9.1...5.....63.....13.5.79..3...8..76.2.94.....75.....1...6.4.8....4..2

                if (!BSstatus.Check_1())
                {
                    goto LNextSet;                            //A and B are not linked by other link(C).
                }
                if (!BSstatus.Check_2())
                {
                    goto LNextSet;                            //Each cell(A) is in a position to link with other cells.
                }
                if (!BSstatus.Check_3())
                {
                    goto LNextSet;                            //There is a limit to the number of cells that have no links other than BaseSet.
                }
                //*==*==*==*==*==*==*==*==*==*==*==*==*==*==*==*==*==*==*==*==*==*==*==*

                /*
                 *        //if(SDK_Ctrl.UGPMan.stageNo==12 && sz>=3){// && rnk==1 ){
                 *          if(SDK_Ctrl.UGPMan.stageNo==9 && sz>=2){// && rnk==1 ){
                 *              WriteLine($"\r sz:{sz} rnk:{rnk} jkc:{_jkc_}");
                 *              Check_rcbnCondition(sz,rnk,sz,RCBN_frameA,printB:true);
                 *              basUGLs.ForEach(P=>WriteLine(P.ToString("BaseSet")));
                 *          }
                 */

LBSFound:
                usedLK.Clear();
                basUGLs.ForEach(P => usedLK.BPSet(P.IDnum)); //IDrc: rc<<17 | 1<<16
                UBasCov UBC = new UBasCov(basUGLs, HB981, sz, usedLK);
                yield return(UBC);

                //---------------------------------------------------------------------------------------
LNextSet:
                continue;
            }
            yield break;

            void __UsedLinkToFrame(Bit981 HB981, List <int> usedLKLst, BaseSet_Status BSstatus)
            {
                int[] _frame_0 = new int[9];
                int[] _frame_1 = new int[9];
                Bit81 _frame_T = new Bit81();
                int   frm, _cellC = 0;

                foreach (var no in HB981.noBit.IEGet_BtoNo())
                {
                    _frame_0[no] = frm = HB981._BQ[no].IEGetRC().Aggregate(0, (Q, rc) => Q | rc.ToRCBitPat());
                    _frame_1[no] = ___frame_ResetUsed(frm, no, usedLKLst);
                    _frame_T    |= HB981._BQ[no];
                }
                Bit81 _frame_81 = new Bit81(_frame_T);

                usedLKLst.ForEach(P => { if ((P & 0xF) == 0xF)
                                         {
                                             _frame_81.BPReset(P >> 4); _cellC++;
                                         }
                                  });

                BSstatus._frame_0  = _frame_0;
                BSstatus._frame_1  = _frame_1;
                BSstatus._frame_T  = _frame_T;
                BSstatus._frame_81 = _frame_81;
                BSstatus._cellC    = _cellC;        //(Number of cell links in BaseSet)
            }
        }
        //W-Wing is an algorithm composed of bivalue cell and link.
        //http://csdenpe.web.fc2.com/page43.html
        public bool  Wwing( )
        {
            Prepare();
            CeLKMan.PrepareCellLink(1);    //Generate StrongLink

            if (BVCellLst == null)
            {
                BVCellLst = pBDL.FindAll(p => (p.FreeBC == 2));             //BV:BiValue
            }
            if (BVCellLst.Count < 2)
            {
                return(false);
            }
            BVCellLst.Sort((A, B) => (A.FreeB - B.FreeB));                       //Important!!!

            bool Wwing = false;
            var  cmb   = new Combination(BVCellLst.Count, 2);
            int  nxt   = 99;

            while (cmb.Successor(nxt))
            {
                UCell P = BVCellLst[cmb.Index[0]];
                UCell Q = BVCellLst[cmb.Index[1]];
                nxt = 1;
                if (P.FreeB != Q.FreeB)
                {
                    nxt = 0; continue;
                }                                                           //BVCellLst is sorted, so possible to skip.
                if (ConnectedCells[P.rc].IsHit(Q.rc))
                {
                    continue;
                }

                foreach (var L in CeLKMan.IEGetCellInHouse(1))               //1:StrongLink(Link has a direction. The opposite link is different.)
                {
                    int no1B = (1 << L.no);
                    if ((P.FreeB & no1B) == 0)
                    {
                        continue;
                    }
                    if (L.rc1 == P.rc || L.rc2 == Q.rc)
                    {
                        continue;
                    }
                    if (!ConnectedCells[P.rc].IsHit(L.rc1))
                    {
                        continue;                                           //L.rc1 is in the connected area of ​​P.rc?
                    }
                    if (!ConnectedCells[Q.rc].IsHit(L.rc2))
                    {
                        continue;                                           //L.rc2 is in the connected area of Q.rc?
                    }
                    int no2B = P.FreeB.BitReset(L.no);                      //another digit

                    string msg2 = "";
                    Bit81  ELM  = ConnectedCells[P.rc] & ConnectedCells[Q.rc]; //ELM:Common part of the influence area of ​​cell P and cell Q
                    foreach (var E in ELM.IEGetUCeNoB(pBDL, no2B))             //Cell/digit in ELM can be excluded
                    {
                        E.CancelB = no2B; Wwing = true;                        //W-Wing found
                        if (SolInfoB)
                        {
                            msg2 += " " + E.rc.ToRCString();
                        }
                    }
                    if (!Wwing)
                    {
                        continue;
                    }

                    SolCode = 2;
                    if (SolInfoB)
                    {
                        UCell A = pBDL[L.rc1], B = pBDL[L.rc2];
                        int   noBX = P.FreeB.DifSet(no2B);
                        P.SetNoBBgColor(noBX, AttCr, SolBkCr2);
                        Q.SetNoBBgColor(noBX, AttCr, SolBkCr2);

                        A.SetNoBBgColor(no1B, AttCr, SolBkCr);
                        B.SetNoBBgColor(no1B, AttCr, SolBkCr);

                        string msg0 = $" bvCell: {_XYwingResSub(P)} ,{_XYwingResSub(Q)}";
                        string msg1 = $"  SLink: {A.rc.ToRCNCLString()}-{B.rc.ToRCNCLString()}(#{(L.no+1)})";
                        Result     = $"W Wing Eli.;#{(no2B.BitToNum()+1)} in {msg2.ToString_SameHouseComp()}";
                        ResultLong = "W Wing\r" + msg0 + "\r" + msg1
                                     + $"\r Eliminated: #{(no2B.BitToNum()+1)} in {msg2.ToString_SameHouseComp()}";
                    }

                    if (__SimpleAnalizerB__)
                    {
                        return(true);
                    }
                    if (!pAnMan.SnapSaveGP(true))
                    {
                        return(true);
                    }
                    Wwing = false;
                }
            }
            return(false);
        }
Exemplo n.º 17
0
        //##### There is a bug #####
        public USuperLink Eval_SuperLinkChain(int rc0, int no0, bool Gbreak, int typeSel, bool DevelopB)
        {
            // rc0: start cell's rc index
            // no0: start digit
            // Gbreak(bool): T:If the evaluation values ​​are inconsistent, the search is suspended.
            // typeSel(int): Start link type1  1:Strong  2:Weak  3:S+W  0:-

            try{
                int dbX = 0;

                USuperLink USLK        = new USuperLink(rc0, no0);
                var        Qtrue       = USLK.Qtrue;
                var        Qfalse      = USLK.Qfalse;
                var        chainDesLKT = USLK.chainDesLKT;
                var        chainDesLKF = USLK.chainDesLKF;
                var        rcQue       = new Queue <GroupedLink>();

                UCell P0   = pBDL[rc0];                 //Origin Cell
                int   no0B = 1 << no0;                  //Origin Digit
                Qtrue[no0].BPSet(rc0);
                GroupedLink GLKnoR0 = new GroupedLink(P0, no0, no0, W, rootF: true);
                GLKnoR0.preGrpedLink  = null;
                chainDesLKT[rc0, no0] = GLKnoR0;

                #region stsrt
                if ((typeSel & 2) > 0)//====================== Start with WeakLink(origin:rc#no0) ======================
                {
                    foreach (var GLKH in IEGet_SuperLinkFirst(P0, no0).Where(X => X.type == W))
                    {
                        if (DevelopB)
                        {
                            WriteLine("*1st:" + GLKH.GrLKToString());
                        }
                        GLKH.UsedCs      |= GLKH.UGCellsB.B81;                                          //set usedcells(accumulate)
                        GLKH.preGrpedLink = GLKnoR0;                                                    //set pre-GLink
                        rcQue.Enqueue(GLKH);                                                            //enqueue next-GLink to RadiationSearchQueue

                        foreach (var P in GLKH.UGCellsB.Where(p => (p.FreeB & no0B) > 0))
                        {
                            int no2 = GLKH.no2;
                            Qfalse[no2].BPSet(P.rc);                                                            //set p.rc#no2 to false
                            chainDesLKF[P.rc, no2] = GLKH;                                                      //record in retroactive chain
                            if (Gbreak && Qtrue[no2].IsHit(P.rc) && GenMessage2(USLK, pBDL[P.rc], no2))
                            {
                                goto FTBreak;                                                                   //found error
                            }
                            if (P.FreeBC == 2)                                                                  //If the next is a binary cell
                            {
                                int nox = P.FreeB.DifSet(1 << no2).BitToNum();                                  //nox:another digit in the cell
                                Qtrue[nox].BPSet(P.rc);                                                         //P.rc#nox is true
                                GroupedLink GLKbv = new GroupedLink(P, no2, nox, S);                            //GLKbv:GLink in cell
                                GLKbv.preGrpedLink     = GLKH;                                                  //set preLink
                                chainDesLKT[P.rc, nox] = GLKbv;                                                 //record in retroactive chain
                                if (DevelopB)
                                {
                                    WriteLine($"        12 W *Rad->{P}  --#{no2} is false.");
                                }
                                if (Gbreak && Qfalse[nox].IsHit(P.rc) && GenMessage2(USLK, pBDL[P.rc], nox))
                                {
                                    goto FTBreak;                                                                                                         //found error
                                }
                            }
                        }
                    }

                    //S start cell, non-conscious digits
                    foreach (var nox in P0.FreeB.IEGet_BtoNo().Where(n => (n != no0)))              //non-conscious digits in originCell
                    {
                        Qfalse[nox].BPSet(rc0);                                                     // is false
                    }
                }

                if ((typeSel & 1) > 0)//====================== Start with StrongLink(origin:rc#no0) ======================
                {
                    foreach (var GLKH in IEGet_SuperLinkFirst(P0, no0).Where(X => X.type == S))
                    {
                        int         nox     = GLKH.no2;
                        GroupedLink GLKnoR1 = new GroupedLink(P0, no0, nox, W, rootF: false);           //nextGLink
                        GLKnoR1.preGrpedLink  = GLKnoR0;                                                //set pre-GLink to next-GLink
                        chainDesLKF[rc0, nox] = GLKnoR1;                                                //record in retroactive chain

                        GLKH.UsedCs      |= GLKH.UGCellsB.B81;                                          //set usedcells(accumulate)
                        GLKH.preGrpedLink = GLKnoR1;                                                    //set pre-GLink
                        rcQue.Enqueue(GLKH);                                                            //enqueue next-GLink to RadialSearchQueue
                        if (GLKH.UGCellsB.Count == 1)                                                   //if the link's next element is a single cell
                        {
                            int no2 = GLKH.no2;                                                         //no2:next digit
                            var P   = GLKH.UGCellsB[0];                                                 //P:next cell
                            Qtrue[no2].BPSet(P.rc);                                                     //set P.rc#no2 is true
                            chainDesLKT[P.rc, no2] = GLKH;                                              //record in retroactive chain
                            if (Gbreak && Qfalse[no2].IsHit(P.rc) && GenMessage2(USLK, pBDL[P.rc], no2))
                            {
                                goto FTBreak;                                                                 //found error
                            }
                            Qtrue[nox].BPSet(P.rc);                                                           //set P.rc#no is true

                            GroupedLink GLKno = new GroupedLink(P, nox, no2, W);                              //GLKno:GLink in cell
                            GLKno.preGrpedLink     = GLKH;                                                    //set preLink
                            chainDesLKF[P.rc, no2] = GLKno;                                                   //record in retroactive chain
                            if (Gbreak && Qtrue[nox].IsHit(P.rc) && GenMessage2(USLK, pBDL[P.rc], nox))
                            {
                                goto FTBreak;                                                                                                //found error
                            }
                        }
                    }
                }
                #endregion stsrt

                #region Radial Search
                //====================== Radial Search ===============================
                while (rcQue.Count > 0)
                {
                    GroupedLink R = rcQue.Dequeue();                                                                //dequeue next element
                    if (DevelopB)
                    {
                        WriteLine($"{dbX++}---Queue:" + R.GrLKToString());
                    }

                    foreach (var GLKH in IEGet_SuperLink(R))                                    //foreach next GLink
                    {
                        if (DevelopB)
                        {
                            WriteLine($"   {dbX++}--GLKH:" + GLKH.GrLKToString());
                        }
                        if (R.type != GLKH.type && R.UGCellsA.Equals(GLKH.UGCellsB))
                        {
                            continue;                                                                               //Skip back links
                        }
                        GLKH.preGrpedLink = R;                                                                      //set preLink
                        int no2 = GLKH.no2;                                                                         //no2:next digit
                        if (GLKH.type == S)                                                                         //Check connection conditions. case StrongLink
                        {
                            if (!(GLKH.UGCellsB.B81 & Qtrue[GLKH.no2]).IsZero())
                            {
                                continue;                                                                               //if the next element is setted true, go to the next process
                            }
                            if (GLKH.UGCellsB.Count == 1)                                                               //if the link's next element is a single cell
                            {
                                var P = GLKH.UGCellsB[0];                                                               //P:next cell
                                Qtrue[no2].BPSet(P.rc);                                                                 //set P.rc#no2 is true
                                chainDesLKT[P.rc, no2] = GLKH;                                                          //record in retroactive chain
                                if (Gbreak && Qfalse[no2].IsHit(P.rc) && GenMessage2(USLK, pBDL[P.rc], no2))
                                {
                                    goto FTBreak;                                                                                                         //found error
                                }
                                foreach (var nox in P.FreeB.IEGet_BtoNo().Where(q => (q != no2)))
                                {
                                    Qfalse[nox].BPSet(P.rc);                                                                      //set p.rc#no2 to false
                                    GroupedLink GLKno = new GroupedLink(P, no2, nox, W);                                          //GLKbv:GLink in cell(P#no2 WeakLink)
                                    GLKno.preGrpedLink     = GLKH;                                                                //set preLink
                                    chainDesLKF[P.rc, nox] = GLKno;                                                               //record in retroactive chain

                                    if (Gbreak && Qtrue[nox].IsHit(P.rc) && GenMessage2(USLK, pBDL[P.rc], nox))
                                    {
                                        goto FTBreak;                                                                                                            //found error
                                    }
                                    if (DevelopB)
                                    {
                                        WriteLine($"        31S ->P:{P}  --#{nox} is false.");
                                    }
                                }
                            }
                        }
                        if (GLKH.type == W)                                                                         //Check connection conditions. case WeakLink
                        {
                            if (!(GLKH.UGCellsB.B81 & Qfalse[GLKH.no2]).IsZero())
                            {
                                continue;                                                                               //if the next element is setted false, go to the next process
                            }
                            foreach (var P in GLKH.UGCellsB)                                                            //foreach next GLink
                            {
                                Qfalse[no2].BPSet(P.rc);                                                                //set P.rc#no2 is true
                                chainDesLKF[P.rc, no2] = GLKH;                                                          //record in retroactive chain
                                if (Gbreak && Qtrue[no2].IsHit(P.rc) && GenMessage2(USLK, pBDL[P.rc], no2))
                                {
                                    goto FTBreak;                                                                                                        //found error
                                }
                                if (DevelopB)
                                {
                                    WriteLine($"        40S ->P:{P}  ++#{no2} is false.");
                                }
                            }

                            if (GLKH.UGCellsB.Count == 1)                                                               //if the link's next element is a single cell
                            {
                                var P = GLKH.UGCellsB[0];
                                if (P.FreeBC == 2)                                                                            //If the next is a binary cell
                                {
                                    int nox = P.FreeB.DifSet(1 << no2).BitToNum();
                                    Qtrue[nox].BPSet(P.rc);                                                                                   //set P.rc#no2 is true
                                    if (DevelopB)
                                    {
                                        WriteLine($"        41S ->P:{P}  ++#{nox} is true.");
                                    }
                                    GroupedLink GLKno = new GroupedLink(P, no2, nox, S);                                          //GLKbv:GLink in cell(P#no2 StrongLink)
                                    GLKno.preGrpedLink     = GLKH;                                                                //set preLink
                                    chainDesLKT[P.rc, nox] = GLKno;                                                               //record in retroactive chain
                                    if (Gbreak && Qfalse[nox].IsHit(P.rc) && GenMessage2(USLK, pBDL[P.rc], nox))
                                    {
                                        goto FTBreak;                                                                                                             //found error
                                    }
                                }
                            }
                        }
                        GLKH.GenNo = R.GenNo + 1;
                        rcQue.Enqueue(GLKH);                                                                        //enqueue next-GLink to RadiationSearchQueue
                    }
                }
                #endregion Radial Search

                USLK.SolFound = true;                                                                       //Solution found
                return(USLK);

FTBreak:        //Failed
                USLK.SolFound = false;
                return(USLK);
            }
            catch (Exception ex) {
                WriteLine($"{ex.Message}+\r{ex.StackTrace}");
            }
            return(null);
        }
        public void SDK_TransProbG(string ctrl, bool DspSolB)
        {
            if (pGP.AnsNum == null)
            {
                Initialize();
            }

            int ixM = 0, ixR = TrPara[8], ixC = 1 - ixR, nx, m, n;

            switch (ctrl)
            {
            case "NumChange": break;

            case "Checked": break;

            case "random":  break;

            case "btnPatCVRg":
                ixM = TrPara[0] = (++TrPara[0]) % 6;
                for (int k = 0; k < 3; k++)
                {
                    RCX[ixR, k + 9] = prmX[ixM, k] * 3;
                }
                break;

            case "btnPatCVR123g":
                nx = RCX[ixR, 9]; ixM = TrPara[1] = (++TrPara[1]) % 6;
                for (int k = 0; k < 3; k++)
                {
                    RCX[ixR, k + nx] = prmX[ixM, k] + nx;
                }
                break;

            case "btnPatCVR456g":
                nx = RCX[ixR, 10]; ixM = TrPara[2] = (++TrPara[2]) % 6;
                for (int k = 0; k < 3; k++)
                {
                    RCX[ixR, k + nx] = prmX[ixM, k] + nx;
                }
                break;

            case "btnPatCVR789g":
                nx = RCX[ixR, 11]; ixM = TrPara[3] = (++TrPara[3]) % 6;
                for (int k = 0; k < 3; k++)
                {
                    RCX[ixR, k + nx] = prmX[ixM, k] + nx;
                }
                break;

            case "btnPatCVCg":
                ixM = TrPara[4] = (++TrPara[4]) % 6;
                for (int k = 0; k < 3; k++)
                {
                    RCX[ixC, k + 9] = prmX[ixM, k] * 3;
                }
                break;

            case "btnPatCVC123g":
                nx = RCX[ixC, 9]; ixM = TrPara[5] = (++TrPara[5]) % 6;
                for (int k = 0; k < 3; k++)
                {
                    RCX[ixC, k + nx] = prmX[ixM, k] + nx;
                }
                break;

            case "btnPatCVC456g":
                nx = RCX[ixC, 10]; ixM = TrPara[6] = (++TrPara[6]) % 6;
                for (int k = 0; k < 3; k++)
                {
                    RCX[ixC, k + nx] = prmX[ixM, k] + nx;
                }
                break;

            case "btnPatCVC789g":
                nx = RCX[ixC, 11]; ixM = TrPara[7] = (++TrPara[7]) % 6;
                for (int k = 0; k < 3; k++)
                {
                    RCX[ixC, k + nx] = prmX[ixM, k] + nx;
                }
                break;

#if false
            case "btnTransRtg":     //clockwise
                ixR = TrPara[8] = (++TrPara[8]) % 2;
                ixC = 1 - ixR;
                subTransLR(ixC);
                if (ixR == 0)
                {
                    subTransLR(ixC);
                }
                break;
#endif
            case "btnPatCVRCg":
            case "btnPatCVRCg2":
                ixR = TrPara[8] = (++TrPara[8]) % 2;
                ixC = 1 - ixR;
                if (ctrl == "btnTransRtg")
                {
                    goto case "btnTransLRg";                        //if clockwise,goto  horizontal flip
                }
                break;

            case "btnTransLRg":     //horizontal flip
                subTransLR(ixC);
                break;

            case "btnTransUDg":     //vertical flip
                subTransUD(ixR);
                break;

            //Symmetric transformation
            case "btnPatCVR123987g":     //row 123
                nx = RCX[ixR, 9]; m = TrPara[1]; ixM = TrPara[1] = (m + 1) % 6;
                for (int k = 0; k < 3; k++)
                {
                    RCX[ixR, k + nx] = prmX[ixM, k] + nx;
                }
                nx = RCX[ixR, 11]; n = TrPara[3]; ixM = TrPara[3] = trsX[m, n];
                for (int k = 0; k < 3; k++)
                {
                    RCX[ixR, k + nx] = prmX[ixM, k] + nx;
                }
                break;

            case "btnPatCVC123987g":     //Column 123
                nx = RCX[ixC, 9]; m = TrPara[5]; ixM = TrPara[5] = (m + 1) % 6;
                for (int k = 0; k < 3; k++)
                {
                    RCX[ixC, k + nx] = prmX[ixM, k] + nx;
                }
                nx = RCX[ixC, 11]; n = TrPara[7]; ixM = TrPara[7] = trsX[m, n];
                for (int k = 0; k < 3; k++)
                {
                    RCX[ixC, k + nx] = prmX[ixM, k] + nx;
                }
                break;

            case "btnPatCVR46g":     //row 46
                nx = RCX[ixR, 10]; ixM = TrPara[2] = (TrPara[2] + 3) % 6;
                for (int k = 0; k < 3; k++)
                {
                    RCX[ixR, k + nx] = prmX[ixM, k] + nx;
                }
                break;

            case "btnPatCVC46g":     //Column 46
                nx = RCX[ixC, 10]; ixM = TrPara[6] = (TrPara[6] + 3) % 6;
                for (int k = 0; k < 3; k++)
                {
                    RCX[ixC, k + nx] = prmX[ixM, k] + nx;
                }
                break;
            }

            for (int j = 0; j < 2; j++)
            {
                for (int k = 0; k < 9; k++)
                {
                    nx            = RCX[j, k / 3 + 9];
                    RCX[j + 2, k] = RCX[j, nx + k % 3];
                }
            }

            List <UCell> UCL = new List <UCell>();
            int[]        AnsN2 = new int[81];
            int          r, c, w;

            for (int rc = 0; rc < 81; rc++)
            {
                r = RCX[ixR + 2, rc / 9]; c = RCX[ixC + 2, rc % 9];
                if (ixR == 1)
                {
                    w = r; r = c; c = w;
                }
                int   rc2 = r * 9 + c;
                UCell P   = UPbas.BDL[rc2];
                UCL.Add(new UCell(rc, P.No, P.FreeB));
                AnsN2[rc] = UPbas.AnsNum[rc2];
            }
            UPuzzle UP = pGP.Copy(0, 0);
            UP.BDL = UCL; UP.AnsNum = AnsN2;
            if (ID >= 0)
            {
                pGNP.SDKProbLst[ID] = UP;
            }
            else
            {
                UP.ID = pGP.ID = 0;
                pGNP.SDKProbLst.Add(UP);
            }
            if (!DspSolB)
            {
                UP.BDL.ForEach(P => { P.No = Max(P.No, 0); });
            }
            pGNP.CurrentPrbNo = ID;

            SetIDCode(TrPara, AnsN2);

            /*
             *      string st="RCX:";
             *      for(int j=0; j<4; j++ ){
             *          for(int k=0; k<12; k++ ) st+=" "+RCX[j,k];
             *          st+=" / ";
             *      }
             *      for(int k=0; k<9; k++ ) st+=" "+TrPara[k];
             *      st+="//";
             *      int[] BPw=new int[3];
             *      for(int k=9; k<12; k++ ){BPw[k-9]=TrPara[k]; st+=" "+TrPara[k]; }
             *      WriteLine(st);
             *
             *      Bit81 BP=new Bit81(BPw);
             *      WriteLine(BP);
             */
        }
        private bool _ForceChainHouseDispEx(Bit81[] sPass, Bit81[] sTrue, int hs0, int no0)
        {
            string dspOpt = GNPXApp000.GMthdOption["ForceLx"];

            if (hs0 < 0)//  dspOpt:ForceL2"
            {
                Result = ResultLong = "ForceChain_House";
                if (__SimpleAnalizerB__)
                {
                    return(true);
                }
                pAnMan.SnapSaveGP(true);
                return(SolCode > 0);
            }


            string st0 = "", st2 = "";

            for (int nox = 0; nox < 9; nox++)
            {
                if (sTrue != null)
                {
                    if (sTrue[nox].IsZero())
                    {
                        continue;
                    }

                    foreach (var rc in sTrue[nox].IEGet_rc())
                    {
                        if (sPass[nox].IsHit(rc))
                        {
                            continue;
                        }
                        sPass[nox].BPSet(rc);

                        UCell Q = pBDL[rc];
                        Q.FixedNo = nox + 1;
                        int elm = Q.FreeB.DifSet(1 << nox);
                        Q.CancelB = elm;
                        SolCode   = 1;

                        if (SolInfoB)
                        {
                            Q.SetNoBBgColor(1 << nox, Colors.Red, Colors.LightGreen);
                            Q.SetNoBColorRev(elm, Colors.Red);

                            st0 = $"ForceChain_House({_HouseToString(hs0)}/#{(no0+1)}) r{(Q.r+1)}c{(Q.c+1)}/#{(nox+1)} is true";
                            string st1 = "";
                            foreach (var P in pBDL.IEGetCellInHouse(hs0, 1 << no0))
                            {
                                USuperLink USLK = pSprLKsMan.get_L2SprLK(P.rc, no0, FullSearchB: true, DevelopB: false);                        //Accurate path
                                st1 += "\r" + pSprLKsMan._GenMessage2true(USLK, Q, nox);
                                if (dspOpt != "ForceL2")
                                {
                                    P.SetNoBBgColor(1 << no0, Colors.Green, Colors.Yellow);
                                }
                            }

                            st2     = st0 + st1;
                            extRes += "\r" + st2;                             //(Description of each solution)
                            extRes  = extRes.TrimStart();

                            if (dspOpt == "ForceL0")
                            {
                                Result = ResultLong = st0;
                                if (__SimpleAnalizerB__)
                                {
                                    return(true);
                                }
                                if (!pAnMan.SnapSaveGP(false))
                                {
                                    return(true);
                                }
                                extRes = ""; st2 = "";
                                if (!SDK_Ctrl.MltAnsSearch)
                                {
                                    return(true);
                                }
                            }
                        }
                    }
                }

                if (SolInfoB && dspOpt == "ForceL1" && st2 != "")
                {
                    st0    = $"ForceChain_House({_HouseToString(hs0)}/#{(no0+1)})";
                    Result = ResultLong = st0;
                    if (__SimpleAnalizerB__)
                    {
                        return(true);
                    }
                    if (!pAnMan.SnapSaveGP(false))
                    {
                        return(true);
                    }
                    extRes = ""; st2 = "";
                    if (!SDK_Ctrl.MltAnsSearch)
                    {
                        return(true);
                    }
                }
            }
            return(SolCode > 0);
        }