void UpdateUnusableNumbersForCageNeighbours(Cage cage) { if (cage.SpansSingleRow || cage.SpansSingleColumn) { if (cage.SpansSingleRow) AddUnusableNumbersToCells(_kenKenGrid.Row(cage.Cells.First().Row).Where(cell => !cage.Cells.Contains(cell)), cage.CommonValuesInCellPossibilities); if (cage.SpansSingleColumn) AddUnusableNumbersToCells(_kenKenGrid.Column(cage.Cells.First().Column).Where(cell => !cage.Cells.Contains(cell)), cage.CommonValuesInCellPossibilities); } else { // => Cage spans multiple rows or columns // => Deleting invalid numbers from multicage cell neighbours is handled as a different // step because it is too complex as a side-effect of another step } }
void MarkCageAsPartiallSolved(Cage cage, IEnumerable<Possibility> possibilities) { if (possibilities.Count() < 1) throw new ArgumentException("List of possibilities cannot be empty"); cage.AddPossibilities(possibilities); UpdateUnusableNumbersForCageNeighbours(cage); }
List<Permutation> FindValidPermutationsForPossibility(Cage cage, Possibility possibility) { List<Permutation> validPerms = new List<Permutation>(); List<Permutation> perms = Helper.GetUniquePermutation(possibility.ToList<int>()); foreach (var permutation in perms) { Cage copyCage = cage.DeepCopy(); bool isPermutationValid = true; for (int i = 0; i < copyCage.Cells.Count; i++) { if (!copyCage.Cells[i].IsValueFeasible(permutation[i])) { isPermutationValid = false; break; } else { MarkCellAsSolved(copyCage.Cells[i], permutation[i], copyCage.Cells); } } if (isPermutationValid) validPerms.Add(permutation); } return validPerms; }
List<Permutation> FindValidPermutationsForCagePossibilities(Cage cage) { List<Permutation> validPerms = new List<Permutation>(); cage.Possibilities.ForEach(possibility => validPerms.AddRange(FindValidPermutationsForPossibility(cage, possibility))); return validPerms; }
List<Possibility> EliminateAlreadyUsedNumbersFromPossibilities(IEnumerable<Possibility> possibilities, Cage cage) { List<int> unusableNumbers = cage.CommonUnusableNumbersInCells; List<Possibility> filteredPossibilities = possibilities.Where(possibility => !possibility.ContainsAny(unusableNumbers)).ToList(); List<Possibility> invalidPossibilities = possibilities.Where(possibility => possibility.ContainsAny(unusableNumbers)).ToList(); if (invalidPossibilities.Count > 0) { Step localStepAction = new Step(); localStepAction.InvalidPossibilities = invalidPossibilities; _log.LogStep("DiscardPossibilities", localStepAction); } filteredPossibilities = filteredPossibilities.FindAll(possibility => { Cell found = cage.Cells.FirstOrDefault(cell => possibility.ContainsOnly(cell.UnusableNumbers)); if (found != null) { Step localStepAction = new Step(); localStepAction.FoundCell = found; localStepAction.InvalidPossibilities = new List<Possibility>() { possibility }; _log.LogStep("DiscardPossibilityForCell", localStepAction); return false; } else { return true; } }); return filteredPossibilities; }
void DeleteCagePossibilities(Cage cage, List<Possibility> invalidPossibilities) { cage.DeletePossibilities(invalidPossibilities); UpdateUnusableNumbersForCageNeighbours(cage); }