<commit_before>define(["Cell", "process/Move", "process/Strategy"],
    function(Cell, Move, Strategy)
    {
        "use strict";

        function SudokuSolver(strategiesIn)
        {
            // strategies optional.

            var strategies = (strategiesIn !== undefined ? strategiesIn : [Strategy.NakedSingle, Strategy.NakedPair]);

            this.strategies = function()
            {
                return strategies;
            };
        }

        SudokuSolver.prototype.forwardSearch = function(puzzle, solver)
        {
            InputValidator.validateNotNull("puzzle", puzzle);
            InputValidator.validateNotNull("solver", solver);

            // Try two candidate cell values.
            var indices = puzzle.findCellsWithCandidateLength(2);
            var answer;

            for (var i = 0; i < indices.length && answer === undefined; i++)
            {
                var index = indices[i];
                var cell = puzzle.get(index);
                var candidates = cell.candidates();

                for (var j = 0; j < candidates.size && answer === undefined; j++)
                {
                    var candidate = candidates.get(j);
                    var puzzleClone = puzzle.withCell(index, new Cell.Value(candidate));
                    puzzleClone = puzzleClone.adjustCandidates();
                    puzzleClone = solver.solve(puzzleClone);

                    if (solver.isDone(puzzleClone))
                    {
                        answer = new Move.SetCellValue(puzzle, index, candidate, "forward search");
                    }
                }
            }

            return answer;
        };

        SudokuSolver.prototype.getMove = function(puzzle)
        {
            InputValidator.validateNotNull("puzzle", puzzle);

            var answer;
            var strategies = this.strategies();

            for (var i = 0; i < strategies.length && answer === undefined; i++)
            {
                var strategy = strategies[i];
                answer = strategy.getMove(puzzle);
            }

            if (answer === undefined)
            {
                answer = this.forwardSearch(puzzle, this);
            }

            return answer;
        };

        SudokuSolver.prototype.isDone = function(puzzle)
        {
            InputValidator.validateNotNull("puzzle", puzzle);

            for (var i = 0; i < puzzle.cells().size; i++)
            {
                var cell = puzzle.get(i);

                if (cell.isCandidates === true)
                {
                    return false;
                }
            }

            return true;
        };

        SudokuSolver.prototype.solve = function(puzzle)
        {
            InputValidator.validateNotNull("puzzle", puzzle);

            LOGGER.trace("solve() start");

            var myPuzzle = puzzle;
            myPuzzle = myPuzzle.adjustCandidates();
            var start = new Date().getTime();
            var maxTries = 81;
            var count = 0;

            while (!this.isDone(myPuzzle) && count < maxTries)
            {
                var move = this.getMove(myPuzzle);

                if (move === undefined)
                {
                    break;
                }

                myPuzzle = move.execute();
                count++;
            }

            LOGGER.time("solve()", start, new Date().getTime());
            LOGGER.trace("solve() end");

            return myPuzzle;
        };

        return SudokuSolver;
    });
<commit_msg>Made the forward search optional.<commit_after>define(["Cell", "process/Move", "process/Strategy"],
    function(Cell, Move, Strategy)
    {
        "use strict";

        function SudokuSolver(useForwardSearchIn, strategiesIn)
        {
            // useForwardSearch optional. default: true
            // strategies optional.

            var useForwardSearch = (useForwardSearchIn !== undefined ? useForwardSearchIn : true);
            var strategies = (strategiesIn !== undefined ? strategiesIn : [Strategy.NakedSingle, Strategy.NakedPair]);

            this.useForwardSearch = function()
            {
                return useForwardSearch;
            };

            this.strategies = function()
            {
                return strategies;
            };
        }

        SudokuSolver.prototype.forwardSearch = function(puzzle)
        {
            InputValidator.validateNotNull("puzzle", puzzle);

            // Try two candidate cell values.
            var indices = puzzle.findCellsWithCandidateLength(2);
            var useForwardSearch = false;
            var solver = new SudokuSolver(useForwardSearch);
            var answer;

            for (var i = 0; i < indices.length && answer === undefined; i++)
            {
                var index = indices[i];
                var cell = puzzle.get(index);
                var candidates = cell.candidates();

                for (var j = 0; j < candidates.size && answer === undefined; j++)
                {
                    var candidate = candidates.get(j);
                    var puzzleClone = puzzle.withCell(index, new Cell.Value(candidate));
                    puzzleClone = puzzleClone.adjustCandidates();
                    puzzleClone = solver.solve(puzzleClone);

                    if (solver.isDone(puzzleClone))
                    {
                        answer = new Move.SetCellValue(puzzle, index, candidate, "forward search");
                    }
                }
            }

            return answer;
        };

        SudokuSolver.prototype.getMove = function(puzzle)
        {
            InputValidator.validateNotNull("puzzle", puzzle);

            var answer;
            var strategies = this.strategies();

            for (var i = 0; i < strategies.length && answer === undefined; i++)
            {
                var strategy = strategies[i];
                answer = strategy.getMove(puzzle);
            }

            if (this.useForwardSearch() && answer === undefined)
            {
                answer = this.forwardSearch(puzzle);
            }

            return answer;
        };

        SudokuSolver.prototype.isDone = function(puzzle)
        {
            InputValidator.validateNotNull("puzzle", puzzle);

            for (var i = 0; i < puzzle.cells().size; i++)
            {
                var cell = puzzle.get(i);

                if (cell.isCandidates === true)
                {
                    return false;
                }
            }

            return true;
        };

        SudokuSolver.prototype.solve = function(puzzle)
        {
            InputValidator.validateNotNull("puzzle", puzzle);

            LOGGER.trace("solve() start");

            var myPuzzle = puzzle;
            myPuzzle = myPuzzle.adjustCandidates();
            var start = new Date().getTime();
            var maxTries = 81;
            var count = 0;

            while (!this.isDone(myPuzzle) && count < maxTries)
            {
                var move = this.getMove(myPuzzle);

                if (move === undefined)
                {
                    break;
                }

                myPuzzle = move.execute();
                count++;
            }

            LOGGER.time("solve()", start, new Date().getTime());
            LOGGER.trace("solve() end");

            return myPuzzle;
        };

        return SudokuSolver;
    });

{'fraction_non_alphanumeric': 0.10511478050745067, 'fraction_numerical': 0.0021479393207141898, 'mean_word_length': 1.342030807922037, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1362281', 'n_tokens_mistral': 1948, 'n_tokens_neox': 1779, 'n_words': 397}