public bool IsPureALS()
 {
     //Pure ALS : not include locked set of proper subset
     if (Size <= 2)
     {
         return(true);
     }
     for (int sz = 2; sz < Size - 1; sz++)
     {
         var cmb = new Combination(Size, sz);
         while (cmb.Successor())
         {
             int fb = 0;
             for (int k = 0; k < sz; k++)
             {
                 fb |= UCellLst[cmb.Index[k]].FreeB;
             }
             if (fb.BitCount() == sz)
             {
                 return(false);
             }
         }
     }
     return(true);
 }
Exemple #2
0
        //Link by ALS-ALS RCC
        public void QSearch_ALS2ALS_Link(bool doubly)
        {
            if (ALSLst == null)
            {
                PrepareALSLinkMan(1);
            }

            if (ALS2ALS_Link)
            {
                return;
            }
            ALS2ALS_Link = true;

            var cmb = new Combination(ALSLst.Count, 2);

            while (cmb.Successor())
            {
                UALS UA = ALSLst[cmb.Index[0]];
                UALS UB = ALSLst[cmb.Index[1]];

                int RCC = Get_AlsAlsRcc(UA, UB);
                if (RCC == 0)
                {
                    continue;
                }
                if (!doubly && RCC.BitCount() != 1)
                {
                    continue;
                }

                if (UA.ConnLst == null)
                {
                    UA.ConnLst = new List <UALSPair>();
                }
                if (UB.ConnLst == null)
                {
                    UB.ConnLst = new List <UALSPair>();
                }
                foreach (var no in RCC.IEGet_BtoNo())
                {
                    UALSPair LKX = new UALSPair(UA, UB, RCC, no);
                    if (!UA.ConnLst.Contains(LKX))
                    {
                        UA.ConnLst.Add(LKX);
                    }
                    LKX = new UALSPair(UB, UA, RCC, no);
                    if (!UB.ConnLst.Contains(LKX))
                    {
                        UB.ConnLst.Add(LKX);
                    }
                }
            }
        }
        //=================== MultiColoring ==================================
        public bool MultiColor_Type1( )
        {
            Prepare();
            CeLKMan.PrepareCellLink(1);                //Generate StrongLink

            for (int no = 0; no < 9; no++)
            {
                int            noB  = (1 << no);
                List <Bit81[]> MCRL = _Coloring(no).ToList();
                if (MCRL == null || MCRL.Count < 2)
                {
                    continue;
                }
                var cmb = new Combination(MCRL.Count, 2);
                while (cmb.Successor())
                {
                    Bit81[] CRLa = MCRL[cmb.Index[0]];
                    Bit81[] CRLb = MCRL[cmb.Index[1]];
                    for (int na = 0; na < 2; na++)
                    {
                        Bit81 HCRLa = new Bit81();
                        foreach (var rc in CRLa[na].IEGet_rc())
                        {
                            HCRLa |= ConnectedCells[rc];
                        }
                        for (int nb = 0; nb < 2; nb++)
                        {
                            if ((HCRLa & CRLb[nb]).IsZero())
                            {
                                continue;
                            }

                            Bit81 BD0    = new Bit81(pBDL, noB);
                            Bit81 ELMtry = BD0 - (CRLa[na] | CRLb[nb] | CRLa[1 - na] | CRLb[1 - nb]);
                            if (ELMtry.Count == 0)
                            {
                                continue;
                            }

                            bool  solF = false;
                            Bit81 ELM  = new Bit81();
                            foreach (var rc in ELMtry.IEGet_rc())
                            {
                                if (!ConnectedCells[rc].IsHit(CRLa[1 - na]))
                                {
                                    continue;
                                }
                                if (!ConnectedCells[rc].IsHit(CRLb[1 - nb]))
                                {
                                    continue;
                                }
                                pBDL[rc].CancelB = noB; ELM.BPSet(rc); solF = true;
                            }
                            if (solF)
                            {
                                Color CrA = _ColorsLst[0];
                                foreach (var P in ELM.IEGet_rc().Select(p => pBDL[p]))
                                {
                                    P.SetNoBBgColor(noB, AttCr, CrA);
                                }
                                for (int k = 0; k < 2; k++)
                                {
                                    Bit81[] CRLX = MCRL[cmb.Index[k]];
                                    Color   Cr1  = _ColorsLst[k];
                                    Color   Cr2  = Cr1; Cr2.A = (byte)120;
                                    foreach (var P in CRLX[1 - k].IEGet_rc().Select(p => pBDL[p]))
                                    {
                                        P.SetNoBBgColor(noB, AttCr, Cr1);
                                    }
                                    foreach (var P in CRLX[k].IEGet_rc().Select(p => pBDL[p]))
                                    {
                                        P.SetNoBBgColor(noB, AttCr, Cr2);
                                    }
                                }

                                SolCode = 2;
                                string SolMsg = "MultiColoring Type1 #" + (no + 1);
                                Result = SolMsg;
                                if (SolInfoB)
                                {
                                    ResultLong = SolMsg;
                                }
                                if (__SimpleAnalizerB__)
                                {
                                    return(true);
                                }
                                if (!pAnMan.SnapSaveGP(true))
                                {
                                    return(true);
                                }
                                solF = false;
                            }
                        }
                    }
                }
            }
            return(false);
        }
        //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);
        }
Exemple #5
0
        public int PrepareALSLinkMan(int nPls)    //QALS_Search
        {
            if (ALSLst != null)
            {
                return(ALSLst.Count());
            }
            int ALSSizeMax = GNPXApp000.ALSSizeMax;

            int mx = 0; //tentative ID, reset later

            ALSLst = new List <UALS>();
            List <int> singlyMan = new List <int>();

            for (int nn = 1; nn <= nPls; nn++)
            {
                for (int tf = 0; tf < 27; tf++)
                {
                    List <UCell> Pcells = pBDL.IEGetCellInHouse(tf, 0x1FF).ToList();
                    if (Pcells.Count < 1)
                    {
                        continue;
                    }
                    int szMax = Min(Pcells.Count, 8 - nn);
                    szMax = Min(szMax, ALSSizeMax);  //ALS size maximum value
                    for (int sz = 1; sz <= szMax; sz++)
                    {
                        Combination cmb = new Combination(Pcells.Count, sz);
                        while (cmb.Successor())
                        {
                            int FreeB = 0;
                            Array.ForEach(cmb.Index, q => FreeB |= Pcells[q].FreeB);
                            if (FreeB.BitCount() != (sz + nn))
                            {
                                continue;
                            }
                            List <UCell> Q = new List <UCell>();
                            Array.ForEach(cmb.Index, q => Q.Add(Pcells[q]));

                            //Check for existence of ALS with the same configuration
                            UALS UA = new UALS(mx++, sz, tf, FreeB, Q);
                            if (!UA.IsPureALS())
                            {
                                continue;
                            }
                            int hs = UA.GetHashCode();
                            if (singlyMan.Any(p => p == hs))
                            {
                                UA.singly = false;
                            }
                            else
                            {
                                singlyMan.Add(hs);
                            }

                            ALSLst.Add(UA);
                        }
                    }
                }
            }

            ALSLst.Sort();
            int ID = 0;

            ALSLst.ForEach(P => P.ID = ID++);
            // ALSLst.ForEach(P=>WriteLine(P));
            return(ALSLst.Count());
        }
        public IEnumerable <UBasCov2> IEGet_BaseSet(int sz, int rnk)        //### BaseSet generator
        {
            if (GLK_UList_All.Count < sz * 2 + rnk)
            {
                yield break;
            }

            BSstatus2 = new BaseSet_Status2(sz, rnk);

            //Marking method
            // #1:Focus on the link(LK0) and follow the connecting links. A link of size(sz) is a candidate for BaseSet/CoverSet.
            //    (This alone won't make it faster.)
            // #2:Select BaseSet from the candidates and check suitability.
            //    Excludes generation G1 links.
            // #3:Also select the CoverSet from the candidates. At least common elements with baseset are required.
            //    Light selection and aptitude testing.
            //    Efficient evaluation of aptitude of baseSet is important.
            // #4:If there is no solution for the candidate starting from LK0, record LK0 in the invalid list.
            // #2':Select BaseSet from the candidates, exclude links in the invalid list.

            Bit324 invalidLink = new Bit324();

            foreach (var LK0 in GLK_UList_All)      //#1 LK0:First link
            {
                _chkX1 = false; _chkX2 = false;

                //    if( SDK_Ctrl.UGPMan.stageNo>=12 && sz>=3 ){//&& rnk==1){
                //        _chkX1=false; _chkX2=true;
                //        if(LK0.ToAppearance()=="r4#2"){
                //            WriteLine($"--->{LK0.ToAppearance()}");
                //            _chkX1=false; _chkX2=true;
                //        }
                //    }
                if (_chkX1)
                {
                    WriteLine($"\r-1- baseset sz:{sz} rnk:{rnk}  first:{LK0} -");
                }

                GLK_UList_Marked.Clear();
                QueueGlk.Clear();
                rcnGenNo         = new int[9, 81];      //### gen ###
                BasCovCandidates = new Bit324();

                #region ----- marking for LK0 -------------------------
                BasCovCandidates.BPSet(LK0.IDsq);             //1)BC_Set 候補のリスト  ## 初のリンク(LK0)の登録
                LK0._gen = 1;
                foreach (var NDx in LK0.ConnectLinks)         //LK0の他端ノードNDx に着目
                {
                    var(rc, no)      = (NDx >> 4, NDx & 0xF); // (rc,no) <-- NDx
                    rcnGenNo[no, rc] = 1;                     //### gen ###      //NDXの世代<-1    set rcnGenNo
                    QueueGlk.Enqueue(NDx);                    //Enqueue(ND1)
                    if (_chkX1)
                    {
                        WriteLine($"@{_jkc_++}      -1.5- Enqueue {rc.ToRCString()}#{no+1}");
                    }
                }

                //==== sz>=2 ====
                while (QueueGlk.Count > 0)
                {
                    var ND2 = QueueGlk.Dequeue();
                    var(rc, no) = (ND2 >> 4, ND2 & 0xF);
                    int gen = rcnGenNo[no, rc];            //### gen ###
                    if (_chkX1)
                    {
                        WriteLine($"@{_jkc_++}  -2- Dequeue {rc.ToRCString()}#{no+1}-G{gen}");
                    }

                    if (gen > sz)
                    {
                        continue;
                    }
                    foreach (var LKpair in GLK_connection[rc, no])
                    {
                        var(no2, rc2) = (LKpair.no2, LKpair.rc2);
                        var         gen2 = rcnGenNo[no2, rc2]; //### gen ###
                        UGLink_unit LKx  = LKpair.objUGL;
                        LKx._gen = gen;
                        bool hit = BasCovCandidates.IsHit(LKx.IDsq);
                        BasCovCandidates.BPSet(LKx.IDsq);   //1)BC_Set 候補のリスト ビット表現で重複を回避
                        if (_chkX1)
                        {
                            string st3 = $"@{_jkc_++}      -2.5- Link set {LKx} {(hit? "---": "New")}";
                            WriteLine(st3);
                        }

                        if (gen2 == 0)
                        {
                            rcnGenNo[no2, rc2] = gen + 1;  //### gen ###
                            if (gen < sz)
                            {
                                QueueGlk.Enqueue(LKpair.rcno);
                                if (_chkX1)
                                {
                                    string st3 = $"@{_jkc_++}         -3- Enqueue {rc2.ToRCString()}#{no2+1}-G{gen+1}";
                                    st3 += "   " + LKx.ToString();
                                    WriteLine(st3);
                                }
                            }
                        }
                    }
                }

                GLK_UList_Marked.Add(LK0);                  //First is LK0.
                BasCovCandidates.BPReset(LK0.IDsq);         //reset LK0.
                foreach (var LX in BasCovCandidates.IEGet_Index().Select(kx => GLK_UList_All[kx]))
                {
                    GLK_UList_Marked.Add(LX);
                }
                if (_chkX2)
                {
                    string stBC = $"\r@{_jkc_++} BasCovCandidates({GLK_UList_Marked.Count}) :";
                    GLK_UList_Marked.ForEach(LK => stBC += $" {LK.ToAppearance(Gen:true)}");       //#### debug print
                    WriteLine(stBC);
                }
                if (GLK_UList_Marked.Count < sz)
                {
                    continue;
                }
                #endregion ----- marking -------------------------

                #region ----- selecte -------------------------
                var         GLK_UList_Sel = new List <UGLink_unit>();
                Combination cmbBas = new Combination(GLK_UList_Marked.Count, sz);
                string      st, stw = "";
                int         nxt = int.MaxValue;             //(skip function)
                string      stT = "";
                while (cmbBas.Successor(nxt))
                {
                    nxt = int.MaxValue;
                    if (cmbBas.Index[0] != 0)
                    {
                        continue;                    //"The first link is fixed at 0!"
                    }
                    GeneralLogicGen2.ChkBas0++;      //*****

                    var   usedLKIDsq  = new Bit324();
                    var   BaseSetLst  = new List <UGLink_unit>();
                    var   HB981       = new Bit981(); //BaseSet bitPattern
                    long  RCBN_frameA = 0;
                    int[] RCB_frameB9 = new int[9];
                    foreach (var(kx, elementX) in cmbBas.IEGetIndex2())
                    {
                        nxt = kx;
                        var UGL = GLK_UList_Marked[elementX];
                        if (kx >= 1 && UGL._gen == 1)
                        {
                            goto LnxtCombination;                                   // (#2) excludes generation G1 links.
                        }
                        if (invalidLink.IsHit(UGL.IDsq))
                        {
                            goto LnxtCombination;                                   // (#2')exclude links in the invalid list.
                        }
                        usedLKIDsq.BPSet(UGL.IDsq);
                        BaseSetLst.Add(UGL);
                        foreach (var P in UGL.ConnectLinks)
                        {
                            int no2 = P & 0xF, rc2 = P >> 4;
                            if (HB981.IsHit(no2, rc2))
                            {
                                goto LnxtCombination;                               // BaseSet links do not overlap.
                            }
                            HB981.BPSet(no2, rc2);
                        }
                        long RCBN_frameB = UGL.RCBN_frameB; //bit expression of [ UC.FreeB<<27 | 1<<(UC.b+18)) | 1<<(UC.c+9) | (1<<UC.r) ]
                        int  freebX      = (int)(RCBN_frameB >> 27);
                        foreach (var no in freebX.IEGet_BtoNo())
                        {
                            RCB_frameB9[no] |= (int)(RCBN_frameB & 0x7FFFFFF);
                        }
                        RCBN_frameA |= UGL.RCBN_frameB;    //bit expression of rcb
                        if (kx > 0)
                        {
                            if (!Check_rcbnCondition(sz, rnk, elementX, RCBN_frameA))
                            {
                                goto LnxtCombination;                                                     //(### extremely efficient) ????
                            }
                        }
                    }
                    if (!Check_rcbnCondition(sz, rnk, 0, RCBN_frameA))
                    {
                        goto LnxtCombination;                                              //Evaluate BaseSet pattern. Extremely efficient.
                    }
                    if (sz >= 2)
                    {
                        BSstatus2.Prepare(usedLKIDsq, BaseSetLst, HB981, RCB_frameB9);

                        //check 421 52.1sec
                        //check 124 53.6sec

                        if (!BSstatus2.Check_4())
                        {
                            goto LnxtCombination;                           //Each element of LK0 is associated with the rest of the links.
                        }
                        if (!BSstatus2.Check_2())
                        {
                            goto LnxtCombination;                           //Each cell(A) is in a position to link with other cells.
                        }
                        if (!BSstatus2.Check_1())
                        {
                            goto LnxtCombination;                           //A and B are not linked by other link(C).
                        }
                        //  if( !BSstatus2.Check_3() ) goto LnxtCombination;  //There is a limit to the number of cells that have no links other than BaseSet.
                        //      Check_1 and _3 are almost the same evaluation. Check_3 is a heavy process.

                        //  if( !BSstatus2.Check_5() ) goto LnxtCombination;  //XXX Almost no effect. Check_1-4 has been determined.
                    }
                    var BasCov = new UBasCov2(usedLKIDsq, BaseSetLst, HB981, sz);
                    if (_chkX2)
                    {
                        string st2 = $"\r{_jkc_++} BaseSet:";
                        BaseSetLst.ForEach(P => st2 += " " + P.ToAppearance());
                        //     WriteLine(st2);
                        WriteLine($"Check_5---->{st2}");            //###################
                    }
                    yield return(BasCov);

LnxtCombination:
                    continue;
                }

                //*==*==*==*==*==*==*==*==*==*==*==*==*==*==*==*
                invalidLink.BPSet(LK0.IDsq); //#4:If there is no solution for the candidate starting from LK0, record LK0 in the invalid list.
                //*==*==*==*==*==*==*==*==*==*==*==*==*==*==*==*

                #endregion ----- selecte -------------------------
            }
            yield break;
        }
        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)));
                        }
                    }
                }
            }
        }
        //1..4....8.9.1...5.....63.....13.5.79..3...8..76.2.94.....75.....1...6.4.8....4..2

        public IEnumerable <UBasCov2> IEGet_CoverSet(UBasCov2 BasCov, int rnk)           //### CoverSet generator
        {
            if (GLK_UList_All == null)
            {
                yield break;
            }
            int sz = BasCov.sz;

            if (GLK_UList_Marked.Count < sz)
            {
                yield break;
            }

            var BaseSetLst = BasCov.BaseSetLst;
            var usedLKIDsq = BasCov.usedLKIDsq;              //used links
            var HB981      = BasCov.HB981;                   //BaseSet bit expression
            int noBit      = HB981.noBit;                    //bit expression of digits containing cell elements

            var UGLCovCandidates = new List <UGLink_unit>(); // UGLCovCandidates:candidate link

            #region Preparation(Create UGLCovCandidates)
            //Preparation: select candidates for CoverSet.(this process is extremely effective!)
            // 1)First select BaseSet, then select CoverSet to cover.
            // 2)CoverSet requirements:
            //  .Exclude links that do not contain BaseSet elements
            //  .Rank=0 includes two or more elements of BaseSet
            //  .Rank>0 contains one or more elements of BaseSet

            Bit81 Bcmp = HB981.CompressToHitCells();
//x            long  RCBN_frameBex = BaseSetLst.Aggregate((long)0,(p,q)=>p|q.RCBN_frameBex);

            foreach (var P in GLK_UList_Marked)    //Exclude Baseset links
//x                if((RCBN_frameBex&P.RCBN_frameB) == 0) continue;
            {
                if (BaseSetLst.Contains(P))
                {
                    continue;
                }
                if (P.type == 0)          // 0:link
                {
                    if ((noBit & (1 << P.no)) == 0)
                    {
                        continue;                                           //Exclude links with digits not included in BaseSet.
                    }
                    int Bcount = (HB981._BQ[P.no] & P.rcBit81).BitCount();  //Bcount : Number of cells in common with BaseSet.
                    if (Bcount == 0)
                    {
                        continue;                                           //Link without common parts is excluded from candidate links.
                    }
                    if (rnk == 0 && Bcount < 2)
                    {
                        continue;                                           //if rank=0, the CoverSet has two or more common items
                    }
                    UGLCovCandidates.Add(P);
                }

                else                   // 1:cell
                {
                    if (noBit.BitCount() <= 1)
                    {
                        continue;                                           //For links within a cell, the Coverset digits must be 2 or more.
                    }
                    if ((noBit & P.FreeB) == 0)
                    {
                        continue;                                           //Exclude links with digits not included in BaseSet.
                    }
                    int B = noBit & P.FreeB;                                //Common digits of BaseSet and link
                    if (B == 0)
                    {
                        continue;                                           //Link without common parts are excluded from candidate links.
                    }
                    int rc = P.rc;                                          //focused cell

                    int kcc = 0, kccLim = (rnk == 0)? 2:1;
                    foreach (var no in B.IEGet_BtoNo())                     //no:Candidate digit of forcused cell.
                    {
                        if (!HB981._BQ[no].IsHit(rc))
                        {
                            continue;                                       //do not check if BaseSet does not include no.
                        }
                        if (++kcc >= kccLim)
                        {
                            UGLCovCandidates.Add(P); break;
                        }                                                   //number of digits contained in BaseSet satisfies the condition(kccLim).
                    }
                }
            }
            if (_chkX2)
            {
                string st2 = $"{_jkc_++} UGLCovCandidates for CoverSet:";
                st2 = UGLCovCandidates.Aggregate(st2, (p, q) => p + " " + q.ToAppearance());//#### debug print

                WriteLine(st2);
            }
            #endregion Preparation(Create UGLCovCandidates)

            #region CoverSet generator
            if (UGLCovCandidates.Count < sz + rnk)
            {
                yield break;
            }
            Bit981 HC981  = new Bit981();         //CoverSet
            Bit981 Can981 = new Bit981();         //Items that break "Locked"(excludable candidates)

            Combination cmbCvr = new Combination(UGLCovCandidates.Count, sz + rnk);
            int         nxt    = int.MaxValue;
            while (cmbCvr.Successor(nxt))                                               //Combination one-element generator
            {
                ++GeneralLogicGen2.ChkCov1;
                HC981.Clear();
                Array.ForEach(cmbCvr.Index, m => HC981 |= UGLCovCandidates[m].rcnBit);  //CoverSet bit expression

                if (!(HB981 - HC981).IsZero())
                {
                    goto LNextSet;                                                      //BaseSet is covered?
                }
                Bit981 CsubB = HC981 - HB981;                                           //CsubB:excludable candidates
                if (CsubB.IsZero())
                {
                    goto LNextSet;                                                      // is exist?
                }
                var CoverSetLst = new List <UGLink_unit>();
                Array.ForEach(cmbCvr.Index, m => CoverSetLst.Add(UGLCovCandidates[m])); //CoverSet List

                if (rnk == 0)
                {
                    Can981 = CsubB;
                }       //(excludable candidates)
                else    //if(rnk>0){

                //  rank=k
                //    Consider the case of covering n-BaseSet with (n+k)-CoverSet.
                //    In order to be an analysis algorithm, the following conditions must be satisfied.
                //        1:(n+k)-CoverSet completely covers n-BaseSet.
                //        2:(k+1) of the (n+k) links of CoverSet have elements in common which are not included in the n-BaseSet.
                //    When these conditions are satisfied, the elements of the intersection of condition 2 are not true.
                {
                    bool SolFound = false;
                    Can981.Clear();
                    foreach (int n in CsubB.noBit.IEGet_BtoNo())
                    {
                        foreach (int rc in CsubB._BQ[n].IEGetRC())
                        {
                            int kc = CoverSetLst.Count(Q => Q.rcnBit.IsHit(n, rc));
                            if (kc == rnk + 1)
                            {
                                Can981.BPSet(n, rc);
                                SolFound = true;
                            }
                        }
                    }

                    if (!SolFound)
                    {
                        continue;
                    }
                }
                ++GeneralLogicGen2.ChkCov2;                       //*****

                BasCov.addCoverSet(CoverSetLst, HC981, Can981, rnk);
                if (_chkX2)
                {
                    string st = $"{_jkc_++}      ◆CoverSet:";
                    foreach (var P in CoverSetLst)
                    {
                        st += $" {P.ToAppearance()}";                                     //#### debug print
                    }
                    WriteLine(st);
                }
                yield return(BasCov);

LNextSet:
                continue;
            }
            yield break;
            #endregion CoverSet generator
        }
        public IEnumerable <UFish> IEGet_BaseSet(int BaseSel, bool FinnedF = false, bool EndoFlg = false)
        {
            if (HBLst == null)
            {
                yield break;
            }

            bool basicFish = (BaseSel.BitCount() <= 9) & !FinnedF;  //not F/M & notF/M
            int  BaseSelR  = 0x3FFFF ^ BaseSel;

            GeneralLogicGen.ChkBas1 = 0;
            GeneralLogicGen.ChkBas2 = 0;
            Bit81       Q;
            Combination cmbBas = new Combination(HBLst.Count, sz);
            int         nxt    = int.MaxValue;

            while (cmbBas.Successor(nxt))
            {
                int   chk1   = ++GeneralLogicGen.ChkBas1;
                int   usedLK = 0;
                Bit81 HB81   = new Bit81();
                Bit81 OHB81  = new Bit81();
                int   rcbB   = 0;
                for (int k = 0; k < sz; k++)
                {
                    nxt = k;
                    int    nx  = cmbBas.Index[k];
                    Bit81F HBF = HBLst[nx];
                    if (((1 << HBF.ID) & BaseSel) == 0)
                    {
                        goto nxtCmb;
                    }
                    if (!(Q = HB81 & HBF).IsZero())        //overlap
                    {
                        if (!EndoFlg)
                        {
                            goto nxtCmb;
                        }
                        OHB81 |= Q;
                    }
                    usedLK |= 1 << HBF.ID;              //house Number
                    HB81   |= HBF;                      //Bit81
                    rcbB   |= HBF.rcbB;
                    if (basicFish && k > 0 && (rcbB & BaseSelR).BitCount() > sz)
                    {
                        goto nxtCmb;
                    }
                }
                if (extFlag && !IsLinked9(HB81))
                {
                    continue;
                }
                int chk2 = ++GeneralLogicGen.ChkBas2;

                UFish UF = new UFish(no, sz, usedLK, HB81, OHB81);
                //if(sz>=3 && BaseSel==0x7FFFFFF) Debug_PattenPrint(UF);
                yield return(UF);

nxtCmb:
                continue;
            }
            yield break;
        }
        public IEnumerable <UFish> IEGet_CoverSet(UFish BSet, int CoverSel, bool Finned, bool CannFlg = false)
        {
            if (HBLst == null)
            {
                yield break;
            }

            List <Bit81> HCLst = new List <Bit81>();

            foreach (var P in HBLst.Where(q => (BSet.HouseB & (1 << q.ID)) == 0))
            {
                if (((1 << P.ID) & CoverSel) == 0)
                {
                    continue;
                }
                if (BSet.BaseB81.IsHit(P))
                {
                    HCLst.Add(P);
                }
            }
            if (HCLst.Count < sz)
            {
                yield break;
            }

            Bit81       Q;
            Combination cmbCov = new Combination(HCLst.Count, sz);
            int         nxt    = int.MaxValue;

            while (cmbCov.Successor(nxt))
            {
                int chk1 = ++GeneralLogicGen.ChkCov1;

                int   usedLK = 0;
                Bit81 HC81   = new Bit81();
                Bit81 OHC81  = new Bit81();
                for (int k = 0; k < sz; k++)
                {
                    nxt = k;
                    int nx = cmbCov.Index[k];
                    if (!(Q = HC81 & HCLst[nx]).IsZero()) //overlap
                    {
                        if (!CannFlg)
                        {
                            goto nxtCmb;
                        }
                        OHC81 |= Q;
                    }
                    usedLK |= 1 << HCLst[nx].ID; //house Number
                    HC81   |= HCLst[nx];         //Bit81
                }

                Bit81 FinB81 = BSet.BaseB81 - HC81;
                if (Finned != (FinB81.Count > 0))
                {
                    continue;
                }
                UFish UF = new UFish(BSet, usedLK, HC81, FinB81, OHC81);
                //if(sz>=3 && CoverSel==0x7FFFFFF)  WriteLine("  CoverSet: " + UF.HouseC.HouseToString() ); //**********
                yield return(UF);

nxtCmb:
                continue;
            }
            yield break;
        }
        }                                                                         //complementary to 2D

        public bool LockedSetSub(int sz, bool HiddenFlag = false)
        {
            string resST = "";
            UCell  UC;

            for (int tfx = 0; tfx < 27; tfx++)
            {
                List <UCell> BDLstF = pBDL.IEGetCellInHouse(tfx, 0x1FF).ToList();    //selecte cells in house
                int          ncF    = BDLstF.Count;
                if (ncF <= sz)
                {
                    continue;
                }

                Combination cmbG = new Combination(ncF, sz);
                while (cmbG.Successor())
                {
                    BDLstF.ForEach(p => p.Selected = false);                                                    //(Initialization of cells in the house. The target is several.)
                    int selBlk = 0;
                    Array.ForEach(cmbG.Index, p => { (UC = BDLstF[p]).Selected = true; selBlk |= 1 << UC.b; }); //selecte cells by Combination

                    int noBSel = 0, noBNon = 0;
                    BDLstF.ForEach(p => {
                        if (p.Selected)
                        {
                            noBSel |= p.FreeB;
                        }
                        else
                        {
                            noBNon |= p.FreeB;
                        }
                    });
                    if ((noBSel & noBNon) == 0)
                    {
                        continue;                                                   //any digits that can be excluded?
                    }
                    //=============== Naked Locked Set ===============
                    if (!HiddenFlag)
                    {
                        if (noBSel.BitCount() == sz)                                   //Number of selected cell's dijits is sz
                        {
                            if (tfx < 18 && selBlk.BitCount() == 1)
                            {
                                // in searching row or column, there are elements that can be excluded in block.
                                int          tfx2 = selBlk.BitToNum() + 18;         //bit expression -> House_No(18-26)
                                List <UCell> PLst = pBDL.IEGetCellInHouse(tfx2, noBSel).ToList();
                                BDLstF.ForEach(P => { if (P.Selected)
                                                      {
                                                          PLst.Remove(P);
                                                      }
                                               });
                                if (PLst.Count > 0)
                                {
                                    PLst.ForEach(P => { P.CancelB = P.FreeB & noBSel; });
                                }
                            }

                            resST = "";
                            foreach (var P in BDLstF)
                            {
                                if (P.Selected)
                                {
                                    P.SetNoBBgColor(noBSel, AttCr, SolBkCr);
                                    resST += " " + P.rc.ToRCString();
                                }
                                else
                                {
                                    P.CancelB = P.FreeB & noBSel;
                                }
                            }
                            resST = resST.ToString_SameHouseComp() + " #" + noBSel.ToBitStringN(9);
                            _LockedSetResult(sz, resST, HiddenFlag);
                            if (__SimpleAnalizerB__)
                            {
                                return(true);
                            }
                            if (!pAnMan.SnapSaveGP())
                            {
                                return(true);
                            }
                        }
                    }

                    //=============== Hidden Locked Set ===============
                    if (HiddenFlag)
                    {
                        if (noBNon.BitCount() == (ncF - sz))                             //Number of unselected cell's dijits is (ncF-sz)
                        {
                            resST = "";
                            foreach (var P in BDLstF.Where(p => p.Selected))
                            {
                                P.CancelB = P.FreeB & noBNon;
                                P.SetNoBBgColor(noBSel, AttCr, SolBkCr);
                                resST += " " + P.rc.ToRCString();
                            }
                            int nobR = noBSel.DifSet(noBNon);
                            resST = resST.ToString_SameHouseComp() + " #" + nobR.ToBitStringN(9);
                            _LockedSetResult(sz, resST, HiddenFlag);
                            if (__SimpleAnalizerB__)
                            {
                                return(true);
                            }
                            if (!pAnMan.SnapSaveGP())
                            {
                                return(true);
                            }
                        }
                    }
                }
            }
            return(false);
        }
        private bool _ALSXYWingSub(int szT)
        {
            //(ALS sorted by size)
            foreach (var UC in ALSMan.ALSLst.Where(p => p.Size <= szT - 2))
            {
                if (!UC.singly)
                {
                    continue;
                }
                int szS = szT - UC.Size;

                UALS UA, UB, UApre = null;
                int  nxt = 0, RccAC = -1, RccBC = -1;
                var  cmb = new Combination(ALSMan.ALSLst.Count, 2);
                while (cmb.Successor(nxt))
                {
                    nxt = 0;
                    UA  = ALSMan.ALSLst[cmb.Index[0]];
                    if (!UA.singly || UA == UC || UA.Size > szS - 1)
                    {
                        continue;
                    }
                    if (UA != UApre)
                    {
                        RccAC = ALSMan.Get_AlsAlsRcc(UA, UC);    //RCC
                        if (RccAC.BitCount() != 1)
                        {
                            continue;
                        }
                        UApre = UA;
                    }

                    UB = ALSMan.ALSLst[cmb.Index[1]];
                    if (!UB.singly || UB.Size > (szS - UA.Size))
                    {
                        continue;                                      //Skip using "Sort by size"
                    }
                    nxt = 1;
                    if (UB == UC || UB.Size != (szS - UA.Size))
                    {
                        continue;
                    }
                    if (!(UA.B81 & UB.B81).IsZero())
                    {
                        continue;                               //Overlap
                    }
                    RccBC = ALSMan.Get_AlsAlsRcc(UB, UC);       //RCC
                    if (RccBC.BitCount() != 1)
                    {
                        continue;
                    }
                    if (RccAC == RccBC)
                    {
                        continue;
                    }

                    int EFrB = (UA.FreeB & UB.FreeB).DifSet(RccAC | RccBC);
                    if (EFrB == 0)
                    {
                        continue;
                    }
                    foreach (var no in EFrB.IEGet_BtoNo())
                    {
                        int   noB = (1 << no);
                        Bit81 UE  = new Bit81();
                        foreach (var P in UA.UCellLst.Where(p => (p.FreeB & noB) > 0))
                        {
                            UE.BPSet(P.rc);
                        }
                        foreach (var P in UB.UCellLst.Where(p => (p.FreeB & noB) > 0))
                        {
                            UE.BPSet(P.rc);
                        }

                        Bit81 TBD = (new Bit81(pBDL, noB)) - (UA.B81 | UB.B81 | UC.B81);
                        foreach (var rc in TBD.IEGet_rc())
                        {
                            if (!(UE - ConnectedCells[rc]).IsZero())
                            {
                                continue;
                            }
                            pBDL[rc].CancelB = noB; SolCode = 2;
                        }

                        if (SolCode > 0) //===== ALS XY-Wing found =====
                        {
                            ALSXYWing_SolResult(UA, UB, UC, RccAC, RccBC);
                            if (__SimpleAnalizerB__)
                            {
                                return(true);
                            }
                            if (!pAnMan.SnapSaveGP(true))
                            {
                                return(true);
                            }
                        }
                    }
                }
            }
            return(false);
        }
Exemple #13
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)
            }
        }
Exemple #14
0
        private bool _ALS_DeathBlossomSubEx(int sz, bool stmLinked = false)
        {
            int szM = (stmLinked? sz - 1: sz);

            foreach (var SC in pBDL.Where(p => p.FreeBC == sz))                    //Stem Cell
            {
                if (pAnMan.CheckTimeOut())
                {
                    return(false);
                }
                List <LinkCellALS> LinkCeAlsLst = ALSMan.LinkCeAlsLst[SC.rc];
                if (LinkCeAlsLst == null || LinkCeAlsLst.Count < sz)
                {
                    continue;
                }

                int nxt = 0, PFreeB = SC.FreeB;
                var cmb = new Combination(LinkCeAlsLst.Count, szM);                //Select szM ALSs in Combination
                while (cmb.Successor(nxt))
                {
                    int FreeB = SC.FreeB, AFreeB = 0x1FF;
                    for (int k = 0; k < szM; k++)
                    {
                        nxt = k;
                        var LK = LinkCeAlsLst[cmb.Index[k]];                      //Link[cell-ALS]
                        if ((FreeB & (1 << LK.nRCC)) == 0)
                        {
                            goto LNxtCmb;
                        }
                        FreeB   = FreeB.BitReset(LK.nRCC);                      //nRCC:RCC of stemCell-ALS
                        AFreeB &= LK.ALS.FreeB;
                        if (AFreeB == 0)
                        {
                            goto LNxtCmb;
                        }
                    }

                    if (stmLinked)
                    {
                        if (FreeB.BitCount() != 1 || (FreeB & AFreeB) == 0)
                        {
                            continue;
                        }
                        int no  = FreeB.BitToNum();
                        int noB = FreeB;

                        Bit81 Ez = new Bit81();
                        for (int k = 0; k < szM; k++)
                        {
                            var ALS   = LinkCeAlsLst[cmb.Index[k]].ALS;
                            var UClst = ALS.UCellLst;
                            foreach (var P in UClst.Where(p => (p.FreeB & noB) > 0))
                            {
                                Ez.BPSet(P.rc);
                            }
                        }

                        foreach (var P in ConnectedCells[SC.rc].IEGet_rc().Select(rc => pBDL[rc]))
                        {
                            if ((P.FreeB & noB) == 0)
                            {
                                continue;
                            }
                            if ((Ez - ConnectedCells[P.rc]).IsZero())
                            {
                                P.CancelB = noB; SolCode = 2;
                            }
                        }
                        if (SolCode < 1)
                        {
                            continue;
                        }

                        var LKCAsol = new List <LinkCellALS>();
                        Array.ForEach(cmb.Index, nx => LKCAsol.Add(LinkCeAlsLst[nx]));
                        _DeathBlossom_SolResult(LKCAsol, SC, no, stmLinked);

                        if (__SimpleAnalizerB__)
                        {
                            return(true);
                        }
                        if (!pAnMan.SnapSaveGP(true))
                        {
                            return(true);
                        }
                    }
                    else if (FreeB == 0 && AFreeB > 0)
                    {
                        AFreeB = AFreeB.DifSet(SC.FreeB);
                        foreach (var no in AFreeB.IEGet_BtoNo())
                        {
                            int   noB = (1 << no);
                            Bit81 Ez  = new Bit81();
                            for (int k = 0; k < sz; k++)
                            {
                                var ALS   = LinkCeAlsLst[cmb.Index[k]].ALS;
                                var UClst = ALS.UCellLst;
                                foreach (var P in UClst.Where(p => (p.FreeB & noB) > 0))
                                {
                                    Ez.BPSet(P.rc);
                                }
                            }

                            foreach (var P in pBDL.Where(p => (p.FreeB & noB) > 0))
                            {
                                if ((Ez - ConnectedCells[P.rc]).IsZero())
                                {
                                    P.CancelB = noB; SolCode = 2;
                                }
                            }
                            if (SolCode < 1)
                            {
                                continue;
                            }

                            var LKCAsol = new List <LinkCellALS>();
                            Array.ForEach(cmb.Index, nx => LKCAsol.Add(LinkCeAlsLst[nx]));
                            _DeathBlossom_SolResult(LKCAsol, SC, no, stmLinked);

                            if (__SimpleAnalizerB__)
                            {
                                return(true);
                            }
                            if (!pAnMan.SnapSaveGP(true))
                            {
                                return(true);
                            }
                        }
                    }

LNxtCmb:
                    continue;
                }
            }
            return(false);
        }
        //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);
        }
Exemple #16
0
        private bool _ALSXZsub(int sz)
        {
            if (ALSMan.ALSLst.Count < 2)
            {
                return(false);
            }

            var cmb = new Combination(ALSMan.ALSLst.Count, 2);
            int nxt = 99;

            while (cmb.Successor(nxt))                          //Select two ALSs
            {
                UALS UA = ALSMan.ALSLst[cmb.Index[0]];
                nxt = 0; if (!UA.singly || UA.Size == 1 || UA.Size > (sz - 2))
                {
                    continue;
                }

                UALS UB = ALSMan.ALSLst[cmb.Index[1]];
                nxt = 1; if (!UB.singly || UB.Size == 1 || (UA.Size + UB.Size) != sz)
                {
                    continue;
                }

                int RCC = ALSMan.Get_AlsAlsRcc(UA, UB);          //Common numbers, House contact, Without overlap
                if (RCC == 0)
                {
                    continue;
                }

                if (RCC.BitCount() == 1)                          //===== Singly Linked =====
                {
                    int EnoB = (UA.FreeB & UB.FreeB).DifSet(RCC); //Exclude candidate digit
                    if (EnoB > 0 && _ALSXZ_SinglyLinked(UA, UB, RCC, EnoB))
                    {
                        SolCode = 2;
                        ALSXZ_SolResult(RCC, UA, UB);

                        if (__SimpleAnalizerB__)
                        {
                            return(true);
                        }
                        if (!pAnMan.SnapSaveGP(true))
                        {
                            return(true);
                        }
                    }
                }
                else if (RCC.BitCount() == 2)    //===== Doubly Linked =====
                {
                    if (_ALSXZ_DoublyLinked(UA, UB, RCC))
                    {
                        SolCode = 2;
                        ALSXZ_SolResult(RCC, UA, UB);

                        if (__SimpleAnalizerB__)
                        {
                            return(true);
                        }
                        if (!pAnMan.SnapSaveGP(true))
                        {
                            return(true);
                        }
                    }
                }
            }
            return(false);
        }