public bool EndoFinnedFMFish_sub( int sz, int no, int FMSize, bool FinnedF, bool EndoF=false, bool CannF=false ){ int noB=(1<<no); int BaseSel=0x7FFFFFF, CoverSel=0x7FFFFFF; FishMan FMan=new FishMan(this,FMSize,no,sz,(sz>=3)); foreach( var Bas in FMan.IEGet_BaseSet(BaseSel,FinnedF:FinnedF,EndoFlg:EndoF) ){ //BaseSet foreach(var Cov in FMan.IEGet_CoverSet(Bas,CoverSel,CannF)){ //CoverSet if(pAnMan.CheckTimeOut()) return false; Bit81 FinB81 = Cov.FinB81 | Bas.EndoFin; Bit81 E=Cov.CoverB81-Bas.BaseB81; Bit81 ELM=new Bit81(); //see latest viewpoint foreach( var rc in E.IEGet_rc() ){ if((FinB81-ConnectedCells[rc]).Count==0) ELM.BPSet(rc); } if( ELM.Count>0 ){ foreach(var P in ELM.IEGetUCeNoB(pBDL,noB)){ P.CancelB=noB; SolCode=2; } if(SolCode>0){ if(SolInfoB){ _Fish_FishResult(no,sz,Bas,Cov,(FMSize==27)); //27:Franken/Mutant } //WriteLine(ResultLong); if(__SimpleAnalizerB__) return true; if(!pAnMan.SnapSaveGP(true)) 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); }
//Link between Cell and ALS public void QSearch_Cell2ALS_Link( ) { if (ALSLst == null) { PrepareALSLinkMan(1); } if (LinkCeAlsLst != null) { return; } LinkCeAlsLst = new List <LinkCellALS> [81]; if (ALSLst == null || ALSLst.Count < 2) { return; } foreach (var PA in ALSLst.Where(P => P.singly)) { foreach (var no in PA.FreeB.IEGet_BtoNo()) { int noB = (1 << no); Bit81 H = new Bit81(true); foreach (var P in PA.UCellLst.Where(q => (q.FreeB & noB) > 0)) { H &= pConnectedCells[P.rc]; } if (H.IsZero()) { continue; } foreach (var P in H.IEGetUCeNoB(pBDL, noB)) { var Q = new LinkCellALS(P, PA, no); if (LinkCeAlsLst[P.rc] == null) { LinkCeAlsLst[P.rc] = new List <LinkCellALS>(); } LinkCeAlsLst[P.rc].Add(Q); } } } for (int rc = 0; rc < 81; rc++) { if (LinkCeAlsLst[rc] != null) { LinkCeAlsLst[rc].Sort(); } } }
private Bit81 _SelectLink_XChain(List <int> LKRec, int rcS, Bit81 ELM, int noB) { Bit81 LKRecB = new Bit81(); foreach (var P in ELM.IEGetUCeNoB(pBDL, noB)) { int rcX = P.rc; LKRecB.BPSet(rcX); while (rcX != rcS) { rcX = LKRec.Find(p => (p & 0xFF) == rcX); if (rcX == 0) { break; } rcX = (rcX >> 8); LKRecB.BPSet(rcX); } } return(LKRecB); }
//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); }
//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 ExtFishSub(int sz, int no, int FMSize, int BaseSel, int CoverSel, bool FinnedF, bool _Fdef = true) { int noB = (1 << no); bool extFlag = (sz >= 3 && ((BaseSel | CoverSel).BitCount() > 18)); if (_Fdef) { FMan = new FishMan(this, FMSize, no, sz, extFlag); } foreach (var Bas in FMan.IEGet_BaseSet(BaseSel, FinnedF:FinnedF)) //select BaseSet { if (pAnMan.CheckTimeOut()) { return(false); } foreach (var Cov in FMan.IEGet_CoverSet(Bas, CoverSel, FinnedF)) //select CoverSet { Bit81 FinB81 = Cov.FinB81; Bit81 ELM = null; var FinZeroB = FinB81.IsZero(); if (!FinnedF && FinZeroB) //===== no Fin ===== { if (!FinnedF && (ELM = Cov.CoverB81 - Bas.BaseB81).Count > 0) { foreach (var P in ELM.IEGetUCeNoB(pBDL, noB)) { P.CancelB = noB; SolCode = 2; } if (SolCode > 0) //solved!( { if (SolInfoB) { _Fish_FishResult(no, sz, Bas, Cov, (FMSize == 27)); //FMSize 18:regular 27:Franken/Mutant } if (__SimpleAnalizerB__) { return(true); } if (!pAnMan.SnapSaveGP(true)) { return(true); } } } } else if (FinnedF && !FinZeroB) //===== Finned ===== { Bit81 Ecand = Cov.CoverB81 - Bas.BaseB81; ELM = new Bit81(); foreach (var P in Ecand.IEGetUCeNoB(pBDL, noB)) { if ((FinB81 - ConnectedCells[P.rc]).Count == 0) { ELM.BPSet(P.rc); } } if (ELM.Count > 0) //there are cells/digits can be excluded { foreach (var P in ELM.IEGet_rc().Select(p => pBDL[p])) { P.CancelB = noB; SolCode = 2; } if (SolCode > 0) //solved! { if (SolInfoB) { _Fish_FishResult(no, sz, Bas, Cov, (FMSize == 27)); //FMSize 18:regular 27:Franken/Mutant } if (__SimpleAnalizerB__) { return(true); } if (!pAnMan.SnapSaveGP(true)) { return(true); } } } } continue; } } return(false); }
//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); }
//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); }
public bool CannibalisticFMFish_sub(int sz, int no, int FMSize, bool FinnedF, bool EndoF = false, bool CannF = false) { int noB = (1 << no); int BaseSel = 0x7FFFFFF, CoverSel = 0x7FFFFFF; FishMan FMan = new FishMan(this, FMSize, no, sz, (sz >= 3)); foreach (var Bas in FMan.IEGet_BaseSet(BaseSel, FinnedF:FinnedF, EndoFlg:EndoF)) //BaseSet { foreach (var Cov in FMan.IEGet_CoverSet(Bas, CoverSel, CannF)) //CoverSet { if (pAnMan.CheckTimeOut()) { return(false); } Bit81 FinB81 = Bas.BaseB81 - Cov.CoverB81; if (FinB81.Count == 0) { foreach (var P in Cov.CannFin.IEGetUCeNoB(pBDL, noB)) { P.CancelB = noB; SolCode = 2; } if (SolCode > 0) { if (SolInfoB) { _Fish_FishResult(no, sz, Bas, Cov, (FMSize == 27)); //FMSize 27:Franken/Mutant } //WriteLine(ResultLong); //___Debug_CannFish("Cannibalistic"); if (__SimpleAnalizerB__) { return(true); } if (!pAnMan.SnapSaveGP(true)) { return(true); } } } else { FinB81 |= Cov.CannFin; Bit81 ELM = null; Bit81 E = (Cov.CoverB81 - Bas.BaseB81) | Cov.CannFin; ELM = new Bit81(); foreach (var rc in E.IEGet_rc()) { if ((FinB81 - ConnectedCells[rc]).Count == 0) { ELM.BPSet(rc); } } if (ELM.Count > 0) { foreach (var P in ELM.IEGetUCeNoB(pBDL, noB)) { P.CancelB = noB; SolCode = 2; } if (SolCode > 0) { if (SolInfoB) { _Fish_FishResult(no, sz, Bas, Cov, (FMSize == 27)); } //WriteLine(ResultLong); //___Debug_CannFish("Finned Cannibalistic"); if (__SimpleAnalizerB__) { return(true); } if (!pAnMan.SnapSaveGP(true)) { return(true); } } } } } } return(false); }
private void SearchGroupedLink() { try{ UGrCells[] LQ = new UGrCells[3]; for (int no = 0; no < 9; no++) { int noB = 1 << no; Bit81 BPnoB = new Bit81(pBDL, noB); //------------------------------------------ for (int tfx = 0; tfx < 18; tfx++) { Bit81 BPnoB2 = BPnoB & pHouseCells[tfx]; List <Bit81> houseLst = new List <Bit81>(); List <int> tfxLst = new List <int>(); for (int k = 0; k < 9; k++) { int hx = (tfx < 9)? (k + 9): k; Bit81 BX = BPnoB2 & pHouseCells[hx]; if (BX.IsZero()) { continue; } houseLst.Add(BX); tfxLst.Add(hx); } for (int k = 0; k < 3; k++) { int hx = (tfx < 9)? (tfx / 3 * 3 + k): ((tfx - 9) / 3 + k * 3); hx += 18; Bit81 BX = BPnoB2 & pHouseCells[hx]; if (BX.IsZero()) { continue; } houseLst.Add(BX); tfxLst.Add(hx); } if (houseLst.Count < 2) { continue; } Permutation prm = new Permutation(houseLst.Count, 2); while (prm.Successor()) { int na = prm.Index[0], nb = prm.Index[1]; Bit81 HA = houseLst[na]; Bit81 HB = houseLst[nb]; if (!(HA & HB).IsZero()) { continue; } UGrCells LA = new UGrCells(tfxLst[na], no); UGrCells LB = new UGrCells(tfxLst[nb], no); foreach (var P in HA.IEGetUCeNoB(pBDL, 0x1FF)) { LA.Add(P); } foreach (var P in HB.IEGetUCeNoB(pBDL, 0x1FF)) { LB.Add(P); } SetGroupedLink(tfxLst[nb], W, no, LA, LB); if (!(BPnoB2 - (HA | HB)).IsZero()) { continue; } SetGroupedLink(tfxLst[nb], S, no, LA, LB); } } //------------------------------------------ for (int tfx = 18; tfx < 27; tfx++) { int bx = tfx - 18; int b0 = (bx / 3 * 27 + (bx % 3) * 3); //Cell number at the top left of the block Bit81 BPnoB2 = BPnoB & pHouseCells[tfx]; List <Bit81> houseLst = new List <Bit81>(); List <int> tfxLst = new List <int>(); for (int k = 0; k < 3; k++) { int r0 = (b0 / 9 + k); Bit81 BX = BPnoB2 & pHouseCells[r0]; if (BX.IsZero()) { continue; } houseLst.Add(BX); tfxLst.Add(r0); } for (int k = 0; k < 3; k++) { int c0 = (b0 % 9) + k; Bit81 BX = BPnoB2 & pHouseCells[c0 + 9]; if (BX.IsZero()) { continue; } houseLst.Add(BX); tfxLst.Add(c0 + 9); } if (houseLst.Count >= 2) { Permutation prm = new Permutation(houseLst.Count, 2); while (prm.Successor()) { int na = prm.Index[0], nb = prm.Index[1]; Bit81 HA = houseLst[na]; Bit81 HB = houseLst[nb] - HA; if (HB.IsZero()) { continue; } UGrCells LA = new UGrCells(tfxLst[na], no); UGrCells LB = new UGrCells(tfxLst[nb], no); foreach (var P in HA.IEGetUCeNoB(pBDL, 0x1FF)) { LA.Add(P); } foreach (var P in HB.IEGetUCeNoB(pBDL, 0x1FF)) { LB.Add(P); } SetGroupedLink(tfxLst[nb], W, no, LA, LB); if (!(BPnoB2 - (HA | HB)).IsZero()) { continue; } SetGroupedLink(tfxLst[nb], S, no, LA, LB); } } if (houseLst.Count >= 1) { for (int na = 0; na < houseLst.Count; na++) { Bit81 HA = houseLst[na]; UGrCells LA = new UGrCells(tfxLst[na], no); foreach (var P in HA.IEGetUCeNoB(pBDL, 0x1FF)) { LA.Add(P); } foreach (var rc in BPnoB2.IEGet_rc()) { if (HA.IsHit(rc)) { continue; } UGrCells LB = new UGrCells(-9, no, pBDL[rc]); SetGroupedLink(tfxLst[na], W, no, LA, LB); SetGroupedLink(-9, W, no, LB, LA); } } } } } } catch (Exception ex) { WriteLine(ex.Message); WriteLine(ex.StackTrace); } }