/** * Calculates difficulty of Sudoku puzzle. Returned difficulty level is an average * of number of closed routes while performing recursive steps in order to find solution. * This is multi-threading procedure. * * @param sudokuPuzzle Sudoku puzzle to be rated. * @return If puzzle does not contain an error then difficulty rating is returned. * If puzzle contains obvious error then {@link ErrorCodes#SUDOKUSTORE_CALCULATEPUZZLERATING_PUZZLE_ERROR}. * If puzzle has no solutions then {@link ErrorCodes#SUDOKUSTORE_CALCULATEPUZZLERATING_NO_SOLUTION}. * If solution is non-unique then {@link ErrorCodes#SUDOKUSTORE_CALCULATEPUZZLERATING_NON_UNIQUE_SOLUTION}. */ public static int calculatePuzzleRating(int[,] sudokuPuzzle) { if (checkPuzzle(sudokuPuzzle) == false) return ErrorCodes.SUDOKUSTORE_CALCULATEPUZZLERATING_PUZZLE_ERROR; SudokuSolver s = new SudokuSolver(sudokuPuzzle); int solType = s.checkIfUniqueSolution(); if (solType == SudokuSolver.SOLUTION_NOT_EXISTS) return ErrorCodes.SUDOKUSTORE_CALCULATEPUZZLERATING_NO_SOLUTION; if (solType == SudokuSolver.SOLUTION_NON_UNIQUE) return ErrorCodes.SUDOKUSTORE_CALCULATEPUZZLERATING_NON_UNIQUE_SOLUTION; /* * Multi-threading implementation */ int threadIterNum = RATING_DEF_NUM_OF_ITERATIONS / THREADS_NUMBER; int[,] results = new int[THREADS_NUMBER, threadIterNum]; Runner[] runners = new Runner[THREADS_NUMBER]; Thread[] threads = new Thread[THREADS_NUMBER]; for (int t = 0; t < THREADS_NUMBER; t++) { runners[t] = new Runner(t, threadIterNum, sudokuPuzzle, results); threads[t] = new Thread(runners[t].run); } for (int t = 0; t < THREADS_NUMBER; t++) { threads[t].Start(); } for (int t = 0; t < THREADS_NUMBER; t++) { try { threads[t].Join(); } catch (ThreadInterruptedException e) { Console.WriteLine(e.StackTrace); return ErrorCodes.SUDOKUSTORE_CALCULATEPUZZLERATING_THREADS_JOIN_FAILED; } } int sum = 0; for (int t = 0; t < THREADS_NUMBER; t++) for (int i = 0; i < threadIterNum; i++) sum+=results[t, i]; return sum / (THREADS_NUMBER * threadIterNum); }
/** * Sudoku puzzle generator. * * @return Sudoku puzzle if process finished correctly, otherwise null. */ public int[,] generate() { if (generatorState != GENERATOR_INIT_FINISHED) { generatorState = GENERATOR_GEN_NOT_STARTED; addMessage("(SudokuGenerator) Generation process not started due to incorrect initialization.", MSG_ERROR); return null; } long solvingStartTime = DateTimeX.currentTimeMillis(); generatorState = GENERATOR_GEN_STARTED; addMessage("(SudokuGenerator) Generation process started.", MSG_INFO); if (randomizeFilledCells == true) addMessage("(SudokuGenerator) >>> Will randomize filled cells within cells with the same impact.", MSG_INFO); boardCells = new BoardCell[BOARD_CELLS_NUMBER]; int cellIndex = 0; for (int i = 0; i < BOARD_SIZE; i++) for (int j = 0; j < BOARD_SIZE; j++) { int d = sudokuBoard[i, j]; if (d != CELL_EMPTY) { boardCells[cellIndex] = new BoardCell(i, j, d); cellIndex++; } } int filledCells = cellIndex; for (int i = 0; i < BOARD_SIZE; i++) for (int j = 0; j < BOARD_SIZE; j++) { int d = sudokuBoard[i, j]; if (d == CELL_EMPTY) { boardCells[cellIndex] = new BoardCell(i, j, d); cellIndex++; } } updateDigitsStillFreeCounts(); sortBoardCells(0, filledCells - 1); do { int r = 0; int i = boardCells[r].rowIndex; int j = boardCells[r].colIndex; int d = sudokuBoard[i, j]; sudokuBoard[i, j] = CELL_EMPTY; SudokuSolver s = new SudokuSolver(sudokuBoard); if (s.checkIfUniqueSolution() != SudokuSolver.SOLUTION_UNIQUE) sudokuBoard[i, j] = d; int lastIndex = filledCells - 1; if (r < lastIndex) { BoardCell b1 = boardCells[r]; BoardCell b2 = boardCells[lastIndex]; boardCells[lastIndex] = b1; boardCells[r] = b2; } filledCells--; updateDigitsStillFreeCounts(); if (filledCells > 0) sortBoardCells(0, filledCells - 1); } while (filledCells > 0); long solvingEndTime = DateTimeX.currentTimeMillis(); computingTime = (solvingEndTime - solvingStartTime) / 1000.0; generatorState = GENERATOR_GEN_FINISHED; addMessage("(SudokuGenerator) Generation process finished, computing time: " + computingTime + " s.", MSG_INFO); return sudokuBoard; }
public void run() { for (int i = 0; i < iterNum; i++) { SudokuSolver s = new SudokuSolver(sudokuPuzzle); s.solve(); setTestResult(i, s.getClosedRoutesNumber()); } }
/** * Board initialization method. * @param initBoard Initial board. * @param info The string to pass to the msg builder. */ private void boardInit(int[,] initBoard, String info) { SudokuSolver puzzle; if ((initBoard == null) && (generateRandomBoard == true)) { puzzle = new SudokuSolver(SudokuPuzzles.PUZZLE_EMPTY); puzzle.solve(); if (puzzle.getSolvingState() == SudokuSolver.SOLVING_STATE_SOLVED) { sudokuBoard = puzzle.solvedBoard; addMessage("(SudokuGenerator) Generator initialized using random board (" + info + ").", MSG_INFO); generatorState = GENERATOR_INIT_FINISHED; return; } else { addMessage("(SudokuGenerator) Generator initialization using random board (" + info + ") failed. Board with error?", MSG_ERROR); addMessage(puzzle.getLastErrorMessage(), MSG_ERROR); generatorState = GENERATOR_INIT_FAILED; return; } } if (SudokuStore.checkPuzzle(initBoard) == false) { generatorState = GENERATOR_INIT_FAILED; addMessage("(SudokuGenerator) Generator initialization (" + info + ") failed. Board with error?", MSG_ERROR); return; } if (solveBeforeGeneration == true) { puzzle = new SudokuSolver(initBoard); puzzle.solve(); if (puzzle.getSolvingState() == SudokuSolver.SOLVING_STATE_SOLVED) { sudokuBoard = puzzle.solvedBoard; addMessage("(SudokuGenerator) Generator initialized usign provided board + finding solution (" + info + ").", MSG_INFO); generatorState = GENERATOR_INIT_FINISHED; return; } else { addMessage("(SudokuGenerator) Generator initialization usign provided board + finding solution (" + info + ") failed. Board with error?", MSG_ERROR); addMessage(puzzle.getLastErrorMessage(), MSG_ERROR); generatorState = GENERATOR_INIT_FAILED; return; } } int[,] board = initBoard; puzzle = new SudokuSolver(board); if (puzzle.checkIfUniqueSolution() == SudokuSolver.SOLUTION_UNIQUE) { sudokuBoard = board; addMessage("(SudokuGenerator) Generator initialized usign provided board (" + info + ").", MSG_INFO); generatorState = GENERATOR_INIT_FINISHED; return; } else { addMessage("(SudokuGenerator) Generator initialization usign provided board (" + info + ") failed. Solution not exists or is non unique.", MSG_ERROR); addMessage(puzzle.getLastErrorMessage(), MSG_ERROR); generatorState = GENERATOR_INIT_FAILED; return; } }