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