Ejemplo n.º 1
0
Archivo: sudoku.c Proyecto: MMauser/-3
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;
}
Ejemplo n.º 2
0
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;
}