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); }
//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); }
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); }
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) } }
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); }
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); }