private static void SearchForSingleInGroup(SolvingContext context, ICellGroup group) { var allNumbers = Enumerable.Range(1, 9) .Select(x => (short)x) .Except(group.Select(x => x.Value).Distinct()) .ToList(); var singles = allNumbers.Select(x => new { Value = x, ElligibleCellsCount = group.Count(y => y.CanPutCandidate(x)) }) .Where(x => x.ElligibleCellsCount == 1) .Select(x => x.Value) .ToList(); var single = singles.FirstOrDefault(); if (single == 0) { return; } var targetCell = group.FirstOrDefault(x => x.CanPutCandidate(single)); if (targetCell == null) { return; } var newCell = new Cell(single, targetCell.X, targetCell.Y); context.Grid = context.Grid.UpdateCell(newCell); context.FilledInCellsCount++; context.GoToLoopStart = true; }
private static void FindCandidatesPairsInCells(SolvingContext context, ICellGroup cellGroup) { var allNumbers = GetAllSudokuNumbers(); var unassignedValues = allNumbers.Except(cellGroup.Select(x => x.Value)).ToList(); var allNumbersCombinations = unassignedValues .SelectMany(x => unassignedValues, Tuple.Create) .Where(tuple => tuple.Item1 != tuple.Item2) .ToList(); foreach (var combination in allNumbersCombinations) { var first = combination.Item1; var firstValueCells = cellGroup.Where(x => x.CanPutCandidate(first)).ToList(); var second = combination.Item2; var secondValueCells = cellGroup.Where(x => x.CanPutCandidate(second)).ToList(); if (firstValueCells.Count != 2 || secondValueCells.Count != 2 || !firstValueCells.SequenceEqual(secondValueCells)) { continue; } foreach (var cell in firstValueCells) { context.CellsAffectedWithCrossOut += cell.RemoveCandidatesExcept(combination.ToArray()); } RemoveCandidates(context, cellGroup, Tuple.Create(firstValueCells.First(), firstValueCells.Last())); } }
private void RememberValueIsNowInvalidForTheRestOfTheCellsOfMy(ICellGroup cellgroup, CellValue value) { foreach (var cell in cellgroup.Cells.Where(cell => cell != this)) { cell.RememberValueCanNotBe(value); } }
/// <summary> /// Checks if an enumeration of <see cref="ICell"/> contains one cell for each value starting at 1 /// </summary> /// <param name="line"> The enumeration of cells </param> /// <returns> True if the group is completed </returns> public static bool IsCompleted(this ICellGroup line) { for (int column = 0; column < line.Cells.Count(); column++) { if (!line.Cells.Any(x => x.Value == column + 1)) { return(false); } } return(true); }
private static void RemoveCandidates(SolvingContext context, ICellGroup cellGroup, Tuple <ICell, ICell> pair) { var otherCells = cellGroup.Except(pair.ToList()).ToList(); var firstFields = pair.Item1.GetCandidates().ToList(); context.Pairs.Add(Tuple.Create(firstFields.First(), firstFields.Last())); context.PairFound = true; foreach (var otherCell in otherCells) { context.CellsAffectedWithCrossOut += otherCell.RemoveCandidates(firstFields.ToArray()); } }
/// <summary> /// Get the indices of all empty cells inside this line /// </summary> /// <param name="cells"> The enumeration of cells </param> /// <returns> The indices of the empty cells </returns> public static IEnumerable <uint> GetEmptyIndices(this ICellGroup line) { var rVal = new LinkedList <uint>(); for (uint i = 0; i < line.Cells.Count(); i++) { if (line.Cells.ElementAt((int)i).Value == 0) { rVal.AddLast(i); } } return(rVal); }
/// <summary> /// Get all the values that are missing in an enumeration of cells. /// </summary> /// <returns> An enumeration of uints representing the missing values </returns> public static IEnumerable <uint> GetMissingValues(this ICellGroup line) { var rVal = new LinkedList <uint>(); for (uint i = 1; i <= line.Cells.Count(); i++) { if (!line.Cells.Any(x => x.Value == i)) { rVal.AddLast(i); } } return(rVal); }
private static IEnumerable <Tuple <ICell, ICell> > HandleCellPairs(SolvingContext context, IEnumerable <Tuple <ICell, ICell> > combinations, ICellGroup cellGroup) { foreach (var combination in combinations) { if (combination.Item1 == null || combination.Item2 == null) { break; } var firstFields = combination.Item1.GetCandidates().ToList(); var secondFields = combination.Item2.GetCandidates().ToList(); if (firstFields.Count != 2 || secondFields.Count != 2 || !firstFields.SequenceEqual(secondFields)) { continue; } RemoveCandidates(context, cellGroup, combination); yield return(combination); } }
/// <summary> /// Checks if an <see cref="ICellGroup"/> contains a specific number /// </summary> /// <param name="number">The number to look for </param> /// <returns> True if the group contains the number </returns> public static bool Contains(this ICellGroup line, uint number) { return(line.Cells.Any(x => x.Value == number)); }