简体   繁体   中英

Sudoku solver that returns number of solutions

I made a working sudoku solver using a basic backtracking algorithm. It works reasonably well even though there are many optimizations to be done.

I tried modifying my code to return the total number of solutions for a given sudoku grid. To do this I simply changed the solving function to add up every possibility instead of stopping at one.

However I only get 1 or 0.

Here is the code for the basic solver:

int     check_row(char **tab, int y, int n)
{
    int i;

    i = 0;
    while (i < 9)
    {
        if (tab[y][i] == n + '0')
            return (0);
        i++;
    }
    return (1);
}

int     check_column(char **tab, int x, int n)
{
    int j;

    j = 0;
    while (j < 9)
    {
        if (tab[j][x] == n + '0')
            return (0);
        j++;
    }
    return (1);
}

int     check_square(char **tab, int x, int y, int n)
{
    int i;
    int j;

    i = (x / 3) * 3;
    while (i < (x / 3) * 3 + 3)
    {
        j = (y / 3) * 3;
        while (j < (y / 3) * 3 + 3)
        {
            if (tab[j][i] == n + '0')
                return (0);
            j++;
        }
        i++;
    }
    return (1);
}

int     solve(char **tab, int x, int y)
{
    int n;

    if (y >= 9 || x >= 9)
        return (1);
    if (tab[y][x] == '.')
    {
        n = 1;
        while (n < 10)
        {
            if (check_row(tab, y, n) && check_column(tab, x, n)
                && check_square(tab, x, y, n))
            {
                tab[y][x] = n + '0';
                if (solve(tab, (x + 1) % 9, y + ((x + 1) / 9)))
                    return (1);
            }
            n++;
        }
        tab[y][x] = '.';
        return (0);
    }
    else
        return (solve(tab, (x + 1) % 9, y + ((x + 1) / 9)));
}

And here is the modified function that should count the solutions:

int     solve_count(char **tab, int x, int y)
{
    int n;
    int count;
    count = 0;
    if (y >= 9 || x >= 9)
        return (1);
    if (tab[y][x] == '.')

    {

        n = 1;
        while (n < 10)
        {
            if (check_row(tab, y, n) && check_column(tab, x, n)
                && check_square(tab, x, y, n))
            {
                tab[y][x] = n + '0';
                count += solve_count(tab, (x + 1) % 9, y + ((x + 1) / 9));
            }
            n++;
        }
        tab[y][x] = '.';
    return (count);


    }
    else
        return (solve_count(tab, (x + 1) % 9, y + ((x + 1) / 9)));
}

The main() and helper functions are as follows:

#include <unistd.h>

int     solve(char **tab, int x, int y);
int     solve_count(char **tab, int x, int y);
void    ft_putchar(char c)
{
    write(1, &c, 1);
}

void    ft_putstr(char *str)
{
    int i;

    i = 0;
    while (*(str + i) != '\0')
    {
        ft_putchar(*(str + i));
        i++;
    }
}

void    ft_putnbr(int n)
{
    int     i;
    int     vect[20];
    long    nb;

    nb = n;
    i = -1;
    if (nb < 0)
    {
        ft_putchar('-');
        nb = -nb;
    }
    if (nb == 0)
        ft_putchar('0');
    while (nb > 0)
    {
        i++;
        vect[i] = nb % 10;
        nb = nb / 10;
    }
    while (i > -1)
    {
        ft_putchar('0' + vect[i]);
        i--;
    }
}

int     ft_check_input(int argc, char **argv)
{
    int i;
    int j;

    i = 1;
    j = 0;
    if (argc != 10)
        return (1);
    while (i < argc)
    {
        while (argv[i][j])
            j++;
        if (j != 9)
            return (1);
        j = 0;
        while (argv[i][j] == '.' || (argv[i][j] > '0' && argv[i][j] <= '9'))
            j++;
        if (j != 9)
            return (1);
        j = 0;
        i++;
    }
    if (i != 10)
        return (1);
    else
        return (0);
}

void    ft_print_sudoku(char **tab)
{
    int i;
    int j;

    i = 1;
    j = 0;
    while (i < 10)
    {
        while (j < 9)
        {
            ft_putchar(tab[i][j]);
            if (j < 8)
                ft_putchar(' ');
            j++;
        }
        ft_putchar('\n');
        j = 0;
        i++;
    }
}

int     main(int argc, char **argv)
{
    if (ft_check_input(argc, argv))
        ft_putstr("Error: not a good sudoku\n");
    else
    {
        if (solve(argv + 1, 0, 0))
        {
            ft_print_sudoku(argv);
            ft_putnbr(solve_count(argv + 1, 0, 0));
        }
        else
            ft_putstr("Error: no solution\n");
    }
    return (0);
}

To get the number of solutions for an empty sudoku you would run ('.' means empty item):

./sudoku "........." "........." "........." "........." "........." "........." "........." "........." "........."

It runs, but still stops at the first solution it finds, and returns 1. What am I missing? I've been scratching my head for a while now.

Eventually I'm thinking of using this function to create a grid by adding random numbers until there's just one solution.

I Did this a long time ago for fun...

What I did to Solve the most difficult ones was to return for each squares, All possible numbers

And then destroy each possible numbers one by one for each grid...

so even if you get 9 possibilities for the first grid you enter the first and if it doesn't fit. you delete it and try the second.

One of them needs too fit :)

To know how may possible solutions to a soduku puzzle exists that would take a brute force calculation.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM