public bool NiceLoop( )   //Depth-first Search
        {
            Prepare();
            CeLKMan.PrepareCellLink(1 + 2);    //Generate StrongLink,WeakLink

            for (int szCtrl = 4; szCtrl < NiceLoopMax; szCtrl++)
            {
                foreach (var P0 in pBDL.Where(p => (p.No == 0)))                       //Origin Cell

                {
                    foreach (var no in P0.FreeB.IEGet_BtoNo())                     //Origin Number
                    {
                        foreach (var LKH in CeLKMan.IEGetRcNoType(P0.rc, no, 3))   //First Link
                        {
                            if (pAnMan.CheckTimeOut())
                            {
                                return(false);
                            }
                            var SolStack = new Stack <UCellLink>();
                            SolStack.Push(LKH);
                            Bit81 UsedCells = new Bit81(LKH.rc2);                   //Bit Representation of Used Cells
                            _NL_Search(LKH, LKH, SolStack, UsedCells, szCtrl - 1);
                            if (SolCode > 0)
                            {
                                return(true);
                            }
                        }
                    }
                }
            }
            return(false);
        }
        //X-Chain is an algorithm using Locked which occurs when concatenating strong and weak links.
        //http://csdenpe.web.fc2.com/page48.html
        public bool XChain()
        {
            Prepare();
            CeLKMan.PrepareCellLink(1);                                          //Generate StrongLink

            for (int no = 0; no < 9; no++)
            {
                int noB = (1 << no);

                List <int> LKRec = new List <int>();
                foreach (var CRL in _GetXChain(no, LKRec))
                {
                    int rcS = CRL[0].ID;                                 //Bit81.ID is used for information exchange(irregular use)

                    Bit81 ELM = (ConnectedCells[rcS] & CRL[1]) - CRL[2]; //CRL[2]:exclude chain of only two links(trivial solution).
                    if (ELM.IsZero())
                    {
                        continue;                                   //ELM:eliminatable cells
                    }
                    //===== X-Chain found =====
                    SolCode = 2;
                    foreach (var P in ELM.IEGetUCeNoB(pBDL, noB))
                    {
                        P.CancelB = noB;
                    }
                    string SolMsg = $"X-Chain #{(no+1)}";
                    Result = SolMsg;
                    if (SolInfoB)
                    {
                        Bit81 LKRecB = _SelectLink_XChain(LKRec, rcS, ELM, noB); //Extract related-Link
                        CRL[0] &= LKRecB; CRL[1] &= LKRecB;

                        Color Cr  = _ColorsLst[0];
                        Color Cr1 = Color.FromArgb(255, Cr.R, Cr.G, Cr.B);
                        Color Cr2 = Color.FromArgb(120, Cr.R, Cr.G, Cr.B);    //(Lightness adjustment)
                        foreach (var P in CRL[0].IEGetUCeNoB(pBDL, noB))
                        {
                            P.SetNoBBgColor(noB, AttCr, Cr2);
                        }
                        foreach (var P in CRL[1].IEGetUCeNoB(pBDL, noB))
                        {
                            P.SetNoBBgColor(noB, AttCr, Cr1);
                        }
                        pBDL[rcS].SetNoBBgColor(noB, AttCr, SolBkCr);
                        ResultLong = SolMsg;;
                    }
                    if (__SimpleAnalizerB__)
                    {
                        return(true);
                    }
                    if (!pAnMan.SnapSaveGP(true))
                    {
                        return(true);
                    }
                }
            }
            return(false);
        }
        private IEnumerable <Bit81[]> _GetXYChain(List <int> LKRec)
        {
            List <UCell> TBDbv = pBDL.FindAll(p => (p.FreeBC == 2));                //Extract BV_Cell(BV:bivalue).

            foreach (var PS in TBDbv)                                               //Choose one BV_Cell(=>PS)
            {
                int rcS = PS.rc;
                foreach (var no in PS.FreeB.IEGet_BtoNo())                          //Choose one digit(in PS)
                {
                    int     noB = (1 << no);
                    Bit81[] CRL = new Bit81[2];
                    CRL[0]    = new Bit81();                                        //Position of the target digit to be concatenated
                    CRL[1]    = new Bit81();                                        //Position of other digits to be connected
                    CRL[0].ID = rcS; CRL[1].ID = no;

                    Bit81       CnctdCs = ConnectedCells[rcS];                      //Associated cells group of starting cell
                    Queue <int> rcQue   = new Queue <int>();
                    int         no0     = pBDL[rcS].FreeB.BitReset(no).BitToNum();  //The other digit of the starting cell
                    rcQue.Enqueue((no0 << 8) | rcS);

                    LKRec.Clear();
                    while (rcQue.Count > 0)                                            //Extend the chain step by step
                    {
                        int rcX = rcQue.Dequeue();
                        int no1 = rcX >> 8, rc1 = rcX & 0xFF;
                        foreach (var LK in CeLKMan.IEGetRcNoType(rc1, no1, 1))       //strongLink connected with rc1, #no
                        {
                            int rc2 = LK.rc2;
                            if (pBDL[rc2].FreeBC != 2)
                            {
                                continue;                                           //bivalue?
                            }
                            if (CRL[0].IsHit(rc2) || CRL[1].IsHit(rc2))
                            {
                                continue;                                           //Different from colored cells?
                            }
                            //Exclude cells associated with the starting cell and having the same digit
                            if (CnctdCs.IsHit(rc2) && (pBDL[rc2].FreeB & noB) > 0)
                            {
                                continue;
                            }

                            int no2 = (pBDL[rc2].FreeB.BitReset(no1)).BitToNum();   //other digit
                            int nx  = (no2 == no)? 0: 1;
                            CRL[nx].BPSet(rc2);
                            rcQue.Enqueue((no2 << 8) | rc2);                          //Put the next [Digit&Cell] in Queue
                            LKRec.Add((rc1 << 8 | rc2));                              //Record Link
                        }
                    }
                    if (CRL[0].Count > 0 || CRL[1].Count > 0)
                    {
                        yield return(CRL);
                    }
                }
            }
            yield break;
        }
 private void Prepare()
 {
     if (pAnMan.GStage != GStageMemo)
     {
         GStageMemo = pAnMan.GStage;
         CeLKMan.Initialize();
         CeLKMan.PrepareCellLink(1 + 2);
     }
 }
Exemple #5
0
 private void Prepare()
 {
     if (pAnMan.GStage != GStageMemo)
     {
         GStageMemo = pAnMan.GStage;
         CeLKMan.Initialize();
         BVCellLst = null;
     }
 }
        private bool _NL_Search(UCellLink LK0, UCellLink LKpre, Stack <UCellLink> SolStack, Bit81 UsedCells, int szCtrl)
        {
            if (szCtrl <= 0)
            {
                return(false);
            }

            foreach (var LKnxt in CeLKMan.IEGet_CeCeSeq(LKpre))     //links that satisfy concatenation conditions
            {
                int rc2Nxt = LKnxt.rc2;
                if (UsedCells.IsHit(rc2Nxt))
                {
                    continue; //UsedCells does not include Origin Cell
                }
                {             //===== Chain Search =====
                    SolStack.Push(LKnxt);
                    //___Debug_Print_NLChain(SolStack);
                    if (rc2Nxt == LK0.rc1 && szCtrl == 1)
                    {
                        if (SolStack.Count > 2)                                               //Loop was formed (the next cell matches the Origin Cell)
                        {
                            int SolType = _NL_CheckSolution(LK0, LKnxt, SolStack, UsedCells); //Solved?
                            if (SolType > 0)
                            {
                                if (SolInfoB)
                                {
                                    _NL_SolResult(LK0, LKnxt, SolStack, SolType);
                                }

                                if (__SimpleAnalizerB__)
                                {
                                    return(true);
                                }
                                if (!pAnMan.SnapSaveGP(false))
                                {
                                    return(true);
                                }
                            }
                        }
                    }
                    else
                    {
                        Bit81 UsedCellsNxt = UsedCells | (new Bit81(rc2Nxt));       //Create a new bit expression of used cell
                        _NL_Search(LK0, LKnxt, SolStack, UsedCellsNxt, szCtrl - 1); //Next step Search(recursive call
                        if (SolCode > 0)
                        {
                            return(true);
                        }
                    }
                    SolStack.Pop();                                 //Failure(Cancel link extension processing)
                } //-----------------------------
            }
            return(false);
        }
        private IEnumerable <Bit81[]> _GetXChain(int no, List <int> LKRec)
        {
            Bit81 TBD = new Bit81(pBDL, (1 << no));

            int rcS;

            while ((rcS = TBD.FindFirstrc()) >= 0)                  //rcS:Set the origin cell.
            {
                TBD.BPReset(rcS);                                   //Reset TBD to Processed.

                //===== Repeatedly coloring processing. initialize =====
                Bit81[] CRL = new Bit81[3];                           //Coloring 2 groups(CRL[0] and CRL[1]).
                CRL[0]    = new Bit81(); CRL[1] = new Bit81(rcS); CRL[2] = new Bit81();
                CRL[0].ID = rcS;
                Queue <int> rcQue = new Queue <int>();
                rcQue.Enqueue((rcS << 1) | 1);                        //(First StrongLink)

                //===== Repeatedly coloring processing. start =====
                LKRec.Clear();                                      //clear chain recorder.
                bool firstLK = true;
                while (rcQue.Count > 0)
                {
                    int rcX = rcQue.Dequeue();                                     //recorded [cell and color]
                    int swF = 1 - (rcX & 1);                                       //next color(inversion S-W)
                    int rc1 = (rcX >> 1);                                          //next cell

                    foreach (var LKx in CeLKMan.IEGetRcNoType(rc1, no, (swF + 1))) //LKx:link connected to cell rc1
                    {
                        int rc2 = LKx.rc2;                                         //anather cell of LKx
                        if ((CRL[0] | CRL[1]).IsHit(rc2))
                        {
                            continue;                               //already colored
                        }
                        CRL[swF].BPSet(rc2);                        //coloring
                        rcQue.Enqueue((rc2 << 1) | swF);            //enqueue(next cell and color)
                        LKRec.Add(rc1 << 8 | rc2);                  //chain record
                        if (firstLK)
                        {
                            CRL[2].BPSet(rc2);                      //record colored cells from rcS(source cell)
                        }
                    }
                    firstLK = false;
                }
                if (CRL[1].Count > 0)
                {
                    yield return(CRL);
                }
                //----- Repeatedly coloring processing. end -----
            }
            yield break;
        }
        public void PrepareSuperLinkMan(bool AllF = false)
        {
            CeLKMan.PrepareCellLink(1 + 2);    //StrongLink,WeakLink
            if (AllF || GNPXApp000.GMthdOption["GroupedCells"] == "1")
            {
                GLKMan.Initialize();
            }
            if (AllF || GNPXApp000.GMthdOption["ALS"] == "1")
            {
                ALSMan.QSearch_AlsInnerLink();
            }

            L2SprLkB81 = new Bit81[9];
            for (int k = 0; k < 9; k++)
            {
                L2SprLkB81[k] = new Bit81();
            }
            L2SprLK = new USuperLink[81, 9];
        }
        private IEnumerable <Bit81[]> _Coloring(int no)
        {
            Bit81[] CRL = new Bit81[2];
            CRL[0] = new Bit81(); CRL[1] = new Bit81();
            Bit81 TBD = new Bit81(pBDL, (1 << no));
            int   rc1 = TBD.FindFirstrc();

            while (rc1 >= 0)
            {
                Queue <int> rcQue = new Queue <int>();
                rcQue.Enqueue(rc1 << 1);
                CRL[0].BPSet(rc1);
                TBD.BPReset(rc1);
                while (rcQue.Count > 0)
                {
                    rc1 = rcQue.Dequeue();
                    int kx = 1 - (rc1 & 1);
                    rc1 >>= 1;
                    TBD.BPReset(rc1);
                    foreach (var P in CeLKMan.IEGetRcNoType(rc1, no, 1))
                    {
                        int rc2 = P.rc2;
                        if (!(CRL[0] | CRL[1]).IsHit(rc2) && TBD.IsHit(rc2))
                        {
                            CRL[kx].BPSet(rc2); rcQue.Enqueue((rc2 << 1) | kx);
                        }
                    }
                }
                yield return(CRL);

                if ((rc1 = TBD.FindFirstrc()) < 0)
                {
                    yield break;
                }
                CRL    = new Bit81[2];
                CRL[0] = new Bit81(); CRL[1] = new Bit81();
            }
            yield break;
        }
        //Coloring is an algorithm that connects the focused digit with a strong link.
        //http://csdenpe.web.fc2.com/page46.html
        public bool Color_Trap( )
        {
            Prepare();
            CeLKMan.PrepareCellLink(1);                                         //Generate StrongLink

            for (int no = 0; no < 9; no++)
            {
                int noB = (1 << no);
                foreach (Bit81[] CRL in _Coloring(no))
                {
                    Bit81 HitB = new Bit81();
                    Bit81 ELM  = (new Bit81(pBDL, noB)) - (CRL[0] | CRL[1]);
                    foreach (var rc in ELM.IEGet_rc())
                    {
                        Bit81 HB = HouseCells[18 + rc.ToBlock()];
                        if (((ConnectedCells[rc] - HB) & CRL[0]).IsZero())
                        {
                            continue;
                        }
                        if (((ConnectedCells[rc] - HB) & CRL[1]).IsZero())
                        {
                            continue;
                        }
                        HitB.BPSet(rc);
                    }
                    if (!HitB.IsZero())
                    {
                        Color Cr  = _ColorsLst[0];
                        Color Cr1 = Cr; Cr1.A = (byte)120;              //Color.FromArgb(120,Cr.R,Cr.G,Cr.B);

                        foreach (var P in HitB.IEGet_rc().Select(p => pBDL[p]))
                        {
                            P.CancelB = noB;
                        }
                        foreach (var P in CRL[0].IEGet_rc().Select(p => pBDL[p]))
                        {
                            P.SetNoBBgColor(noB, AttCr, Cr);
                        }
                        foreach (var P in CRL[1].IEGet_rc().Select(p => pBDL[p]))
                        {
                            P.SetNoBBgColor(noB, AttCr, Cr1);
                        }

                        SolCode = 2;
                        string SolMsg = "Coloring Trap #" + (no + 1);
                        Result = SolMsg;
                        if (SolInfoB)
                        {
                            ResultLong = SolMsg;
                        }
                        if (__SimpleAnalizerB__)
                        {
                            return(true);
                        }
                        if (!pAnMan.SnapSaveGP(true))
                        {
                            return(true);
                        }
                        HitB = new Bit81();
                    }
                }
            }

            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);
        }
 public void Initialize()
 {
     CeLKMan.Initialize();
     GLKMan.Initialize();
     ALSMan.Initialize();
 }
        public bool MultiColor_Type2( )
        {
            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 prm = new Permutation(MCRL.Count, 2);
                while (prm.Successor())
                {
                    if (prm.Index[0] < prm.Index[1])
                    {
                        continue;
                    }
                    Bit81[] CRLa = MCRL[prm.Index[0]];
                    Bit81[] CRLb = MCRL[prm.Index[1]];
                    if (CRLa[0].IsZero() || CRLa[1].IsZero())
                    {
                        continue;
                    }
                    if (CRLb[0].IsZero() || CRLb[1].IsZero())
                    {
                        continue;
                    }

                    Bit81 HCRL0 = new Bit81(), HCRL1 = new Bit81();
                    foreach (var rc in CRLa[0].IEGet_rc())
                    {
                        HCRL0 |= ConnectedCells[rc];
                    }
                    foreach (var rc in CRLa[1].IEGet_rc())
                    {
                        HCRL1 |= ConnectedCells[rc];
                    }

                    for (int nb = 0; nb < 2; nb++)
                    {
                        if ((CRLb[nb] & HCRL0).IsZero())
                        {
                            continue;
                        }
                        if ((CRLb[nb] & HCRL1).IsZero())
                        {
                            continue;
                        }

                        Color Cr1 = _ColorsLst[0];
                        Color Cr2 = Color.FromArgb(100, Cr1.R, Cr1.G, Cr1.B);
                        foreach (var P in CRLa[0].IEGet_rc().Select(p => pBDL[p]))
                        {
                            P.SetNoBBgColor(noB, AttCr, Cr1);
                        }
                        foreach (var P in CRLa[1].IEGet_rc().Select(p => pBDL[p]))
                        {
                            P.SetNoBBgColor(noB, AttCr, Cr2);
                        }

                        Cr1 = _ColorsLst[1];
                        Cr2 = Color.FromArgb(100, Cr1.R, Cr1.G, Cr1.B);
                        foreach (var P in CRLb[1 - nb].IEGet_rc().Select(p => pBDL[p]))
                        {
                            P.SetNoBBgColor(noB, AttCr, Cr2);
                        }
                        foreach (var P in CRLb[nb].IEGet_rc().Select(p => pBDL[p]))
                        {
                            P.SetCellBgColor(Cr1); P.CancelB = noB;
                        }

                        SolCode = 2;
                        string SolMsg = "MultiColoring Type2 #" + (no + 1);
                        Result = SolMsg;
                        if (SolInfoB)
                        {
                            ResultLong = SolMsg;
                        }
                        if (__SimpleAnalizerB__)
                        {
                            return(true);
                        }
                        if (!pAnMan.SnapSaveGP(true))
                        {
                            return(true);
                        }
                    }
                }
            }
            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 #15
0
        //EmptyRectangle is an algorithm using cell-to-cell link and ConnectedCells.
        //http://csdenpe.web.fc2.com/page41.html
        public bool  EmptyRectangle( )
        {
            Prepare();
            CeLKMan.PrepareCellLink(1);                                         //Generate StrongLink

            for (int no = 0; no < 9; no++)                                      //Focused digit
            {
                int noB = 1 << no;
                for (int bx = 0; bx < 9; bx++)                                  //Focused Block
                {
                    int erB = pBDL.IEGetCellInHouse(bx + 18, noB).Aggregate(0, (Q, P) => Q | (1 << P.nx));
                    if (erB == 0)
                    {
                        continue;
                    }

                    for (int er = 0; er < 9; er++)                            //Focused Cell in the Focused Block
                    {
                        int Lr = er / 3, Lc = er % 3;                         //Block local Row and Column
                        int rxF = 7 << (Lr * 3);                              //7=1+2+4   (Block local Row r1c123)
                        int cxF = 73 << Lc;                                   //73=1+8+64 (Block local Column r123c1)

                        if ((erB & rxF) == 0 || erB.DifSet(rxF) == 0)
                        {
                            continue;                                       //Row Lr(Row Cndition Check)
                        }
                        if ((erB & cxF) == 0 || erB.DifSet(cxF) == 0)
                        {
                            continue;                                       //Column Lc(Column Cndition Check)
                        }
                        if (erB.DifSet(rxF | cxF) > 0)
                        {
                            continue;                                       //Row Lr and Column Lc(ER Condition Check)
                        }
                        int r1 = bx / 3 * 3 + Lr;                           //Convert to Absolute Row
                        int c1 = (bx % 3) * 3 + Lc;                         //Convert to Absolute Column

                        foreach (var P in HouseCells[9 + c1].IEGetUCeNoB(pBDL, noB).Where(Q => Q.b != bx))
                        {
                            //P:cell in house(column c1), P is outside bx
                            foreach (var LK in CeLKMan.IEGetRcNoBTypB(P.rc, noB, 1))//rc:link end, noB:digit, 1:StrongLink
                            {
                                UCell Elm = pBDL[r1 * 9 + LK.UCe2.c];
                                if (Elm.b != bx && (Elm.FreeB & noB) > 0)           //There is a Digit that can be excluded
                                {
                                    EmptyRectangle_SolResult(no, bx, LK, Elm);      //solution found
                                    if (__SimpleAnalizerB__)
                                    {
                                        return(true);
                                    }
                                    if (!pAnMan.SnapSaveGP(true))
                                    {
                                        return(true);
                                    }
                                }
                            }
                        }

                        foreach (var P in HouseCells[0 + r1].IEGetUCeNoB(pBDL, noB).Where(Q => Q.b != bx))
                        {
                            //P:cell in house(row r1), P is outside bx
                            foreach (var LK in CeLKMan.IEGetRcNoBTypB(P.rc, noB, 1))//rc:link end, noB:digit, 1:StrongLink
                            {
                                UCell Elm = pBDL[LK.UCe2.r * 9 + c1];
                                if (Elm.b != bx && (Elm.FreeB & noB) > 0)           //There is a Digit that can be excluded
                                {
                                    EmptyRectangle_SolResult(no, bx, LK, Elm);      //solution found
                                    if (__SimpleAnalizerB__)
                                    {
                                        return(true);
                                    }
                                    if (!pAnMan.SnapSaveGP(true))
                                    {
                                        return(true);
                                    }
                                }
                            }
                        }
                    }
                }
            }
            return(false);
        }
Exemple #16
0
        //Skyscraper is an algorithm consisting of two StrongLinks.
        //http://csdenpe.web.fc2.com/page40.html
        public bool Skyscraper()
        {
            Prepare();
            CeLKMan.PrepareCellLink(1);                                             //Generate StrongLink

            for (int no = 0; no < 9; no++)
            {
                int noB   = (1 << no);
                var SSLst = CeLKMan.IEGetNoType(no, 1).ToList();         //select only StrongLink of #no
                if (SSLst.Count <= 2)
                {
                    continue;
                }

                var prm  = new Permutation(SSLst.Count, 2);
                int nxtX = 99;
                while (prm.Successor(nxtX))
                {
                    UCellLink UCLa = SSLst[prm.Index[0]], UCLb = SSLst[prm.Index[1]];

                    nxtX = 1;
                    if (UCLa.ID > UCLb.ID)
                    {
                        nxtX = 0; continue;
                    }                                                   //next permutation data skip_generation(nxtX=0)
                    if ((UCLa.B81 | UCLb.B81).Count != 4)
                    {
                        continue;                                       //All cells are different?
                    }
                    Bit81 ConA1 = ConnectedCells[UCLa.rc1];             //ConA1:cell group related to cell rc1
                    if (!ConA1.IsHit(UCLb.rc1) || ConA1.IsHit(UCLb.rc2))
                    {
                        continue;
                    }

                    Bit81 ConA2 = ConnectedCells[UCLa.rc2];               //ConA2:cell group related to cell rc1
                    if (ConA2.IsHit(UCLb.rc1) || ConA2.IsHit(UCLb.rc2))
                    {
                        continue;
                    }
                    //Only UCLa.rc1 and UCLb.rc1 belong to the same house.

                    Bit81 ELM = ConA2 & ConnectedCells[UCLb.rc2];
                    ELM -= (ConA1 | ConnectedCells[UCLb.rc1]);          //ELM:eliminatable cells

                    bool SSfound = false;
                    foreach (UCell P in ELM.IEGetUCeNoB(pBDL, noB))
                    {
                        P.CancelB = P.FreeB & noB; SSfound = true;
                    }
                    if (!SSfound)
                    {
                        continue;           //Skyscraper found
                    }
                    #region Result
                    SolCode = 2;
                    if (SolInfoB)
                    {
                        pBDL[UCLa.rc1].SetNoBBgColor(noB, AttCr, SolBkCr);
                        pBDL[UCLa.rc2].SetNoBBgColor(noB, AttCr, SolBkCr);
                        pBDL[UCLb.rc1].SetNoBBgColor(noB, AttCr, SolBkCr);
                        pBDL[UCLb.rc2].SetNoBBgColor(noB, AttCr, SolBkCr);

                        string msg = "\r", msg2 = "";
                        msg += $"  on {(no+1)} in {UCLa.rc1.ToRCNCLString()} {UCLb.rc1.ToRCNCLString()}";
                        msg += $"\r  connected by {UCLa.rc2.ToRCNCLString()} {UCLb.rc2.ToRCNCLString()}";
                        msg += "\r  eliminated ";
                        foreach (UCell P in ELM.IEGetUCeNoB(pBDL, noB))
                        {
                            msg2 += " " + P.rc.ToRCString();
                        }
                        msg2      += " " + msg2.ToString_SameHouseComp();
                        ResultLong = "Skyscraper" + msg + msg2;
                        Result     = $"Skyscraper #{(no+1)} in {msg2}";
                    }
                    else
                    {
                        Result = $"Skyscraper #{(no+1)}";
                    }
                    #endregion Result
                    if (__SimpleAnalizerB__)
                    {
                        return(true);
                    }
                    if (!pAnMan.SnapSaveGP(true))
                    {
                        return(true);
                    }
                }
            }
            return(false);
        }
        //=================== 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);
        }
        //XY-Chain is an algorithm using Locked which occurs in the concatenation of bivalues.
        //http://csdenpe.web.fc2.com/page49.html
        public bool XYChain()
        {
            Prepare();
            CeLKMan.PrepareCellLink(1);                //Generate StrongLink

            List <int> LKRec = new List <int>();

            foreach (var CRL in _GetXYChain(LKRec))
            {
                int rcS = CRL[0].ID, no = CRL[1].ID, noB = (1 << no);

                Bit81 ELM = ConnectedCells[rcS] - (CRL[0] | CRL[1]);
                if (ELM.IsZero())
                {
                    continue;
                }

                Bit81 ELM2     = new Bit81();
                bool  XYChainF = false;
                foreach (var E in ELM.IEGetUCeNoB(pBDL, noB))
                {
                    if (CRL[0].IsHit(ConnectedCells[E.rc]))
                    {
                        E.CancelB = noB; XYChainF = true;
                        ELM2     |= CRL[0] & ConnectedCells[E.rc];
                        break;
                    }
                }
                if (!XYChainF)
                {
                    continue;
                }

                //===== XY-Chain found =====
                SolCode = 2;
                String SolMsg = "XY Chain";
                Result = SolMsg;

                int rcE;
                foreach (var P in ELM2.IEGetUCeNoB(pBDL, noB))
                {
                    P.SetNoBBgColor(noB, AttCr, SolBkCr);
                }
                Bit81 ELM2cpy = ELM2.Copy();
                while ((rcE = ELM2.FindFirstrc()) >= 0)
                {
                    string stR      = "";
                    Bit81  XYchainB = _SelectLink_XYChain(LKRec, rcS, rcE, noB, ref stR) - ELM2cpy;
                    if (SolInfoB)
                    {
                        SolMsg += "\r " + stR;
                    }

                    foreach (var P in XYchainB.IEGetUCeNoB(pBDL, 0x1FF))
                    {
                        P.SetNoBBgColor(P.FreeB, AttCr, SolBkCr2);
                    }
                    ELM2.BPReset(rcE);
                }
                if (SolInfoB)
                {
                    ResultLong = SolMsg;
                }
                pBDL[rcS].SetNoBBgColor(noB, AttCr, SolBkCr);

                if (__SimpleAnalizerB__)
                {
                    return(true);
                }
                if (!pAnMan.SnapSaveGP(true))
                {
                    return(true);
                }
                XYChainF = false;
            }
            return(false);
        }
        public bool Color_Wrap( )
        {
            Prepare();
            CeLKMan.PrepareCellLink(1);                //Generate StrongLink

            for (int no = 0; no < 9; no++)
            {
                int noB = (1 << no);
                foreach (Bit81[] CRL in _Coloring(no))
                {
                    Bit81 BD0 = new Bit81(pBDL, noB);
                    Bit81 ELM = BD0 - (CRL[0] | CRL[1]);
                    if (ELM.Count == 0)
                    {
                        continue;
                    }

                    for (int k = 0; k < 2; k++)
                    {
                        for (int dr = 0; dr < 27; dr++)
                        {
                            if ((CRL[k] & HouseCells[dr]).Count < 2)
                            {
                                continue;
                            }
                            Color CrA = _ColorsLst[1];
                            Color Cr  = _ColorsLst[0];
                            Color Cr1 = Cr;
                            Color Cr2 = Color.FromArgb(120, Cr.R, Cr.G, Cr.B);
                            foreach (var P in ELM.IEGet_rc().Select(p => pBDL[p]))
                            {
                                P.SetNoBBgColor(noB, AttCr, CrA);
                            }
                            foreach (var P in CRL[1 - k].IEGet_rc().Select(p => pBDL[p]))
                            {
                                P.SetNoBBgColor(noB, AttCr, Cr1);
                            }
                            foreach (var P in CRL[k].IEGet_rc().Select(p => pBDL[p]))
                            {
                                P.SetCellBgColor(Cr2); P.CancelB = noB;
                            }

                            SolCode = 2;
                            string SolMsg = "Coloring Wrap #" + (no + 1);
                            Result = SolMsg;
                            if (SolInfoB)
                            {
                                ResultLong = SolMsg;
                            }
                            if (__SimpleAnalizerB__)
                            {
                                return(true);
                            }
                            if (!pAnMan.SnapSaveGP(true))
                            {
                                return(true);
                            }
                        }
                    }
                }
            }
            return(false);
        }
        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);
        }