Pages

Sunday, August 12, 2012

very simple brute force sudoku solve program in C

     In my college first year, I heard Sivakumar telling about his friend's brother who created a c program to solve sudoku. At that time I was thinking it was very hard and that guy who created that program is very intelligent. Because I never solved even a single sudoku puzzle. Sometimes I sat for hours and it will go wrong in at last.

     Till yesterday I never thought that I am able write a program to solve a sudoku puzzle. But this bike accident made me to sit alone in room and I had nothing to do. Siva came into mind as well as the puzzle program. I just gave a thought. Viola the concept is very simple. Brute-force! the all time success methodology will solve this puzz in minutes even in worst case.

    Here I have attached my code which is less than 200 lines.

    Also read the code here. And please update me if it is having any issues.

sudoku.h
#ifndef SUDOKU_H
#define SUDOKU_H 1
#define ZERO 0
#define MAX 9
#define PASS 0
#define FAIL 1
#define FIXED 0
#define WORKING 1
#define TOWORK 2
typedef struct element {
    int val;
    int status;
} element;
extern element elm[MAX][MAX];
void get_input();
int next_elm();
int check(int, int);
void show();
#endif

main.c
#include <stdio.h>
#include "sudoku.h"
element elm[MAX][MAX];
int main() {
    printf("SUDOKU PROGRAM BY theB\n");
    get_input();
    int ret = next_elm();
    if (ret == PASS) {
        show();
    }
    else {
        printf("INPUT ERROR\n");
    }
    return 0;
}

get_input.c
#include <stdio.h>
#include "sudoku.h"
void get_input() {
    int i, j;
    for (i = 0; i < MAX ; i++) {
        for (j = 0; j < MAX; j++) {
            printf("ENTER elm[%d][%d]: ", i, j);
            scanf("%d", &elm[i][j].val);

            if (elm[i][j].val)
                elm[i][j].status = FIXED;
            else
                elm[i][j].status = TOWORK;
        }
    }
}

check.c
#include <stdio.h>
#include "sudoku.h"
int check(int x, int y) {
    int i, j;
    //CHECK HORIZONTAL
    for (i = 0; i < MAX; i++) {
        if ((elm[x][y].val == elm[i][y].val) && (x != i))
            return FAIL;
    }
    //CHECK VERTICAL
    for (i = 0; i < MAX; i++) {
        if ((elm[x][y].val == elm[x][i].val) && (y != i))
            return FAIL;
    }
    //CHECK BOXES
    int startx = (x / 3) * 3;
    int starty = (y / 3) * 3;
    for (i = startx; i < startx + 3; i++) {
        for (j = starty; j < starty + 3; j++) {
            if ((elm[x][y].val == elm[i][j].val) && (x != i) && (y != j)) {
                return FAIL;
            }
        }
    }
    return PASS;
}

next_elm.c
#include <stdio.h>
#include "sudoku.h"
int next_elm() {
    int i, j, k;
    for (i = 0; i < MAX; i++) {
        for (j = 0; j < MAX; j++) {
            if (elm[i][j].status == TOWORK)
                goto L;
        }
    }
    return PASS;
    L:
    for (k = 1; k <= MAX; k++) {
        elm[i][j].val = k;
        elm[i][j].status = WORKING;
        int ret = check(i, j);
        if (ret == FAIL)
            continue;
        else if (ret == PASS) {
            ret = next_elm();
            if (ret == PASS)
                return PASS;
            else
                continue;
        }
    }
    elm[i][j].val = 0;
    elm[i][j].status = TOWORK;
    return FAIL;
}

4 comments:

  1. I did not run the program. But from the code what I see in next_elm.c I find the following logical flaws.

    Let us say according to the given values at the initial point the possible values that can come in box 0,0 are 1,3,7.

    But lets assum...
    e that in the final solution the value that needs to come in the box 0,0 is 3. As per your code you only seems to accept 1 and keep working.

    How do u come back and solve the column if you find it later that it does not give the solution. I do not see any come back or repair mechanism there.

    Potential logical flaws :
    1. The assumption that the first possible value between 1 to 9 in ascending order at any column will be a correct solution.
    2. Saying it a input error if the assumption above is not giving the correct solution

    --Wrote by Dinesh in Facebook

    ReplyDelete
  2. I think you missed the for loop. The for loop assigns value from 1 to MAX(9) to the unknown element. first it checks whether entered value is not clashing with existing value. If clashing the for loop continues with the next value.

    int ret = check(i, j);
    if (ret == FAIL)
    continue;

    If it passes the check, it go for the next unknown element. Its a recursive call. So it will last untill it finds a solution or a clash occurs. The recursion will stop once there will be no unknown element remaining

    for (i = 0; i < MAX; i++) {
    for (j = 0; j < MAX; j++) {
    if (elm[i][j].status == TOWORK)
    goto L;
    }
    }
    return PASS;

    Then all calls in the stack returns PASS to its recursive caller. Finally the main will get a PASS return value. Then main shows the result. If there is a clash, it will return FAIL to its recursive caller. Then the caller continues with next value.

    else if (ret == PASS) {
    ret = next_elm();
    if (ret == PASS)
    return PASS;
    else
    continue;
    }

    If all all values are over, it returns a FAIL to its recursive caller and resets the current to unknown. Then the caller continues with next value.

    elm[i][j].val = 0;
    elm[i][j].status = TOWORK;
    return FAIL;

    ReplyDelete
  3. This comment has been removed by the author.

    ReplyDelete
  4. I just understood the way the recursion is used here. Really awesome. I wonder I could have written this. To think of recursion so deeply and write this "YOU ARE SIMPLY AWESOME".

    For a end user It might just be a program that returns a SUDOKU value.
    But as a programmer I should say that its just Wonderful.
    EXTENSIVE USE OF RECURSION. MARVELOUS.

    And thats my BALA :)

    Pls do call me. Am not able to contact you. Hope you changed your number

    ReplyDelete