Esempio n. 1
0
        private void EmptyRectangle_SolResult(int no, int bx, UCellLink PLK, UCell PElm)
        {
            int noB = (1 << no);

            SolCode      = 2;
            Result       = $"EmptyRectangl #{(no+1)} in b{(bx+1)}";
            PElm.CancelB = noB;                                             //Cancellation Digit Setting
            if (!SolInfoB)
            {
                return;
            }

            ResultLong = "EmptyRectangl";
            PLK.UCe1.SetNoBBgColor(noB, AttCr, SolBkCr2);                   //Mark Strong Links
            PLK.UCe2.SetNoBBgColor(noB, AttCr, SolBkCr2);                   //Mark Strong Links

            string st = "";

            foreach (var Q in pBDL.IEGetCellInHouse(bx + 18, noB))
            {
                Q.SetNoBBgColor(noB, AttCr, SolBkCr);   //Empty Rectangle
                st += " " + Q.rc.ToRCString();
            }
            string msg = $"\r         digit: #{(no+1)}\r            ER: B{(bx+1)}({st.ToString_SameHouseComp()})";

            msg       += $"\r        S-Link: {PLK.rc1.ToRCString()}-{PLK.rc2.ToRCString()}";
            msg       += $"\rEliminatedCell: {PElm.rc.ToRCString()}";
            ResultLong = "EmptyRectangl" + msg;
        }
Esempio n. 2
0
        public bool Check_CellCellSequence(UCellLink LKpre, UCellLink LKnxt)
        {
            int   noP = LKpre.no, noN = LKnxt.no;
            UCell UCX = LKpre.UCe2;

            switch (LKpre.type)
            {
            case 1:
                switch (LKnxt.type)
                {
                case 1: return(noP != noN);         //S->S

                case 2: return(noP == noN);         //S->W
                }
                break;

            case 2:
                switch (LKnxt.type)
                {
                case 1: return(noP == noN);                        //W->S

                case 2: return((noP != noN) && (UCX.FreeBC == 2)); //W->W
                }
                break;
            }
            return(false);
        }
Esempio n. 3
0
        public GroupedLink(UCellLink LK) : this()
        {
            UCelLK    = LK;
            UGCellsA  = new UGrCells(LK.tfx, LK.no, LK.UCe1);
            UGCellsB  = new UGrCells(LK.tfx, LK.no, LK.UCe2);
            this.type = LK.type;
            this.tfx  = LK.tfx;

            FreeB = UGCellsA.Aggregate(0, (Q, P) => Q | P.FreeB);
            FreeB = UGCellsB.Aggregate(FreeB, (Q, P) => Q | P.FreeB);
        }
        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 representation 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);
        }
Esempio n. 5
0
        public void SetLinkList(int tfx, int type, int no, UCell UC1, UCell UC2, bool SFlag = false)
        {
            var LK  = new UCellLink(tfx, type, no, UC1, UC2, SFlag);
            int rc1 = UC1.rc;

            if (CeLK81[rc1] == null)
            {
                CeLK81[rc1] = new List <UCellLink>();
            }
            if (!CeLK81[rc1].Contains(LK))
            {
                CeLK81[rc1].Add(LK);
            }
        }
        public bool Check_SuperLinkSequence(GroupedLink GLKpre, GroupedLink GLKnxt)
        {
            if (GLKpre == null)
            {
                WriteLine("null");
            }
            int typP = GLKpre.type;

            if (GLKpre is ALSLink)
            {
                typP = S;
            }
            int noP = GLKpre.no2;

            int typN = GLKnxt.type;
            int noN  = GLKnxt.no;

            UCellLink LKpre = GLKpre.UCelLK;
            UCellLink LKnxt = GLKnxt.UCelLK;

            int FreeBC = 0;

            if (LKpre != null)
            {
                FreeBC = pBDL[LKpre.rc2].FreeBC;

                if (LKnxt != null)   //singleLink -> singleLink
                {
                    return(_Check_SWSequenceSub(typP, noP, LKnxt.type, noN, FreeBC));
                }
                else                //singleLink -> multiLink
                {
                    UGrCells UGrCs = GLKnxt.UGCellsA;
                    if (UGrCs.Count == 1) //singleCell -> singleCell
                    {
                        return(_Check_SWSequenceSub(typP, noP, typN, noN, FreeBC));
                    }
                }
            }
            else if (GLKpre.UGCellsB.Count == 1 && LKnxt != null) // multiLink -> singleLink
            {
                FreeBC = GLKpre.UGCellsB.FreeB.BitCount();
                return(_Check_SWSequenceSub(typP, noP, typN, noN, FreeBC));
            }

            FreeBC = GLKpre.UGCellsB.FreeB.BitCount();
            return(_Check_SWSequenceSub(typP, noP, typN, noN, FreeBC));
        }
        private void _NL_SolResult(UCellLink LK0, UCellLink LKnxt, Stack <UCellLink> SolStack, int SolType)
        {
            string st = "";

            List <UCellLink> SolLst = SolStack.ToList();

            SolLst.Reverse();
            SolLst.Add(LK0);

            foreach (var LK in SolLst)
            {
                int   noB = (1 << LK.no);
                UCell P1 = pBDL[LK.rc1], P2 = pBDL[LK.rc2];
                P2.SetCellBgColor(SolBkCr);
                if (LK.type == S)
                {
                    P1.SetNoBColor(noB, AttCr); P2.SetNoBColor(noB, AttCr3);
                }
                else
                {
                    P2.SetNoBColor(noB, AttCr); P1.SetNoBColor(noB, AttCr3);
                }
            }

            if (SolType == 1)
            {
                st = "Nice Loop(Continuous)";             //continuous
            }
            else                                          //discontinuous
            {
                st = $"Nice Loop(Discontinuous) r{(LK0.rc1/9+1)}c{(LK0.rc1%9+1)}";
                int dcTyp = LK0.type * 10 + LKnxt.type;
                switch (dcTyp)
                {
                case 11: st += $" is {(LK0.no+1)}";       break;    //S->S

                case 12: st += $" is not {(LKnxt.no+1)}"; break;    //S->W

                case 21: st += $" is not {(LK0.no+1)}";   break;    //W->S

                case 22: st += $" is not {(LK0.no+1)}";   break;    //W->W
                }
            }

            Result     = st;
            ResultLong = st + "\r" + _ToRCSequenceString(SolStack);
        }
Esempio n. 8
0
        public IEnumerable <UCellLink> IEGet_CeCeSeq(UCellLink LKpre)
        {
            var P = CeLK81[LKpre.rc2];

            if (P == null)
            {
                yield break;
            }
            foreach (var LKnxt in P)
            {
                if (Check_CellCellSequence(LKpre, LKnxt))
                {
                    yield return(LKnxt);
                }
            }
            yield break;
        }
Esempio n. 9
0
        public override bool Equals(object obj)
        {
            UCellLink Q = obj as UCellLink;

            if (Q == null)
            {
                return(true);
            }
            if (this.type != Q.type || this.no != Q.no)
            {
                return(false);
            }
            if (this.rc1 != Q.rc1 || this.rc2 != Q.rc2)
            {
                return(false);
            }
            return(true);
        }
Esempio n. 10
0
        public GroupedLink(UCell UC, int no1, int no2, int type, bool rootF = false) : this()
        {
            this.rootF = rootF;
            int F = (1 << no1) | (1 << no2);

            // if( no1==no2 || (UC.FreeB&(1<<no1))==0 || (UC.FreeB&(1<<no2))==0 ){
            if ((UC.FreeB & (1 << no1)) == 0 || (UC.FreeB & (1 << no2)) == 0)
            {
                UGCellsA = UGCellsB = null;
                return;
            }

            UGCellsA  = new UGrCells(-1, no1, UC);
            UGCellsB  = new UGrCells(-1, no2, UC);
            UCelLK    = null;
            this.type = (UC.FreeBC == 2)? type: 2;          //2:WeakLink

            FreeB = UGCellsA.Aggregate(0, (Q, P) => Q | P.FreeB);
            FreeB = UGCellsB.Aggregate(FreeB, (Q, P) => Q | P.FreeB);
        }
Esempio n. 11
0
        public int CompareTo(object obj)
        {
            UCellLink Q = obj as UCellLink;

            if (this.type != Q.type)
            {
                return(this.type - Q.type);
            }
            if (this.no != Q.no)
            {
                return(this.no - Q.no);
            }
            if (this.rc1 != Q.rc1)
            {
                return(this.rc1 - Q.rc1);
            }
            if (this.rc2 != Q.rc2)
            {
                return(this.rc2 - Q.rc2);
            }
            return(this.ID - Q.ID);
        }
        private string _ToRCSequenceString(Stack <UCellLink> SolStack)
        {
            if (SolStack.Count == 0)
            {
                return("[rc]:-");
            }
            List <UCellLink> SolLst = SolStack.ToList();

            SolLst.Reverse();

            UCellLink LK0 = SolLst[0];
            UCell     P0  = pBDL[LK0.rc1];
            string    po  = $"[rc]:[{(P0.rc/9*10+(P0.rc%9)+11)}]";

            foreach (var LK in SolLst)
            {
                UCell  P1 = pBDL[LK.rc2];
                string mk = (LK.type == 1)? "=": "-";
                po += mk + (LK.no + 1) + mk + $"[{(P1.rc/9*10+(P1.rc%9)+11)}]";
            }
            return(po);
        }
Esempio n. 13
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);
        }
Esempio n. 14
0
        public UCellLink Reverse()
        {
            UCellLink ULK = new UCellLink(tfx, type, no, UCe2, UCe1, SFlag);

            return(ULK);
        }
        //XYwing is an algorithm that consists of two WeakLinks with common cells.
        //http://csdenpe.web.fc2.com/page42.html
        public bool XYwing( )
        {
            Prepare();
            CeLKMan.PrepareCellLink(2);                                         //Generate WeakLinks

            if (BVCellLst == null)
            {
                BVCellLst = pBDL.FindAll(p => (p.FreeBC == 2));                 //Generate BVs(BV:bivalue).
            }
            if (BVCellLst.Count < 3)
            {
                return(false);
            }

            bool XYwing = false;

            foreach (var P0 in BVCellLst)                                       //Choose one BV_Cell(=>PS)
            {
                List <UCellLink> BVLKLst = CeLKMan.IEGetRcNoBTypB(P0.rc, 0x1FF, 2).Where(R => R.BVFlag).ToList();
                //Extract WeakLinks starting from P0
                //foreach( var P in BVLKLst ) WriteLine(P);
                if (BVLKLst.Count < 2)
                {
                    continue;
                }

                var cmb = new Combination(BVLKLst.Count, 2);
                int nxt = 1;
                while (cmb.Successor(nxt))                                              //Combine two WLinks from BVLKLst
                {
                    UCellLink LKA = BVLKLst[cmb.Index[0]], LKB = BVLKLst[cmb.Index[1]]; //(
                    UCell     Q = LKA.UCe2, R = LKB.UCe2;
                    if (Q.rc == R.rc || LKA.no == LKB.no)
                    {
                        continue;                                               //Two WLinks have different end and different digits
                    }
                    Bit81 Q81 = ConnectedCells[LKA.rc2] & ConnectedCells[LKB.rc2];
                    if (Q81.Count <= 0)
                    {
                        continue;                                               //Two WLinks have cells connected indirectly
                    }
                    int noB = Q.FreeB.DifSet(1 << LKA.no) & R.FreeB.DifSet(1 << LKB.no);
                    if (noB == 0)
                    {
                        continue;                                               //Two WLinks have common digit(=>no).
                    }
                    int no = noB.BitToNum();

                    string msg2 = "";
                    foreach (var A in Q81.IEGetUCeNoB(pBDL, noB))
                    {
                        if (A == P0 || A == Q || A == R)
                        {
                            continue;
                        }
                        A.CancelB = noB; XYwing = true;                             //cell(A)/digit(no) can be excluded
                        if (SolInfoB)
                        {
                            msg2 += $" {A.rc.ToRCNCLString()}(#{no+1})";
                        }
                    }

                    if (XYwing)
                    {
                        SolCode = 2;
                        P0.SetNoBColor(P0.FreeB, AttCr); P0.SetCellBgColor(SolBkCr);
                        Q.SetCellBgColor(SolBkCr); R.SetCellBgColor(SolBkCr);

                        string msg0 = $" Pivot: {_XYwingResSub(P0)}";
                        string msg1 = $" Pin: {_XYwingResSub(R)} ,{_XYwingResSub(Q)}";
                        Result = "XY Wing" + msg0;
                        if (SolInfoB)
                        {
                            ResultLong = $"XY Wing\r     {msg0}\r       {msg1}\r Eliminated:{msg2}";
                        }

                        if (__SimpleAnalizerB__)
                        {
                            return(true);
                        }
                        if (!pAnMan.SnapSaveGP())
                        {
                            return(true);
                        }
                        XYwing = false;
                    }
                }
            }
            return(false);
        }
        private 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);
        }