public Puzzle Solve(Puzzle puzzle, SolverContext context, List <CellRange> anchors) { bool wordsInserted; do { wordsInserted = false; foreach (var range in puzzle.PartiallyFilledCellRanges.ToList()) { var words = puzzle.Words.Where(w => puzzle.Matches(range, w)); if (!words.Any()) { return(null); } if (words.Count() == 1) { puzzle = puzzle.SetWord(range, words.Single()); wordsInserted = true; } } } while (wordsInserted); var part = puzzle.PartiallyFilledCellRanges.ToList(); List <Tuple <string, CellRange> > pairs = new List <Tuple <string, CellRange> >(); foreach (var word in puzzle.Words) { foreach (var cellRange in part.Where(p => puzzle.Matches(p, word))) { pairs.Add(Tuple.Create(word, cellRange)); } } foreach (var pair in OrderPairs(pairs, anchors)) { var word = pair.Item1; var range = pair.Item2; context.count++; var candidatePuzzle = puzzle.SetWord(range, word); if (candidatePuzzle == null) { continue; } if (context.AlreadyTried(candidatePuzzle)) { continue; } //var words = candidatePuzzle.Words.ToArray(); //var ranges = candidatePuzzle.PartiallyFilledCellRanges.Concat(candidatePuzzle.UnfilledCellRanges).ToArray(); //if (words.Length != ranges.Length) //{ // continue; //} if (context.count % 10 == 0) { Console.Clear(); Console.WriteLine(candidatePuzzle); Console.WriteLine($"Solving C:{context.count} D:{context.depth} T:{context.TriedCount}"); } //foreach (var anchor in anchors) //{ // var cnt = part.Where(p => p.Overlaps(anchor)).Count(); // Console.WriteLine($"{anchor}: {cnt}"); //} //if (context.count > 50000) //{ // Console.ReadKey(); //} context.depth++; var solved = Solve(candidatePuzzle, context, anchors.Concat(new[] { range }).ToList()); context.depth--; if (solved != null) { return(solved); } if (candidatePuzzle.IsPartialSolution()) { Console.WriteLine("Rejected partial solution:"); Console.WriteLine(candidatePuzzle); candidatePuzzle.IsPartialSolution(); Environment.Exit(-1); } context.AddTried(candidatePuzzle.CopyOfCells()); } // No solution is possible return(null); }