コード例 #1
0
ファイル: sudoku.c プロジェクト: ZhangXinNan/leptonica-1
/*!
 * \brief   sudokuTestUniqueness()
 *
 * \param[in]    array of 81 numbers, 9 lines of 9 numbers each
 * \param[out]   punique 1 if unique, 0 if not
 * \return  0 if OK, 1 on error
 *
 * <pre>
 * Notes:
 *      (1) This applies the brute force method to all four 90 degree
 *          rotations.  If there is more than one solution, it is highly
 *          unlikely that all four results will be the same;
 *          consequently, if they are the same, the solution is
 *          most likely to be unique.
 * </pre>
 */
l_int32
sudokuTestUniqueness(l_int32  *array,
                     l_int32  *punique)
{
l_int32    same1, same2, same3;
l_int32   *array1, *array2, *array3;
L_SUDOKU  *sud, *sud1, *sud2, *sud3;

    PROCNAME("sudokuTestUniqueness");

    if (!punique)
        return ERROR_INT("&unique not defined", procName, 1);
    *punique = 0;
    if (!array)
        return ERROR_INT("array not defined", procName, 1);

    sud = sudokuCreate(array);
    sudokuSolve(sud);
    array1 = sudokuRotateArray(array, 1);
    sud1 = sudokuCreate(array1);
    sudokuSolve(sud1);
    array2 = sudokuRotateArray(array, 2);
    sud2 = sudokuCreate(array2);
    sudokuSolve(sud2);
    array3 = sudokuRotateArray(array, 3);
    sud3 = sudokuCreate(array3);
    sudokuSolve(sud3);

    sudokuCompareState(sud, sud1, 1, &same1);
    sudokuCompareState(sud, sud2, 2, &same2);
    sudokuCompareState(sud, sud3, 3, &same3);
    *punique = (same1 && same2 && same3);

    sudokuDestroy(&sud);
    sudokuDestroy(&sud1);
    sudokuDestroy(&sud2);
    sudokuDestroy(&sud3);
    LEPT_FREE(array1);
    LEPT_FREE(array2);
    LEPT_FREE(array3);
    return 0;
}
コード例 #2
0
ファイル: sudokutest.c プロジェクト: 0ximDigital/appsScanner
int main(int    argc,
         char **argv)
{
l_int32      unique;
l_int32     *array;
L_SUDOKU    *sud;
static char  mainName[] = "sudokutest";

    if (argc != 1 && argc != 2)
	return ERROR_INT(" Syntax: sudokutest [filein]", mainName, 1);

    if (argc == 1) {
            /* Generate a new sudoku by element elimination */
        array = sudokuReadString(startsol);
        sud = sudokuGenerate(array, 3693, 28, 7);
        sudokuDestroy(&sud);
        lept_free(array);
        return 0;
    }

        /* Solve the input sudoku */
    if ((array = sudokuReadFile(argv[1])) == NULL)
        return ERROR_INT("invalid input", mainName, 1);
    if ((sud = sudokuCreate(array)) == NULL)
        return ERROR_INT("sud not made", mainName, 1);
    sudokuOutput(sud, L_SUDOKU_INIT);
    startTimer();
    sudokuSolve(sud);
    fprintf(stderr, "Time: %7.3f sec\n", stopTimer());
    sudokuOutput(sud, L_SUDOKU_STATE);
    sudokuDestroy(&sud);

        /* Test for uniqueness */
    sudokuTestUniqueness(array, &unique);
    if (unique)
        fprintf(stderr, "Sudoku is unique\n");
    else
        fprintf(stderr, "Sudoku is NOT unique\n");
    lept_free(array);

    return 0;
}
コード例 #3
0
ファイル: sudoku.c プロジェクト: ZhangXinNan/leptonica-1
/*!
 * \brief   sudokuGenerate()
 *
 * \param[in]    array of 81 numbers, 9 rows of 9 numbers each
 * \param[in]    seed random number
 * \param[in]    minelems min non-zero elements allowed; <= 80
 * \param[in]    maxtries max tries to remove a number and get a valid sudoku
 * \return  l_sudoku, or NULL on error
 *
 * <pre>
 * Notes:
 *      (1) This is a brute force generator.  It starts with a completed
 *          sudoku solution and, by removing elements (setting them to 0),
 *          generates a valid (unique) sudoku initial condition.
 *      (2) The process stops when either %minelems, the minimum
 *          number of non-zero elements, is reached, or when the
 *          number of attempts to remove the next element exceeds %maxtries.
 *      (3) No sudoku is known with less than 17 nonzero elements.
 * </pre>
 */
L_SUDOKU *
sudokuGenerate(l_int32  *array,
               l_int32   seed,
               l_int32   minelems,
               l_int32   maxtries)
{
l_int32    index, sector, nzeros, removefirst, tries, val, oldval, unique;
L_SUDOKU  *sud, *testsud;

    PROCNAME("sudokuGenerate");

    if (!array)
        return (L_SUDOKU *)ERROR_PTR("array not defined", procName, NULL);
    if (minelems > 80)
        return (L_SUDOKU *)ERROR_PTR("minelems must be < 81", procName, NULL);

        /* Remove up to 30 numbers at random from the solution.
         * Test if the solution is valid -- the initial 'solution' may
         * have been invalid.  Then test if the sudoku with 30 zeroes
         * is unique -- it almost always will be. */
    srand(seed);
    nzeros = 0;
    sector = 0;
    removefirst = L_MIN(30, 81 - minelems);
    while (nzeros < removefirst) {
        genRandomIntegerInRange(9, 0, &val);
        index = 27 * (sector / 3) + 3 * (sector % 3) +
                9 * (val / 3) + (val % 3);
        if (array[index] == 0) continue;
        array[index] = 0;
        nzeros++;
        sector++;
        sector %= 9;
    }
    testsud = sudokuCreate(array);
    sudokuSolve(testsud);
    if (testsud->failure) {
        sudokuDestroy(&testsud);
        L_ERROR("invalid initial solution\n", procName);
        return NULL;
    }
    sudokuTestUniqueness(testsud->init, &unique);
    sudokuDestroy(&testsud);
    if (!unique) {
        L_ERROR("non-unique result with 30 zeroes\n", procName);
        return NULL;
    }

        /* Remove more numbers, testing at each removal for uniqueness. */
    tries = 0;
    sector = 0;
    while (1) {
        if (tries > maxtries) break;
        if (81 - nzeros <= minelems) break;

        if (tries == 0) {
            fprintf(stderr, "Trying %d zeros\n", nzeros);
            tries = 1;
        }

            /* Choose an element to be zeroed.  We choose one
             * at random in succession from each of the nine sectors. */
        genRandomIntegerInRange(9, 0, &val);
        index = 27 * (sector / 3) + 3 * (sector % 3) +
                9 * (val / 3) + (val % 3);
        sector++;
        sector %= 9;
        if (array[index] == 0) continue;

            /* Save the old value in case we need to revert */
        oldval = array[index];

            /* Is there a solution?  If not, try again. */
        array[index] = 0;
        testsud = sudokuCreate(array);
        sudokuSolve(testsud);
        if (testsud->failure == TRUE) {
            sudokuDestroy(&testsud);
            array[index] = oldval;  /* revert */
            tries++;
            continue;
        }

            /* Is the solution unique?  If not, try again. */
        sudokuTestUniqueness(testsud->init, &unique);
        sudokuDestroy(&testsud);
        if (!unique) {  /* revert and try again */
            array[index] = oldval;
            tries++;
        } else {  /* accept this */
            tries = 0;
            fprintf(stderr, "Have %d zeros\n", nzeros);
            nzeros++;
        }
    }
    fprintf(stderr, "Final: nelems = %d\n", 81 - nzeros);

        /* Show that we can recover the solution */
    sud = sudokuCreate(array);
    sudokuOutput(sud, L_SUDOKU_INIT);
    sudokuSolve(sud);
    sudokuOutput(sud, L_SUDOKU_STATE);

    return sud;
}
コード例 #4
0
ファイル: main.c プロジェクト: suxpert/sudoku
int main(int argc, char *argv[])
{
	FILE * fin = NULL;
	int lineCounter = 1;
	int sudoku[9][9] = {{0}};
	int row = 0;
	int col = 0;
	int fileOK = 1;
	int prec, c;

	if( 2 != argc ) {
		printf("Argument error!\nUsage: %s <file-name>\n", argv[0]);
		return 0;
	}

	fin = fopen(argv[1], "rb");
	if( NULL == fin ) {
		printf("Cannot open file `%s' for read!\n", argv[1]);
		return 1;
	}

#define GET_NEXT_CHAR (prec = c, c = fgetc(fin))

	while( fileOK && EOF != (GET_NEXT_CHAR) ) {
		// printf("`%c|%c',", prec, c);
		switch( c ) {
			case '#' :
				while( '\n' != (GET_NEXT_CHAR) );
				// fall through;
			case '\n' :
				if( 0 != col%9 ) {
					printf("Error! Unfinished line at L%d, %d %s expected!",
							lineCounter, (9-col),
							(9-col==1? "number": "numbers") );
					fileOK = 0;
				} // if unfinished
				lineCounter++;
				break;
			case '%' :
				if( '\n' == prec && '%' == (GET_NEXT_CHAR) ) {
					// line starting by `%%', treat as separator
					if( 0 != row%9 || 0 != col%9 ) {
						printf("Error!"
								" Incomplete sudoku before separator at L%d!",
								lineCounter);
						fileOK = 0;
					} // if incomplete
				} // if separator
				break;
			case '0' :
			case '1' :
			case '2' :
			case '3' :
			case '4' :
			case '5' :
			case '6' :
			case '7' :
			case '8' :
			case '9' :
				sudoku[row][col++] = c-'0';
				if( 9 == col ) {
					col = 0;
					row++;
					if( 9 == row ) {
						// a complete sudoku has been stored, try to solve it.
						printf(">> Complete sudoku, will now solve...\n");
						printSudoku(sudoku);
						sudokuSolve(sudoku);
						row = 0;
					} // if complete
				} // if line finished
				break;
			default :
				// do nothing;
				break;
		} // switch
	} // while
	return 0;
}