/// <summary> /// If two cells in one segment contains the same two candidates only, /// then these candidates in other cells can be removed. /// </summary> private void NakedPair(List <Cell> changes) { using (var cacheItem = _cache.Get <Candidates, int>()) { var dic = cacheItem.Dictionary; foreach (var seg in Segments) { if (seg.FreeCells < 3) { continue; } dic.Clear(); foreach (var cell in seg) { if (cell.HasValue) { continue; } if (dic.ContainsKey(cell.Candidates)) { dic[cell.Candidates]++; } else { dic[cell.Candidates] = 1; } } foreach (var pair in dic) { if (pair.Value < 2 || pair.Value >= seg.FreeCells) { continue; } if (CandidatesHelper.Count(pair.Key) != pair.Value) { continue; } foreach (var cell in seg) { if (cell.HasValue || cell.Candidates == pair.Key) { continue; } var old = cell.Candidates; cell.RemoveCandidates(pair.Key); if (cell.Candidates != old) { changes.Add(cell); } } } } } }
public void RemoveCandidates(Candidates candidates) { if (HasValue) { return; } Candidates &= ~candidates; Possibilities = CandidatesHelper.Count(Candidates); OnChanged(); }
public bool HasCandidate(int value) { if (HasValue || (Candidates & CandidatesHelper.ToCandidate(value)) == 0) { return(false); } else { return(true); } }
private new void Add(Cell cell) { base.Add(cell); if (!cell.HasValue) { FreeCells++; } else { Values |= CandidatesHelper.ToCandidate(cell.Value); } }
public void SetCandidates(Candidates candidates) { if (HasValue) { throw new InvalidOperationException("Cell has already a value."); } if ((Candidates | candidates) != Candidates) { throw new InvalidOperationException("Cannot add new candidates."); } Candidates = candidates; Possibilities = CandidatesHelper.Count(Candidates); OnChanged(); }
public void SetSingleCandidate(int value) { if (value < Cell.MinValue || value > Cell.MaxValue) { throw new ArgumentOutOfRangeException("Invalid value."); } if (HasValue) { throw new InvalidOperationException("Cell has already a value."); } Candidates = CandidatesHelper.ToCandidate(value); Possibilities = 1; OnChanged(); }
public void Reset() { if (HasValue) { foreach (var seg in Segments.Keys) { seg.FreeCells++; seg.Values &= ~CandidatesHelper.ToCandidate(Value); } } _value = Cell.EmptyValue; IsFixed = false; Candidates = Cell.AllCandidates; Possibilities = CandidatesHelper.Count(Candidates); OnChanged(); }
public void RemoveSingleCandidate(int value) { if (value < Cell.MinValue || value > Cell.MaxValue) { throw new ArgumentOutOfRangeException("Invalid value."); } if (HasValue) { return; } if (!HasCandidate(value)) { return; } Candidates &= ~CandidatesHelper.ToCandidate(value); Possibilities--; OnChanged(); }
public bool HasValue(int value) { return((Values & CandidatesHelper.ToCandidate(value)) != 0); }
/// <summary> /// If two candidates in one segment are contained in the same two cells only, /// then other candidates in those cells can be removed. /// </summary> private void HiddenPair(List <Cell> changes) { using (var cacheItem = _cache.Get <int, SinglePairInfo>()) { var dic = cacheItem.Dictionary; // cells -> count, Candidates foreach (var seg in Segments) { if (seg.FreeCells < 3) { continue; } dic.Clear(); for (int i = Cell.MinValue; i <= Cell.MaxValue; i++) { if (seg.HasValue(i)) { continue; } List <Cell> cells = new List <Cell>(); int cellMask = 0; int mask = 1; foreach (var cell in seg) { if (cell.HasCandidate(i)) { cellMask |= mask; cells.Add(cell); } mask <<= 1; } SinglePairInfo info; if (dic.TryGetValue(cellMask, out info)) { info.Count++; info.Candidates |= CandidatesHelper.ToCandidate(i); } else { dic[cellMask] = new SinglePairInfo() { Cells = cells, Count = 1, Candidates = CandidatesHelper.ToCandidate(i) }; } } foreach (var info in dic.Values) { if (info.Count < 2 || info.Cells.Count != info.Count) { continue; } foreach (var cell in info.Cells) { if (cell.Possibilities != info.Count) { cell.SetCandidates(info.Candidates); changes.Add(cell); } } } } } }