Example #1
0
        private static void Solve(PuzzleSetup puzzleSetup)
        {
            IncorrectGuesses = new Dictionary <int, Candidates>();
            for (var i = 0; i < 81; i++)
            {
                IncorrectGuesses[i] = Candidates.None;
            }
            var puzzle = new PuzzleGrid(puzzleSetup);

            foreach (var cell in puzzle.Cells)
            {
                cell.Initialize();
            }
            puzzle.Print();
            bool solved;
            var  result = Solve(puzzle, out solved);

            Console.WriteLine(solved ? "Solved!" : "Failed");
            result.Print();
        }
Example #2
0
        private static PuzzleGrid Solve(PuzzleGrid puzzle, out bool solved)
        {
            var anyChanges = false;

            do
            {
                anyChanges = false;
                var unsolvedCells = puzzle.Cells
                                    .Where(c => !c.Solution.HasValue)
                                    .ToArray();
                if (!unsolvedCells.Any())
                {
                    solved = true;
                    return(puzzle);
                }
                if (anyChanges |= unsolvedCells.TrySingleCandidateSolve())
                {
                    Console.WriteLine("Single candidate.");
                    continue;
                }
                if (anyChanges |= unsolvedCells.TryUniqueCandidateSolve())
                {
                    Console.WriteLine("Unique candidate.");
                    continue;
                }
                if (anyChanges |= puzzle.Boxes.TryCandidateLineElimination())
                {
                    Console.WriteLine("Candidate line.");
                    continue;
                }
                if (anyChanges |= puzzle.AllUnits.TryNakedPairElimination())
                {
                    Console.WriteLine("Naked pair.");
                    continue;
                }
                if (anyChanges |= puzzle.AllUnits.TryNakedTripleElimination())
                {
                    Console.WriteLine("Naked triple.");
                    continue;
                }
                if (anyChanges |= puzzle.AllUnits.TryNakedQuadElimination())
                {
                    Console.WriteLine("Naked quadruple.");
                    continue;
                }
                if (anyChanges |= puzzle.AllUnits.TryNakedQuintElimination())
                {
                    Console.WriteLine("Naked quintuplet.");
                    continue;
                }
                if (anyChanges |= puzzle.TryDoublePairElimination())
                {
                    Console.WriteLine("Double pair.");
                    continue;
                }
                if (anyChanges |= puzzle.TryClosedLoopCandidateElimination(loopScale: 2))
                {
                    Console.WriteLine("X-Wing.");
                    continue;
                }
                if (anyChanges |= puzzle.TryClosedLoopCandidateElimination(loopScale: 3))
                {
                    Console.WriteLine("Swordfish.");
                    continue;
                }
                if (anyChanges |= puzzle.TryClosedLoopCandidateElimination(loopScale: 4))
                {
                    Console.WriteLine("Closed loop, scale 4.");
                    continue;
                }
                if (anyChanges |= puzzle.TryClosedLoopCandidateElimination(loopScale: 5))
                {
                    Console.WriteLine("Closed loop, scale 5.");
                    continue;
                }
                //var mostSolvedCellIdx = unsolvedCells
                //	.OrderBy(c => c.Candidates.CountExcluding(IncorrectGuesses[c.Idx]))
                //	.First()
                //	.Idx;
                //var clone = puzzle.DeepClone();
                //var cell = clone.Cells[mostSolvedCellIdx];
                //var nextGuess = cell.Candidates.FirstOrDefaultExcluding(IncorrectGuesses[mostSolvedCellIdx]);
                //if(nextGuess == Candidates.None)
                //{
                //	throw new InvalidOperationException($"No remaining guesses for cell {mostSolvedCellIdx}");
                //}
                //Console.WriteLine($"Guessing {nextGuess} on cell {cell.Idx}");
                //cell.Solve(nextGuess);
                //try
                //{
                //	Solve(clone, out solved);
                //	if (solved)
                //	{
                //		return clone;
                //	}
                //	anyChanges = true;
                //}
                //catch (InvalidSolutionException)
                //{
                //	Console.WriteLine("Incorrect guess.");
                //	IncorrectGuesses[mostSolvedCellIdx] |= nextGuess;
                //	solved = false;
                //	return clone;
                //}
            }while (anyChanges);
            solved = false;
            return(puzzle);
        }
Example #3
0
        public static bool ClosedLoop(
            this PuzzleGrid puzzle,
            byte loopScale,
            Func <PuzzleGrid, Cell[][]> getUnits,           // row or cols
            Func <PuzzleGrid, Cell[][]> getOtherUnits,      // cols or rows
            Func <Cell, byte> getIdxInOtherUnit)            // RowIdx or ColIdx
        {
            var anyChanges = false;

            foreach (var candidate in CandidatesUtil.ALL)
            {
                var indiciesOfCandidateWithinUnits = new Dictionary <int, Index>();
                for (var i = 0; i < 9; i++)
                {
                    Index indicies;
                    if (GetIndiciesOfCandidateIfOccuringTwice(getUnits(puzzle)[i], candidate, out indicies))
                    {
                        indiciesOfCandidateWithinUnits.Add(i, indicies);
                    }
                }
                if (indiciesOfCandidateWithinUnits.Count < loopScale)
                {
                    continue;
                }
                var unitCount     = indiciesOfCandidateWithinUnits.Count;
                var unitIdxGroups = indiciesOfCandidateWithinUnits.Select(i => i.Key).ToList().UniqueCombinations(loopScale);
                foreach (var unitIdxGroup in unitIdxGroups)
                {
                    var units = indiciesOfCandidateWithinUnits
                                .Where(i => unitIdxGroup.Contains(i.Key))
                                .ToArray();
                    var indicies = Index.None;
                    foreach (var index in units.Select(u => u.Value))
                    {
                        indicies |= index;
                    }
                    if (!indicies.HasNumberOfIndicies(loopScale))
                    {
                        continue;
                    }
                    foreach (var unitIndexAndCellIndiciesPair in indiciesOfCandidateWithinUnits)
                    {
                        var unitIdx       = unitIndexAndCellIndiciesPair.Key;
                        var indexesInUnit = unitIndexAndCellIndiciesPair.Value.GetValues()
                                            .Select(idx => IndexUtil.INDEX_BYTE_MAP[idx])
                                            .ToArray();
                        var cell1 = getUnits(puzzle)[unitIdx][indexesInUnit[0]];
                        var cell2 = getUnits(puzzle)[unitIdx][indexesInUnit[1]];

                        foreach (var cell in getOtherUnits(puzzle)[getIdxInOtherUnit(cell1)])
                        {
                            if (cell == cell1 || cell == cell2)
                            {
                                continue;
                            }
                            anyChanges |= cell.RemoveCandidates(candidate);
                        }
                    }
                }
            }
            return(anyChanges);
        }