int Sudoku_ParseFile( struct Sudoku* sud, const wchar_t* filepath, const wchar_t delimiter ) { unsigned char* file; unsigned int i, j, rowindex, cellvalue, cellindex; int retv; SudokuCell mask_possible; //read file file = ReadAllBytes( filepath ); if( file == NULL ) return SUDOKUERROR_FILE; //clear struct memset( sud, 0, sizeof( struct Sudoku ) ); retv = SUDOKUERROR_PARSER; //determine grid size by counting occurences of delimiter in first row for( i = 0; file[i] != '\n'; i++ ) { if( file[i] == delimiter ) sud->length++; } //minimum size of grid is 2x2 (1 2 \n3 4 \n) if( sud->length < 2 ) { retv = SUDOKUERROR_GRIDSIZE; goto CLEANUP; } sud->length_of_box = ( int ) ( 0.5f + sqrt( sud->length ) ); if( sud->length_of_box * sud->length_of_box != sud->length ) { retv = SUDOKUERROR_GRIDSIZE; goto CLEANUP; } mask_possible = 0; for( i = 0; i < sud->length; i++ ) { mask_possible |= ( 1ll << i ); } //allocate grid sud->grid = ( SudokuCell** ) calloc( sud->length, sizeof( SudokuCell* ) ); if( sud->grid == NULL ) goto CLEANUP; sud->cellvalue = ( int** ) calloc( sud->length, sizeof( int* ) ); if( sud->cellvalue == NULL ) goto CLEANUP; //allocate grid rows for( i = 0; i < sud->length; i++ ) { sud->grid[i] = ( SudokuCell* ) malloc( sud->length * sizeof( SudokuCell ) ); if( sud->grid[i] == NULL ) goto CLEANUP; //alle werte auf möglich setzen for( j = 0; j < sud->length; j++ ) sud->grid[i][j] = ( SudokuCell ) mask_possible; sud->cellvalue[i] = ( int* ) calloc( sud->length, sizeof( int ) ); } //allocate contains helper for( i = 0; i < 3; i++ ) { sud->contains[i] = ( unsigned long long* ) calloc( sud->length, sizeof( unsigned long long ) ); if( sud->contains[i] == NULL ) goto CLEANUP; } sud->cellbox = ( SudokuCell**** ) calloc( sud->length, sizeof( SudokuCell*** ) ); if( sud->cellbox == NULL ) goto CLEANUP; sud->cellboxvalue = ( unsigned int**** ) calloc( sud->length, sizeof( unsigned int*** ) ); if( sud->cellboxvalue == NULL ) goto CLEANUP; //allocate and set box helper for( i = 0; i < sud->length; i++ ) { sud->cellbox[i] = ( SudokuCell*** ) calloc( sud->length, sizeof( SudokuCell** ) ); if( sud->cellbox[i] == NULL ) goto CLEANUP; sud->cellboxvalue[i] = ( unsigned int*** ) calloc( sud->length, sizeof( unsigned int** ) ); if( sud->cellboxvalue[i] == NULL ) goto CLEANUP; for( j = 0; j < sud->length; j++ ) { //position (0,0) in box->allocate if( j % sud->length_of_box == 0 && i % sud->length_of_box == 0 ) { sud->cellbox[i][j] = ( SudokuCell** ) calloc( sud->length, sizeof( SudokuCell* ) ); if( sud->cellbox[i][j] == NULL ) goto CLEANUP; sud->cellboxvalue[i][j] = ( unsigned int** ) calloc( sud->length, sizeof( unsigned int* ) ); if( sud->cellboxvalue[i][j] == NULL ) goto CLEANUP; //position (0,x) in box -> copy ptr from above cell) } else if( j % sud->length_of_box == 0 ) { sud->cellbox[i][j] = sud->cellbox[i - 1][j]; sud->cellboxvalue[i][j] = sud->cellboxvalue[i - 1][j]; } else { sud->cellbox[i][j] = sud->cellbox[i][j - 1]; sud->cellboxvalue[i][j] = sud->cellboxvalue[i][j - 1]; } } } //i:y j:x for( i = 0; i < sud->length; i += sud->length_of_box ) { for( j = 0; j < sud->length; j += sud->length_of_box ) { for( cellindex = 0; cellindex < sud->length; cellindex++ ) { sud->cellbox[i][j][cellindex] = &sud->grid[i + cellindex / sud->length_of_box][j + cellindex % sud->length_of_box]; sud->cellboxvalue[i][j][cellindex] = &sud->cellvalue[i + cellindex / sud->length_of_box][j + cellindex % sud->length_of_box]; } } } cellvalue = 0; cellindex = 0; rowindex = 0; //parse grid for( i = 0; file[i] != '\0'; i++ ) { //if current tchar is delimiter, finish cell if( file[i] == delimiter ) { Sudoku_SetCell( sud, cellindex++, rowindex, cellvalue ); if( cellindex == sud->length ) { cellindex = 0; //if no. of rows == no. of cols + 1 end parsing if( rowindex == sud->length ) break; } cellvalue = 0; //if current tchar is end of line increment rowindex } else if( file[i] == '\n' ) { rowindex++; //if current tchar is not ctrl tchar, parse as cell content } else if( file[i] == '\r' ) { continue; } else { cellvalue *= 10; cellvalue += file[i] - '0'; } } //skip cleanup retv = 0; goto END; CLEANUP: //free sudoku if allocated if( sud != NULL ) { //free sudoku grid if allocated if( sud->grid != NULL ) { for( i = 0; i < sud->length; i++ ) { if( sud->grid[i] != NULL ) free( sud->grid[i] ); } free( sud->grid ); } //free cellvalue grid if( sud->cellvalue != NULL ) { for( i = 0; i < sud->length; i++ ) { if( sud->cellvalue[i] != NULL ) free( sud->cellvalue[i] ); } free( sud->cellvalue ); } if( sud->cellbox != NULL ) { for( i = 0; i < sud->length; i += sud->length_of_box ) { if( sud->cellbox[i] != NULL ) { for( j = 0; j < sud->length; j += sud->length_of_box ) { if( sud->cellbox[i][j] != NULL ) free( sud->cellbox[i][j] ); } free( sud->cellbox[i] ); } } free( sud->cellbox ); } if( sud->cellboxvalue != NULL ) { for( i = 0; i < sud->length; i += sud->length_of_box ) { if( sud->cellboxvalue[i] != NULL ) { for( j = 0; j < sud->length; j += sud->length_of_box ) { if( sud->cellboxvalue[i][j] != NULL ) free( sud->cellboxvalue[i][j] ); } free( sud->cellboxvalue[i] ); } } free( sud->cellboxvalue ); } //free contains grid for( i = 0; i < 3; i++ ) { if( sud->contains[i] != NULL ) free( sud->contains[i] ); } free( sud ); sud = NULL; } END: //free loaded file if( file != NULL ) free( file ); return retv; }
int SudokuStack_GetNextModification( struct SudokuStack* stack, struct Sudoku** dest ) { int rc; unsigned int x, y, i; //parameter validation if( stack == NULL || dest == NULL ) return SUDOKUSTACKERROR_INVALIDARGS; struct Sudoku* nextcopy = ( struct Sudoku* )malloc( sizeof( struct Sudoku ) ); if( nextcopy == NULL ) return SUDOKUSTACKERROR_OUTOFMEMORY; if( stack->_ctSudokus == stack->_maxSudokus ) return SUDOKUSTACKERROR_FULL; //create copy from current sudoku if( ( rc = Sudoku_CreateCopy( stack->_stack[stack->_ctSudokus - 1]._sud, nextcopy ) ) != 0 ) { free( nextcopy ); *dest = NULL; return rc; } //get first free cell in grid if( ( rc = Sudoku_GetNextFreeCell( nextcopy, &x, &y ) ) != 0 ) { Sudoku_Free( nextcopy ); *dest = NULL; return rc; } //get candidates and find first candidate SudokuCell candidates = nextcopy->grid[y][x]; for( i = 0; i < nextcopy->length; i++ ) { #ifdef SUDOKU_CELLTYPE_BITVECTOR if( ( candidates & ( 1LL << i ) ) != 0 ) { #else if( candidates[i] != 0 ) { #endif break; } } //no candidates available //shouldn't occur due to different validation result //resulting in call to GetNextSudoku //=>detect error and return is sufficient if( i++ == nextcopy->length ) { Sudoku_Free( nextcopy ); return -3; } //set candidate in cell #ifdef SUDOKU_CELLTYPE_BITVECTOR stack->_stack[stack->_ctSudokus]._cellcandidates = candidates; #else vcopy( stack->_stack[stack->_ctSudokus]._cellcandidates, candidates, nextcopy->length ); #endif Sudoku_SetCell( nextcopy, x, y, i ); stack->_stack[stack->_ctSudokus]._sud = nextcopy; stack->_stack[stack->_ctSudokus].x = x; stack->_stack[stack->_ctSudokus].y = y; stack->_stack[stack->_ctSudokus]._ctchanges = i; stack->_ctSudokus++; //copy new sudoku ptr to dest *dest = nextcopy; return 0; } int SudokuStack_GetNextSudoku( struct SudokuStack* stack, struct Sudoku** dest ) { int rc; unsigned int x, y, i; SudokuCell candidates; //parameter validation if( stack == NULL || dest == NULL ) return SUDOKUSTACKERROR_INVALIDARGS; struct Sudoku* nextcopy = ( struct Sudoku* )malloc( sizeof( struct Sudoku ) ); if( nextcopy == NULL ) return SUDOKUSTACKERROR_OUTOFMEMORY; if( stack->_ctSudokus == 1 ) return SUDOKUSTACKERROR_EMPTY; stack->_ctSudokus--; //delete current solution Sudoku_Free( stack->_stack[stack->_ctSudokus]._sud ); //create copy from previous solution if( ( rc = Sudoku_CreateCopy( stack->_stack[stack->_ctSudokus - 1]._sud, nextcopy ) ) != 0 ) { free( nextcopy ); *dest = NULL; return rc; } //get candidates available for last changed cell candidates = stack->_stack[stack->_ctSudokus]._cellcandidates; for( i = stack->_stack[stack->_ctSudokus]._ctchanges; i < nextcopy->length; i++ ) { #ifdef SUDOKU_CELLTYPE_BITVECTOR if( ( candidates & ( 1LL << i ) ) != 0 ) { #else if( candidates[i] != 0 ) { #endif break; } } //if no next candidate is available for cell //move to previous solution if( i++ == nextcopy->length ) { Sudoku_Free( nextcopy ); return SudokuStack_GetNextSudoku( stack, dest ); } x = stack->_stack[stack->_ctSudokus].x; y = stack->_stack[stack->_ctSudokus].y; //set cell to next possible candidate #ifdef SUDOKU_CELLTYPE_BITVECTOR stack->_stack[stack->_ctSudokus]._cellcandidates = candidates; #else vcopy( stack->_stack[stack->_ctSudokus]._cellcandidates, candidates, nextcopy->length ); #endif Sudoku_SetCell( nextcopy, x, y, i ); stack->_stack[stack->_ctSudokus]._sud = nextcopy; stack->_stack[stack->_ctSudokus].x = x; stack->_stack[stack->_ctSudokus].y = y; stack->_stack[stack->_ctSudokus]._ctchanges = i; stack->_ctSudokus++; //copy new sudoku ptr to dest *dest = nextcopy; return 0; } struct Sudoku* SudokuStack_Peek( struct SudokuStack* stack ) { //parameter validation if( stack == NULL || stack->_ctSudokus == 0 ) return NULL; //return previous sudoku return stack->_stack[stack->_ctSudokus - 1]._sud; } unsigned int SudokuStack_GetCurrentDepth(struct SudokuStack* stack) { return stack->_ctSudokus; }