// In a colunm, row, or group, if a set of numbers it wholly consumed by a group of matching cells, i.e. the number of cells // matches the number of possible answers per cell, then those answers cannot be used by a less restrictive cell in any of // the matching cells' cellsets private static void ReduceUsingMatchingCells(Cell[] cellSet) { var cellGroups = cellSet .Where(c => c.PossibleAnswers.Count > 1) .GroupBy(c => c.PossibleAnswerHash) .Where(g => g.First().PossibleAnswers.Count == g.Count()); foreach (var cellGroup in cellGroups) { var answers = cellGroup.First().PossibleAnswers; var groupCells = string.Join(", ", cellGroup.Select(c => string.Format("({0}, {1})", c.Column, c.Row))); foreach (var cell in cellGroup) { var cellsToReduce = cell.OtherColumnCells .Union(cell.OtherRowCells) .Union(cell.OtherGroupCells) .Except(cellGroup) .Select(c => new { c.Row, c.Column, c.PossibleAnswers, AnswersToRemove = c.PossibleAnswers.Where(answers.Contains).ToArray() }) .Where(c => c.AnswersToRemove.Length > 0); foreach (var reduceCell in cellsToReduce) { var toRemoveString = string.Join(", ", reduceCell.AnswersToRemove.Select(a => ((int)a + 1).ToString(CultureInfo.InvariantCulture))); System.Console.WriteLine(string.Format("Captive group {3} removes [{0}] from cell ({1}, {2})", toRemoveString, reduceCell.Column, reduceCell.Row, groupCells)); cell.PossibleAnswers.RemoveAll(reduceCell.AnswersToRemove.Contains); } } } }
private Puzzle CloneAndGuess(Puzzle puzzle, Cell cellToGuess, Number guess) { var clone = new Puzzle(puzzle); clone.Columns[cellToGuess.Column][cellToGuess.Row].SetAnswer(guess); RemoveAnsweredFromOtherPossibles(clone); return clone; }
private static void SetOnlyPossibleCell(Cell[] cellSet) { foreach (var number in Validations.AllNumbers) { var possibleCells = cellSet.Where(c => c.PossibleAnswers.Contains(number)).ToArray(); if (possibleCells.Length == 1) { possibleCells[0].SetAnswer(number); } } }
private void SetOnlyPossibleCell(Cell[] cellSet, string name) { foreach (var number in Validations.AllNumbers) { var thisNumber = number; var possibleCells = cellSet.Where(c => c.PossibleAnswers.Contains(thisNumber)).ToArray(); if (possibleCells.Length == 1 && possibleCells[0].PossibleAnswers.Count > 1) { var cell = possibleCells[0]; WriteLine(string.Format("{0} set to {1} for only possible cell in {2}", cell.Coordinates, (int)thisNumber, name)); cell.SetAnswer(thisNumber); } } }
// In a colunm, row, or group, if a set of numbers it wholly consumed by a group of matching cells, i.e. the number of cells // matches the number of possible answers per cell, then those answers cannot be used by a less restrictive cell in any of // the matching cells' cellsets private void ReduceUsingMatchingCells(Cell[] cellSet, string name) { var cellGroups = cellSet .Where(c => c.PossibleAnswers.Count > 1) .GroupBy(c => c.PossibleAnswerHash) .Where(g => g.First().PossibleAnswers.Count == g.Count()); foreach (var cellGroup in cellGroups) { var answers = cellGroup.First().PossibleAnswers; var groupCells = string.Join(", ", cellGroup.Select(c => string.Format("({0}, {1})", c.Column + 1, c.Row + 1))); var answerStrings = string.Join(", ", answers.Select(a => ((int)a).ToString(CultureInfo.InvariantCulture))); var cellsToReduce = cellSet .Except(cellGroup) .Select(c => new { c.Coordinates, c.PossibleAnswers, AnswersToRemove = c.PossibleAnswers.Where(answers.Contains).ToArray() }) .Where(c => c.AnswersToRemove.Length > 0); foreach (var reduceCell in cellsToReduce) { var toRemoveString = string.Join(", ", reduceCell.AnswersToRemove.Select(a => ((int)a).ToString(CultureInfo.InvariantCulture))); WriteLine(string.Format("{0} looses [{1}] by maching group {2} [{3}] in {4}", reduceCell.Coordinates, toRemoveString, groupCells, answerStrings, name)); reduceCell.PossibleAnswers.RemoveAll(reduceCell.AnswersToRemove.Contains); OnReduced(null); } } }
public static bool HasNoPossibleAnswers(Cell arg) { return !arg.PossibleAnswers.Any(); }