A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 1189 lines 31 kB view raw
1/* sudoku.c - sudoku game 2 * 3 * Writing a fun Su-Do-Ku game has turned out to be a difficult exercise. 4 * The biggest difficulty is keeping the game fun - and this means allowing 5 * the user to make mistakes. The game is not much fun if it prevents the 6 * user from making moves, or if it informs them of an incorrect move. 7 * With movement constraints, the 'game' is little more than an automated 8 * solver (and no fun at all). 9 * 10 * Another challenge is generating good puzzles that are entertaining to 11 * solve. It is certainly true that there is an art to creating good 12 * Su-Do-Ku puzzles, and that good hand generated puzzles are more 13 * entertaining than many computer generated puzzles - I just hope that 14 * the algorithm implemented here provides fun puzzles. It is an area 15 * that needs work. The puzzle classification is very simple, and could 16 * also do with work. Finally, understanding the automatically generated 17 * hints is sometimes more work than solving the puzzle - a better, and 18 * more human friendly, mechanism is needed. 19 * 20 * Comments, suggestions, and contributions are always welcome - send email 21 * to: mike 'at' laurasia.com.au. Note that this code assumes a single 22 * threaded process, makes extensive use of global variables, and has 23 * not been written to be reused in other applications. The code makes no 24 * use of dynamic memory allocation, and hence, requires no heap. It should 25 * also run with minimal stack space. 26 * 27 * This code and accompanying files have been placed into the public domain 28 * by Michael Kennett, July 2005. It is provided without any warranty 29 * whatsoever, and in no event shall Michael Kennett be liable for 30 * any damages of any kind, however caused, arising from this software. 31 */ 32 33#include "plugin.h" 34 35#include "sudoku.h" 36#include "templates.h" 37#include "generator.h" 38 39#define assert(x) 40 41/* Common state encoding in a 32-bit integer: 42 * bits 0-6 index 43 * 7-15 state [bit high signals digits not possible] 44 * 16-19 digit 45 * 20 fixed [set if digit initially fixed] 46 * 21 choice [set if solver chose this digit] 47 * 22 ignore [set if ignored by reapply()] 48 * 23 unused 49 * 24-26 hint 50 * 27-31 unused 51 */ 52#define INDEX_MASK 0x0000007f 53#define GET_INDEX(val) (INDEX_MASK&(val)) 54#define SET_INDEX(val) (val) 55 56#define STATE_MASK 0x0000ff80 57#define STATE_SHIFT (7-1) /* digits 1..9 */ 58#define DIGIT_STATE(digit) BIT_N(STATE_SHIFT+(digit)) 59 60#define DIGIT_MASK 0x000f0000 61#define DIGIT_SHIFT 16 62#define GET_DIGIT(val) (((val)&DIGIT_MASK)>>(DIGIT_SHIFT)) 63#define SET_DIGIT(val) ((val)<<(DIGIT_SHIFT)) 64 65#define FIXED 0x00100000 66#define CHOICE 0x00200000 67#define IGNORED 0x00400000 68 69/* Hint codes (c.f. singles(), pairs(), findmoves()) */ 70#define HINT_ROW 0x01000000 71#define HINT_COLUMN 0x02000000 72#define HINT_BLOCK 0x04000000 73 74/* For a general board it may be necessary to do backtracking (i.e. to 75 * rewind the board to an earlier state), and make choices during the 76 * solution process. This can be implemented naturally using recursion, 77 * but it is more efficient to maintain a single board. 78 */ 79static int board[ 81 ]; 80 81/* Addressing board elements: linear array 0..80 */ 82#define ROW(idx) ((idx)/9) 83#define COLUMN(idx) ((idx)%9) 84#define BLOCK(idx) (3*(ROW(idx)/3)+(COLUMN(idx)/3)) 85#define INDEX(row,col) (9*(row)+(col)) 86 87/* Blocks indexed 0..9 */ 88#define IDX_BLOCK(row,col) (3*((row)/3)+((col)/3)) 89#define TOP_LEFT(block) (INDEX(block/3,block%3)) 90 91/* Board state */ 92#define STATE(idx) ((board[idx])&STATE_MASK) 93#define DIGIT(idx) (GET_DIGIT(board[idx])) 94#define HINT(idx) ((board[idx])&HINT_MASK) 95#define IS_EMPTY(idx) (0 == DIGIT(idx)) 96#define DISALLOWED(idx,digit) ((board[idx])&DIGIT_STATE(digit)) 97#define IS_FIXED(idx) (board[idx]&FIXED) 98 99/* Record move history, and maintain a counter for the current 100 * move number. Concessions are made for the user interface, and 101 * allow digit 0 to indicate clearing a square. The move history 102 * is used to support 'undo's for the user interface, and hence 103 * is larger than required - there is sufficient space to solve 104 * the puzzle, undo every move, and then redo the puzzle - and 105 * if the user requires more space, then the full history will be 106 * lost. 107 */ 108static int idx_history; 109static int history[ 3 * 81 ]; 110 111/* Possible moves for a given board (c.f. fillmoves()). 112 * Also used by choice() when the deterministic solver has failed, 113 * and for calculating user hints. The number of hints is stored 114 * in num_hints, or -1 if no hints calculated. The number of hints 115 * requested by the user since their last move is stored in req_hints; 116 * if the user keeps requesting hints, start giving more information. 117 * Finally, record the last hint issued to the user; attempt to give 118 * different hints each time. 119 */ 120static int idx_possible; 121static int possible[ 81 ]; 122 123static int pass; /* count # passes of deterministic solver */ 124 125/* Support for template file */ 126static int tmplt[ 81 ]; /* Template indices */ 127static int len_tmplt; /* Number of template indices */ 128 129/* Reset global state */ 130static 131void 132reset( void ) 133{ 134 rb->memset( board, 0x00, sizeof( board ) ); 135 rb->memset( history, 0x00, sizeof( history ) ); 136 idx_history = 0; 137 pass = 0; 138} 139 140/* Management of the move history - compression */ 141static 142void 143compress( int limit ) 144{ 145 int i, j; 146 for( i = j = 0 ; i < idx_history && j < limit ; ++i ) 147 if( !( history[ i ] & IGNORED ) ) 148 history[ j++ ] = history[ i ]; 149 for( ; i < idx_history ; ++i ) 150 history[ j++ ] = history[ i ]; 151 idx_history = j; 152} 153 154/* Management of the move history - adding a move */ 155static 156void 157add_move( int idx, int digit, int choice ) 158{ 159 int i; 160 161 if( sizeof( history ) / sizeof( int ) == idx_history ) 162 compress( 81 ); 163 164 /* Never ignore the last move */ 165 history[ idx_history++ ] = SET_INDEX( idx ) | SET_DIGIT( digit ) | choice; 166 167 /* Ignore all previous references to idx */ 168 for( i = idx_history - 2 ; 0 <= i ; --i ) 169 if( GET_INDEX( history[ i ] ) == idx ) 170 { 171 history[ i ] |= IGNORED; 172 break; 173 } 174} 175 176/* Iteration over rows/columns/blocks handled by specialised code. 177 * Each function returns a block index - call must manage element/idx. 178 */ 179static 180int 181idx_row( int el, int idx ) /* Index within a row */ 182{ 183 return INDEX( el, idx ); 184} 185 186static 187int 188idx_column( int el, int idx ) /* Index within a column */ 189{ 190 return INDEX( idx, el ); 191} 192 193static 194int 195idx_block( int el, int idx ) /* Index within a block */ 196{ 197 return INDEX( 3 * ( el / 3 ) + idx / 3, 3 * ( el % 3 ) + idx % 3 ); 198} 199 200/* Update board state after setting a digit (clearing not handled) 201 */ 202static 203void 204update( int idx ) 205{ 206 const int row = ROW( idx ); 207 const int col = COLUMN( idx ); 208 const int block = IDX_BLOCK( row, col ); 209 const int mask = DIGIT_STATE( DIGIT( idx ) ); 210 int i; 211 212 board[ idx ] |= STATE_MASK; /* filled - no choice possible */ 213 214 /* Digit cannot appear in row, column or block */ 215 for( i = 0 ; i < 9 ; ++i ) 216 { 217 board[ idx_row( row, i ) ] |= mask; 218 board[ idx_column( col, i ) ] |= mask; 219 board[ idx_block( block, i ) ] |= mask; 220 } 221} 222 223/* Refresh board state, given move history. Note that this can yield 224 * an incorrect state if the user has made errors - return -1 if an 225 * incorrect state is generated; else return 0 for a correct state. 226 */ 227static 228int 229reapply( void ) 230{ 231 int digit, idx, j; 232 int allok = 0; 233 rb->memset( board, 0x00, sizeof( board ) ); 234 for( j = 0 ; j < idx_history ; ++j ) 235 if( !( history[ j ] & IGNORED ) && 0 != GET_DIGIT( history[ j ] ) ) 236 { 237 idx = GET_INDEX( history[ j ] ); 238 digit = GET_DIGIT( history[ j ] ); 239 if( !IS_EMPTY( idx ) || DISALLOWED( idx, digit ) ) 240 allok = -1; 241 board[ idx ] = SET_DIGIT( digit ); 242 if( history[ j ] & FIXED ) 243 board[ idx ] |= FIXED; 244 update( idx ); 245 } 246 return allok; 247} 248 249/* Clear moves, leaving fixed squares 250 */ 251static 252void 253clear_moves( void ) 254{ 255 for( idx_history = 0 ; history[ idx_history ] & FIXED ; ++idx_history ) 256 ; 257 reapply( ); 258} 259 260static int digits[ 9 ]; /* # digits expressed in element square */ 261static int counts[ 9 ]; /* Count of digits (c.f. count_set_digits()) */ 262 263/* Count # set bits (within STATE_MASK) */ 264static 265int 266numset( int mask ) 267{ 268 int i, n = 0; 269 for( i = STATE_SHIFT + 1 ; i <= STATE_SHIFT + 9 ; ++i ) 270 if( mask & BIT_N(i) ) 271 ++n; 272 else 273 ++counts[ i - STATE_SHIFT - 1 ]; 274 return n; 275} 276 277static 278void 279count_set_digits( int el, int (*idx_fn)( int, int ) ) 280{ 281 int i; 282 rb->memset( counts, 0x00, sizeof( counts ) ); 283 for( i = 0 ; i < 9 ; ++i ) 284 digits[ i ] = numset( board[ (*idx_fn)( el, i ) ] ); 285} 286 287/* Fill square with given digit, and update state. 288 * Returns 0 on success, else -1 on error (i.e. invalid fill) 289 */ 290static 291int 292fill( int idx, int digit ) 293{ 294 assert( 0 != digit ); 295 296 if( !IS_EMPTY( idx ) ) 297 return ( DIGIT( idx ) == digit ) ? 0 : -1; 298 299 if( DISALLOWED( idx, digit ) ) 300 return -1; 301 302 board[ idx ] = SET_DIGIT( digit ); 303 update( idx ); 304 add_move( idx, digit, 0 ); 305 306 return 0; 307} 308 309/* Find all squares with a single digit allowed -- do not mutate board */ 310static 311void 312singles( int el, int (*idx_fn)( int, int ), int hintcode ) 313{ 314 int i, j, idx; 315 316 count_set_digits( el, idx_fn ); 317 318 for( i = 0 ; i < 9 ; ++i ) 319 { 320 if( 1 == counts[ i ] ) 321 { 322 /* Digit 'i+1' appears just once in the element */ 323 for( j = 0 ; j < 9 ; ++j ) 324 { 325 idx = (*idx_fn)( el, j ); 326 if( !DISALLOWED( idx, i + 1 ) && idx_possible < 81 ) 327 possible[ idx_possible++ ] = SET_INDEX( idx ) 328 | SET_DIGIT( i + 1 ) 329 | hintcode; 330 } 331 } 332 if( 8 == digits[ i ] ) 333 { 334 /* 8 digits are masked at this position - just one remaining */ 335 idx = (*idx_fn)( el, i ); 336 for( j = 1 ; j <= 9 ; ++j ) 337 if( 0 == ( STATE( idx ) & DIGIT_STATE( j ) ) && idx_possible < 81 ) 338 possible[ idx_possible++ ] = SET_INDEX( idx ) 339 | SET_DIGIT( j ) 340 | hintcode; 341 } 342 } 343} 344 345/* Given the board state, find all possible 'moves' (i.e. squares with just 346 * a single digit). 347 * 348 * Returns the number of (deterministic) moves (and fills the moves array), 349 * or 0 if no moves are possible. This function does not mutate the board 350 * state, and hence, can return the same move multiple times (with 351 * different hints). 352 */ 353static 354int 355findmoves( void ) 356{ 357 int i; 358 359 rb->yield(); 360 361 idx_possible = 0; 362 for( i = 0 ; i < 9 ; ++i ) 363 { 364 singles( i, idx_row, HINT_ROW ); 365 singles( i, idx_column, HINT_COLUMN ); 366 singles( i, idx_block, HINT_BLOCK ); 367 } 368 return idx_possible; 369} 370 371/* Strategies for refining the board state 372 * - 'pairs' if there are two unfilled squares in a given row/column/ 373 * block with the same state, and just two possibilities, 374 * then all other unfilled squares in the row/column/block 375 * CANNOT be either of these digits. 376 * - 'block' if the unknown squares in a block all appear in the same 377 * row or column, then all unknown squares outside the block 378 * and in the same row/column cannot be any of the unknown 379 * squares in the block. 380 * - 'common' if all possible locations for a digit in a block appear 381 * in a row or column, then that digit cannot appear outside 382 * the block in the same row or column. 383 * - 'position2' if the positions of 2 unknown digits in a block match 384 * identically in precisely 2 positions, then those 2 positions 385 * can only contain the 2 unknown digits. 386 * 387 * Recall that each state bit uses a 1 to prevent a digit from 388 * filling that square. 389 */ 390 391static 392void 393pairs( int el, int (*idx_fn)( int, int ) ) 394{ 395 int i, j, k, mask, idx; 396 397 rb->yield(); 398 399 for( i = 0 ; i < 8 ; ++i ) 400 if( 7 == digits[ i ] ) /* 2 digits unknown */ 401 for( j = i + 1 ; j < 9 ; ++j ) 402 { 403 idx = (*idx_fn)( el, i ); 404 if( STATE( idx ) == STATE( (*idx_fn)( el, j ) ) ) 405 { 406 /* Found a row/column pair - mask other entries */ 407 mask = STATE_MASK ^ (STATE_MASK & board[ idx ] ); 408 for( k = 0 ; k < i ; ++k ) 409 board[ (*idx_fn)( el, k ) ] |= mask; 410 for( k = i + 1 ; k < j ; ++k ) 411 board[ (*idx_fn)( el, k ) ] |= mask; 412 for( k = j + 1 ; k < 9 ; ++k ) 413 board[ (*idx_fn)( el, k ) ] |= mask; 414 digits[ j ] = -1; /* now processed */ 415 } 416 } 417} 418 419/* Worker: mask elements outside block */ 420static 421void 422exmask( int mask, int block, int el, int (*idx_fn)( int, int ) ) 423{ 424 int i, idx; 425 426 rb->yield(); 427 428 for( i = 0 ; i < 9 ; ++i ) 429 { 430 idx = (*idx_fn)( el, i ); 431 if( block != BLOCK( idx ) && IS_EMPTY( idx ) ) 432 board[ idx ] |= mask; 433 } 434} 435 436/* Worker for block() */ 437static 438void 439exblock( int block, int el, int (*idx_fn)( int, int ) ) 440{ 441 int i, idx, mask; 442 443 rb->yield(); 444 445 /* By assumption, all unknown squares in the block appear in the 446 * same row/column, so to construct a mask for these squares, it 447 * is sufficient to invert the mask for the known squares in the 448 * block. 449 */ 450 mask = 0; 451 for( i = 0 ; i < 9 ; ++i ) 452 { 453 idx = idx_block( block, i ); 454 if( !IS_EMPTY( idx ) ) 455 mask |= DIGIT_STATE( DIGIT( idx ) ); 456 } 457 exmask( mask ^ STATE_MASK, block, el, idx_fn ); 458} 459 460static 461void 462block( int el ) 463{ 464 int i, idx = 0, row, col; 465 466 rb->yield(); 467 468 /* Find first unknown square */ 469 for( i = 0 ; i < 9 && !IS_EMPTY( idx = idx_block( el, i ) ) ; ++i ) 470 ; 471 if( i < 9 ) 472 { 473 assert( IS_EMPTY( idx ) ); 474 row = ROW( idx ); 475 col = COLUMN( idx ); 476 for( ++i ; i < 9 ; ++i ) 477 { 478 idx = idx_block( el, i ); 479 if( IS_EMPTY( idx ) ) 480 { 481 if( ROW( idx ) != row ) 482 row = -1; 483 if( COLUMN( idx ) != col ) 484 col = -1; 485 } 486 } 487 if( 0 <= row ) 488 exblock( el, row, idx_row ); 489 if( 0 <= col ) 490 exblock( el, col, idx_column ); 491 } 492} 493 494static 495void 496common( int el ) 497{ 498 int i, idx, row, col, digit, mask; 499 500 rb->yield(); 501 502 for( digit = 1 ; digit <= 9 ; ++digit ) 503 { 504 mask = DIGIT_STATE( digit ); 505 row = col = -1; /* Value '9' indicates invalid */ 506 for( i = 0 ; i < 9 ; ++i ) 507 { 508 /* Digit possible? */ 509 idx = idx_block( el, i ); 510 if( IS_EMPTY( idx ) && 0 == ( board[ idx ] & mask ) ) 511 { 512 if( row < 0 ) 513 row = ROW( idx ); 514 else 515 if( row != ROW( idx ) ) 516 row = 9; /* Digit appears in multiple rows */ 517 if( col < 0 ) 518 col = COLUMN( idx ); 519 else 520 if( col != COLUMN( idx ) ) 521 col = 9; /* Digit appears in multiple columns */ 522 } 523 } 524 if( -1 != row && row < 9 ) 525 exmask( mask, el, row, idx_row ); 526 if( -1 != col && col < 9 ) 527 exmask( mask, el, col, idx_column ); 528 } 529} 530 531/* Encoding of positions of a digit (c.f. position2()) - abuse DIGIT_STATE */ 532static int posn_digit[ 10 ]; 533 534static 535void 536position2( int el ) 537{ 538 int digit, digit2, i, mask, mask2, posn, count, idx; 539 540 rb->yield(); 541 542 /* Calculate positions of each digit within block */ 543 for( digit = 1 ; digit <= 9 ; ++digit ) 544 { 545 mask = DIGIT_STATE( digit ); 546 posn_digit[ digit ] = count = posn = 0; 547 for( i = 0 ; i < 9 ; ++i ) 548 if( 0 == ( mask & board[ idx_block( el, i ) ] ) ) 549 { 550 ++count; 551 posn |= DIGIT_STATE( i ); 552 } 553 if( 2 == count ) 554 posn_digit[ digit ] = posn; 555 } 556 /* Find pairs of matching positions, and mask */ 557 for( digit = 1 ; digit < 9 ; ++digit ) 558 if( 0 != posn_digit[ digit ] ) 559 for( digit2 = digit + 1 ; digit2 <= 9 ; ++digit2 ) 560 if( posn_digit[ digit ] == posn_digit[ digit2 ] ) 561 { 562 mask = STATE_MASK 563 ^ ( DIGIT_STATE( digit ) | DIGIT_STATE( digit2 ) ); 564 mask2 = DIGIT_STATE( digit ); 565 for( i = 0 ; i < 9 ; ++i ) 566 { 567 idx = idx_block( el, i ); 568 if( 0 == ( mask2 & board[ idx ] ) ) 569 { 570 assert( 0 == (DIGIT_STATE(digit2) & board[idx]) ); 571 board[ idx ] |= mask; 572 } 573 } 574 posn_digit[ digit ] = posn_digit[ digit2 ] = 0; 575 break; 576 } 577} 578 579/* Find some moves for the board; starts with a simple approach (finding 580 * singles), and if no moves found, starts using more involved strategies 581 * until a move is found. The more advanced strategies can mask states 582 * in the board, making this an efficient mechanism, but difficult for 583 * a human to understand. 584 */ 585static 586int 587allmoves( void ) 588{ 589 int i, n; 590 591 rb->yield(); 592 593 n = findmoves( ); 594 if( 0 < n ) 595 return n; 596 597 for( i = 0 ; i < 9 ; ++i ) 598 { 599 count_set_digits( i, idx_row ); 600 pairs( i, idx_row ); 601 602 count_set_digits( i, idx_column ); 603 pairs( i, idx_column ); 604 605 count_set_digits( i, idx_block ); 606 pairs( i, idx_block ); 607 } 608 n = findmoves( ); 609 if( 0 < n ) 610 return n; 611 612 for( i = 0 ; i < 9 ; ++i ) 613 { 614 block( i ); 615 common( i ); 616 position2( i ); 617 } 618 return findmoves( ); 619} 620 621/* Helper: sort based on index */ 622#if 0 /* unused function */ 623static 624int 625cmpindex( const void * a, const void * b ) 626{ 627 return GET_INDEX( *((const int *)b) ) - GET_INDEX( *((const int *)a) ); 628} 629 630/* Return number of hints. The hints mechanism should attempt to find 631 * 'easy' moves first, and if none are possible, then try for more 632 * cryptic moves. 633 */ 634static int 635findhints( void ) 636{ 637 int i, n, mutated = 0; 638 639 rb->yield(); 640 641 n = findmoves( ); 642 if( n < 2 ) 643 { 644 /* Each call to pairs() can mutate the board state, making the 645 * hints very, very cryptic... so later undo the mutations. 646 */ 647 for( i = 0 ; i < 9 ; ++i ) 648 { 649 count_set_digits( i, idx_row ); 650 pairs( i, idx_row ); 651 652 count_set_digits( i, idx_column ); 653 pairs( i, idx_column ); 654 655 count_set_digits( i, idx_block ); 656 pairs( i, idx_block ); 657 } 658 mutated = 1; 659 n = findmoves( ); 660 } 661 if( n < 2 ) 662 { 663 for( i = 0 ; i < 9 ; ++i ) 664 { 665 block( i ); 666 common( i ); 667 } 668 mutated = 1; 669 n = findmoves( ); 670 } 671 672 /* Sort the possible moves, and allow just one hint per square */ 673 if( 0 < n ) 674 { 675 int i, j; 676 677 rb->qsort( possible, n, sizeof( int ), cmpindex ); 678 for( i = 0, j = 1 ; j < n ; ++j ) 679 { 680 if( GET_INDEX( possible[ i ] ) == GET_INDEX( possible[ j ] ) ) 681 { 682 /* Let the user make mistakes - do not assume the 683 * board is in a consistent state. 684 */ 685 if( GET_DIGIT( possible[i] ) == GET_DIGIT( possible[j] ) ) 686 possible[ i ] |= possible[ j ]; 687 } 688 else 689 i = j; 690 } 691 n = i + 1; 692 } 693 694 /* Undo any mutations of the board state */ 695 if( mutated ) 696 reapply( ); 697 698 return n; 699} 700#endif /* unused function */ 701 702/* Deterministic solver; return 0 on success, else -1 on error. 703 */ 704static 705int 706deterministic( void ) 707{ 708 int i, n; 709 710 rb->yield(); 711 712 n = allmoves( ); 713 while( 0 < n ) 714 { 715 ++pass; 716 for( i = 0 ; i < n ; ++i ) 717 if( -1 == fill( GET_INDEX( possible[ i ] ), 718 GET_DIGIT( possible[ i ] ) ) ) 719 return -1; 720 n = allmoves( ); 721 } 722 return 0; 723} 724 725/* Return index of square for choice. 726 * 727 * If no choice is possible (i.e. board solved or inconsistent), 728 * return -1. 729 * 730 * The current implementation finds a square with the minimum 731 * number of unknown digits (i.e. maximum # masked digits). 732 */ 733static 734int 735cmp( const void * e1, const void * e2 ) 736{ 737 return GET_DIGIT( *(const int *)e2 ) - GET_DIGIT( *(const int *)e1 ); 738} 739 740static 741int 742choice( void ) 743{ 744 int i, n; 745 746 rb->yield(); 747 748 for( n = i = 0 ; i < 81 ; ++i ) 749 if( IS_EMPTY( i ) ) 750 { 751 possible[ n ] = SET_INDEX( i ) | SET_DIGIT( numset( board[ i ] ) ); 752 753 /* Inconsistency if square unknown, but nothing possible */ 754 if( 9 == GET_DIGIT( possible[ n ] ) ) 755 return -2; 756 ++n; 757 } 758 759 if( 0 == n ) 760 return -1; /* All squares known */ 761 762 rb->qsort( possible, n, sizeof( possible[ 0 ] ), cmp ); 763 return GET_INDEX( possible[ 0 ] ); 764} 765 766/* Choose a digit for the given square. 767 * The starting digit is passed as a parameter. 768 * Returns -1 if no choice possible. 769 */ 770static 771int 772choose( int idx, int digit ) 773{ 774 rb->yield(); 775 776 for( ; digit <= 9 ; ++digit ) 777 if( !DISALLOWED( idx, digit ) ) 778 { 779 board[ idx ] = SET_DIGIT( digit ); 780 update( idx ); 781 add_move( idx, digit, CHOICE ); 782 return digit; 783 } 784 785 return -1; 786} 787 788/* Backtrack to a previous choice point, and attempt to reseed 789 * the search. Return -1 if no further choice possible, or 790 * the index of the changed square. 791 * 792 * Assumes that the move history and board are valid. 793 */ 794static 795int 796backtrack( void ) 797{ 798 int digit, idx; 799 800 rb->yield(); 801 802 for( ; 0 <= --idx_history ; ) 803 if( history[ idx_history ] & CHOICE ) 804 { 805 /* Remember the last choice, and advance */ 806 idx = GET_INDEX( history[ idx_history ] ); 807 digit = GET_DIGIT( history[ idx_history ] ) + 1; 808 reapply( ); 809 if( -1 != choose( idx, digit ) ) 810 return idx; 811 } 812 813 return -1; 814} 815 816/* Attempt to solve 'board'; return 0 on success else -1 on error. 817 * 818 * The solution process attempts to fill-in deterministically as 819 * much of the board as possible. Once that is no longer possible, 820 * need to choose a square to fill in. 821 */ 822static 823int 824solve( void ) 825{ 826 int idx; 827 828 rb->yield(); 829 830 while( 1 ) 831 { 832 if( 0 == deterministic( ) ) 833 { 834 /* Solved, make a new choice, or rewind a previous choice */ 835 idx = choice( ); 836 if( -1 == idx ) 837 return 0; 838 else 839 if( ( idx < 0 || -1 == choose( idx, 1 ) ) && -1 == backtrack( ) ) 840 return -1; 841 } 842 else /* rewind to a previous choice */ 843 if( -1 == backtrack( ) ) 844 return -1; 845 } 846 return -1; 847} 848 849static 850int 851init_template( int template ) 852{ 853 int i, row, col; 854 int mask; 855 856 reset( ); 857 len_tmplt = 0; 858 859 /* Consume grid - allow leading spaces and comments at end */ 860 for( row = 0 ; row < 9 ; ++row ) 861 { 862 mask=0x100; 863 for( col = 0 ; col < 9 ; ++col ) 864 { 865 if (templates[template][row] & mask) 866 tmplt[ len_tmplt++ ] = INDEX( row, col ); 867 mask /= 2; 868 } 869 } 870 871 /* Construct move history for a template */ 872 idx_history = 0; 873 for( i = 0 ; i < 81 ; ++i ) 874 if( 0 != DIGIT( i ) ) 875 history[ idx_history++ ] = i | (DIGIT( i )<<8); 876 877 /* Finally, markup all of these moves as 'fixed' */ 878 for( i = 0 ; i < idx_history ; ++i ) 879 history[ i ] |= FIXED; 880 881 return 0; 882} 883 884/* Classify a SuDoKu, given its solution. 885 * 886 * The classification is based on the average number of possible moves 887 * for each pass of the deterministic solver - it is a rather simplistic 888 * measure, but gives reasonable results. Note also that the classification 889 * is based on the first solution found (but does handle the pathological 890 * case of multiple solutions). Note that the average moves per pass 891 * depends just on the number of squares initially set... this simplifies 892 * the statistics collection immensely, requiring just the number of passes 893 * to be counted. 894 * 895 * Return 0 on error, else a string classification. 896 */ 897 898static 899char * 900classify( void ) 901{ 902 int i, score; 903 904 rb->yield(); 905 906 pass = 0; 907 clear_moves( ); 908 if( -1 == solve( ) ) 909 return 0; 910 911 score = 81; 912 for( i = 0 ; i < 81 ; ++i ) 913 if( IS_FIXED( i ) ) 914 --score; 915 916 assert( 81 == idx_history ); 917 918 for( i = 0 ; i < 81 ; ++i ) 919 if( history[ i ] & CHOICE ) 920 score -= 5; 921 922 if( 15 * pass < score ) 923 return "very easy"; 924 else 925 if( 11 * pass < score ) 926 return "easy"; 927 else 928 if( 7 * pass < score ) 929 return "medium"; 930 else 931 if( 4 * pass < score ) 932 return "hard"; 933 else 934 return "fiendish"; 935} 936 937/* exchange disjoint, identical length blocks of data */ 938static 939void 940exchange( int * a, int * b, int len ) 941{ 942 int i, tmp; 943 for( i = 0 ; i < len ; ++i ) 944 { 945 tmp = a[ i ]; 946 a[ i ] = b[ i ]; 947 b[ i ] = tmp; 948 } 949} 950 951/* rotate left */ 952static 953void 954rotate1_left( int * a, int len ) 955{ 956 int i, tmp; 957 tmp = a[ 0 ]; 958 for( i = 1 ; i < len ; ++i ) 959 a[ i - 1 ] = a[ i ]; 960 a[ len - 1 ] = tmp; 961} 962 963/* rotate right */ 964static 965void 966rotate1_right( int * a, int len ) 967{ 968 int i, tmp; 969 tmp = a[ len - 1 ]; 970 for( i = len - 1 ; 0 < i ; --i ) 971 a[ i ] = a[ i - 1 ]; 972 a[ 0 ] = tmp; 973} 974 975/* Generalised left rotation - there is a naturally recursive 976 * solution that is best implementation using iteration. 977 * Note that it is not necessary to do repeated unit rotations. 978 * 979 * This function is analogous to 'cutting' a 'pack of cards'. 980 * 981 * On entry: 0 < idx < len 982 */ 983static 984void 985rotate( int * a, int len, int idx ) 986{ 987 int xdi = len - idx; 988 int delta = idx - xdi; 989 990 while( 0 != delta && 0 != idx ) 991 { 992 if( delta < 0 ) 993 { 994 if( 1 == idx ) 995 { 996 rotate1_left( a, len ); 997 idx = 0; 998 } 999 else 1000 { 1001 exchange( a, a + xdi, idx ); 1002 len = xdi; 1003 } 1004 } 1005 else /* 0 < delta */ 1006 { 1007 if( 1 == xdi ) 1008 { 1009 rotate1_right( a, len ); 1010 idx = 0; 1011 } 1012 else 1013 { 1014 exchange( a, a + idx, xdi ); 1015 a += xdi; 1016 len = idx; 1017 idx -= xdi; 1018 } 1019 } 1020 xdi = len - idx; 1021 delta = idx - xdi; 1022 } 1023 if( 0 < idx ) 1024 exchange( a, a + idx, idx ); 1025} 1026 1027/* Shuffle an array of integers */ 1028static 1029void 1030shuffle( int * a, int len ) 1031{ 1032 int i, j, tmp; 1033 1034 i = len; 1035 while( 1 <= i ) 1036 { 1037 j = rb->rand( ) % i; 1038 tmp = a[ --i ]; 1039 a[ i ] = a[ j ]; 1040 a[ j ] = tmp; 1041 } 1042} 1043 1044/* Generate a SuDoKu puzzle 1045 * 1046 * The generation process selects a random template, and then attempts 1047 * to fill in the exposed squares to generate a board. The order of the 1048 * digits and of filling in the exposed squares are random. 1049 */ 1050 1051/* Select random template; sets tmplt, len_tmplt */ 1052static 1053void 1054select_template( void ) 1055{ 1056 int i = rb->rand( ) % NUM_TEMPLATES; 1057 init_template( i ); 1058} 1059 1060static bool check_buttons(void) 1061{ 1062 int button = rb->button_get(false); 1063 return (button && (!(button & BUTTON_REL)) && (!(button & BUTTON_REPEAT))); 1064} 1065 1066static 1067bool 1068generate( void ) 1069{ 1070 static int digits[ 9 ]; 1071 1072 int i; 1073 1074start: 1075 /* Allow the user to abort generation by pressing any button */ 1076 if (check_buttons()) 1077 return false; 1078 1079 for( i = 0 ; i < 9 ; ++i ) 1080 digits[ i ] = i + 1; 1081 1082 rotate( digits, 9, 1 + rb->rand( ) % 8 ); 1083 shuffle( digits, 9 ); 1084 select_template( ); 1085 1086 rotate( tmplt, len_tmplt, 1 + rb->rand( ) % ( len_tmplt - 1 ) ); 1087 shuffle( tmplt, len_tmplt ); 1088 1089 reset( ); /* construct a new board */ 1090 1091 for( i = 0 ; i < len_tmplt ; ++i ) 1092 fill( tmplt[ i ], digits[ i % 9 ] ); 1093 1094 /* Allow the user to abort generation by pressing any button */ 1095 if (check_buttons()) 1096 return false; 1097 1098 rb->yield(); 1099 1100 if( 0 != solve( ) || idx_history < 81 ) 1101 goto start; 1102 1103 /* Allow the user to abort generation by pressing any button */ 1104 if (check_buttons()) 1105 return false; 1106 1107 rb->yield(); 1108 1109 for( i = 0 ; i < len_tmplt ; ++i ) 1110 board[ tmplt[ i ] ] |= FIXED; 1111 1112 /* Construct fixed squares */ 1113 for( idx_history = i = 0 ; i < 81 ; ++i ) 1114 if( IS_FIXED( i ) ) 1115 history[ idx_history++ ] = SET_INDEX( i ) 1116 | SET_DIGIT( DIGIT( i ) ) 1117 | FIXED; 1118 clear_moves( ); 1119 1120 if( 0 != solve( ) || idx_history < 81 ) 1121 goto start; 1122 if( -1 != backtrack( ) && 0 == solve( ) ) 1123 goto start; 1124 1125 clear_moves( ); 1126 1127 return true; 1128} 1129 1130bool sudoku_generate_board(struct sudoku_state_t* state, char** difficulty) 1131{ 1132 int r,c,i; 1133 1134 rb->srand(*rb->current_tick); 1135 1136 rb->button_clear_queue(); 1137 1138 if (!generate()) { 1139 /* User has aborted with a button press */ 1140 return false; 1141 } 1142 1143 i=0; 1144 for (r=0;r<9;r++) { 1145 for (c=0;c<9;c++) { 1146 if( IS_EMPTY( i ) ) 1147 state->startboard[r][c]='0'; 1148 else 1149 state->startboard[r][c]='0'+GET_DIGIT( board[ i ] ); 1150 1151 state->currentboard[r][c]=state->startboard[r][c]; 1152 i++; 1153 } 1154 } 1155 1156 *difficulty = classify( ); 1157 return true; 1158} 1159 1160bool sudoku_solve_board(struct sudoku_state_t* state) 1161{ 1162 bool ret; 1163 int r,c,i; 1164 1165 reset( ); 1166 i=0; 1167 for (r=0;r<9;r++) { 1168 for (c=0;c<9;c++) { 1169 if( state->startboard[r][c]!='0' ) 1170 { 1171 fill( i, state->startboard[r][c] - '0' ); 1172 } 1173 i++; 1174 } 1175 } 1176 1177 ret = ( 0 == solve( ) && 81 == idx_history ); 1178 1179 if (ret) { 1180 i=0; 1181 for (r=0;r<9;r++) { 1182 for (c=0;c<9;c++) { 1183 state->currentboard[r][c]='0'+GET_DIGIT( board[ i ] ); 1184 i++; 1185 } 1186 } 1187 } 1188 return ret; 1189}