diff --git a/apps/plugins/sudoku/sudoku.c b/apps/plugins/sudoku/sudoku.c index 4a7fbd93a8..02615caac1 100644 --- a/apps/plugins/sudoku/sudoku.c +++ b/apps/plugins/sudoku/sudoku.c @@ -286,292 +286,6 @@ static unsigned int cellypos[9]={ #define BLOCK 3 #define SIZE (BLOCK*BLOCK) -#if 0 -/****** Solver routine by Tom Shackell - -Downloaded from: - -http://www-users.cs.york.ac.uk/~shackell/sudoku/Sudoku.html - -Released under GPLv2 - -*/ - -typedef unsigned int Bitset; - -#define true 1 -#define false 0 - -typedef struct _Sudoku { - Bitset table[SIZE][SIZE]; -}Sudoku; - -typedef struct _Stats { - int numTries; - int backTracks; - int numEmpty; - bool solutionFound; -}Stats; - -typedef struct _Options { - bool allSolutions; - bool uniquenessCheck; -}Options; - -void sudoku_init(Sudoku* sud); -void sudoku_set(Sudoku* sud, int x, int y, int num, bool original); -int sudoku_get(Sudoku* sud, int x, int y, bool* original); - -#define BIT(n) ((Bitset)BIT_N(n)) -#define BIT_TEST(v,n) ((((Bitset)v) & BIT(n)) != 0) -#define BIT_CLEAR(v,n) (v) &= ~BIT(n) -#define MARK_BIT BIT(0) -#define ORIGINAL_BIT BIT(SIZE+1) - -#define ALL_BITS (BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) | BIT(6) | BIT(7) | BIT(8) | BIT(9)) - -/* initialize a sudoku problem, should be called before using set or get */ -void sudoku_init(Sudoku* sud) -{ - int y, x; - for (y = 0; y < SIZE; y++){ - for (x = 0; x < SIZE; x++){ - sud->table[x][y] = ALL_BITS; - } - } -} - -/* set the number at a particular x and y column */ -void sudoku_set(Sudoku* sud, int x, int y, int num, bool original) -{ - int i, j; - int bx, by; - Bitset orig; - - /* clear the row and columns */ - for (i = 0; i < SIZE; i++){ - BIT_CLEAR(sud->table[i][y], num); - BIT_CLEAR(sud->table[x][i], num); - } - /* clear the block */ - bx = x - (x % BLOCK); - by = y - (y % BLOCK); - for (i = 0; i < BLOCK; i++){ - for (j = 0; j < BLOCK; j++){ - BIT_CLEAR(sud->table[bx+j][by+i], num); - } - } - /* mark the table */ - orig = original ? ORIGINAL_BIT : 0; - sud->table[x][y] = BIT(num) | MARK_BIT | orig; -} - -/* get the number at a particular x and y column, if this - is not unique return 0 */ -int sudoku_get(Sudoku* sud, int x, int y, bool* original) -{ - Bitset val = sud->table[x][y]; - int result = 0; - int i; - - if (original) { - *original = val & ORIGINAL_BIT; - } - for (i = 1; i <= SIZE; i++){ - if (BIT_TEST(val, i)){ - if (result != 0){ - return 0; - } - result = i; - } - } - return result; -} - -/* returns true if this is a valid problem, this is necessary because the input - problem might be degenerate which breaks the solver algorithm. */ -static bool is_valid(const Sudoku* sud) -{ - int x, y; - - for (y = 0; y < SIZE; y++){ - for (x = 0; x < SIZE; x++){ - if ((sud->table[x][y] & ALL_BITS) == 0){ - return false; - } - } - } - return true; -} - -/* scan the table for the most constrained item, giving all it's options, sets - the best x and y coordinates, the number of options and the options for - that coordinate and returns true if the puzzle is finished */ -static bool scan(const Sudoku* sud, int* rX, int* rY, int *num, int* options) -{ - int x, y, i, j; - int bestCount = SIZE+1; - Bitset val; - bool allMarked = true; - - for (y = 0; y < SIZE; y++){ - for (x = 0; x < SIZE; x++){ - Bitset val = sud->table[x][y]; - int i; - int count = 0; - - if (val & MARK_BIT) { - /* already set */ - continue; - } - allMarked = false; - for (i = 1; i <= SIZE; i++){ - if (BIT_TEST(val, i)){ - count++; - } - } - if (count < bestCount){ - bestCount = count; - *rX = x; - *rY = y; - if (count == 0){ - /* can't possibly be beaten */ - *num = 0; - return false; - } - } - } - } - /* now copy into options */ - *num = bestCount; - val = sud->table[*rX][*rY]; - for (i = 1, j = 0; i <= SIZE; i++){ - if (BIT_TEST(val, i)){ - options[j++] = i; - } - } - return allMarked; -} - -static bool solve(Sudoku* sud, Stats* stats, const Options* options); - -/* try a particular option and return true if that gives a solution or false - if it doesn't, restores board on backtracking */ -static bool spawn_option(Sudoku* sud, Stats* stats, const Options* options, - int x, int y, int num) -{ - Sudoku copy; - - rb->memcpy(©,sud,sizeof(Sudoku)); - sudoku_set(©, x, y, num, false); - stats->numTries += 1; - if (solve(©, stats, options)){ - if (!options->allSolutions && stats->solutionFound){ - rb->memcpy(sud,©,sizeof(Sudoku)); - } - return true; - }else{ - stats->backTracks++; - } - return false; -} - -/* solve a sudoku problem, returns true if there is a solution and false - otherwise. stats is used to track statisticss */ -static bool solve(Sudoku* sud, Stats* stats, const Options* options) -{ - while (true){ - int x = 0; - int y = 0; - int i, num; - int places[SIZE]; - - if (scan(sud, &x, &y, &num, places)){ - /* a solution was found! */ - if (options->uniquenessCheck && stats->solutionFound){ - /*printf("\n\t... But the solution is not unique!\n"); */ - return true; - } - stats->solutionFound = true; - if (options->allSolutions || options->uniquenessCheck){ - /*printf("\n\tSolution after %d iterations\n", stats->numTries); */ - /*sudoku_print(sud); */ - return false; - } - else{ - return true; - } - } - if (num == 0){ - /* can't be satisfied */ - return false; - } - /* try all the places (except the last one) */ - for (i = 0; i < num-1; i++){ - if (spawn_option(sud, stats, options, x, y, places[i])){ - /* solution found! */ - if (!options->allSolutions && stats->solutionFound){ - return true; - } - } - } - /* take the last place ourself */ - stats->numTries += 1; - sudoku_set(sud, x, y, places[num-1], false); - } -} - -/******** END OF IMPORTED CODE */ - - -/* A wrapper function between the Sudoku plugin and the above solver code */ -void sudoku_solve(struct sudoku_state_t* state) -{ - bool ret; - Stats stats; - Options options; - Sudoku sud; - bool original; - int r,c; - - /* Initialise the parameters */ - sudoku_init(&sud); - rb->memset(&stats,0,sizeof(stats)); - options.allSolutions=false; - options.uniquenessCheck=false; - - /* Convert Rockbox format into format for solver */ - for (r=0;r<9;r++) { - for (c=0;c<9;c++) { - if (state->startboard[r][c]!='0') { - sudoku_set(&sud, c, r, state->startboard[r][c]-'0', true); - } - } - } - - /* need to check for degenerate input problems ... */ - if (is_valid(&sud)){ - ret = solve(&sud, &stats, &options); - } else { - ret = false; - } - - if (ret) { - /* Populate the board with the solution. */ - for (r=0;r<9;r++) { - for (c=0;c<9;c++) { - state->currentboard[r][c]='0'+ - sudoku_get(&sud, c, r, &original); - } - } - } else { - rb->splash(HZ*2, "Solve failed"); - } - - return; -} -#endif /* 0 */ - void sudoku_solve(struct sudoku_state_t* state) { bool ret = sudoku_solve_board(state);