0

I can solve an easy puzzle but attempting a slightly harder one is impossible; what am I overlooking? Here is my solver method:

   int solver (int x, int y)
   {
     int a, b, i, j;
     for (a=1; a<10; a++)
     {
       if (checkEverything(x, y, a))
       {
         board[x][y] = a;
         counter++;
         if (counter == 81)
         {
           return true;
         }
                     if (x == 9)

        {

          return true;

        }

        if (counter > 200 || counter < -10) {

          return false;

        }

        for (i=0; i<9; i++)

        {

          for (j=0; j<9; j++)

          {

            if (board[i][j] == 0)

            {

              if (solver(i, j))

              {

                return true;

              }   

            }

          }

        }

        counter--;      

      }

    }

    board[x][y] = 0;

    return false;

    }

My checkEverything function checks to make sure that the given number is safe to be placed in the row, column, and 3x3 grid...I am very lost because it seems to be right to me but it is so slow. Thanks for any help!

user3366369
  • 13
  • 1
  • 8
  • How will you invoke this recursive function? – konjac Mar 05 '14 at 03:26
  • @KunHuang: in my main function I call it by two for loops: for (i=0; i<9; i++) and another nested inside of that using int j with an if statement checking to see if board[i][j] == 0 and if so I call solver. Does that answer your question? Sorry, I am very very new to both c and stackoverflow – user3366369 Mar 05 '14 at 03:52

1 Answers1

0

Your implementation takes too much extra checking.

When finding a current valid candidate for current (x, y), it is redundant to find the next undetermined position from the beginning of the chessboard.

The complexity for your recursive function will be O(N*N)*O(N)*M(N is the side length of the chessboard, or 9. M is the complexity of your checkEverything ).In this expression, O(N*N) is to find the next undetermined position and O(N) is the complexity of try every digit from 1 to N. I don't know how you implement checkEverything, but a naive implement will be M = O(N). That means the total complexity may be about O(N4)

The common advices for optimization will be:

  1. reduce the complexity of finding the next position to be O(1). You can preprocess the chessboard and obtain all of the undetermined positions into an list in advance.

  2. reduce the complexity of checkEverything. It can be reduced into O(1) by using some hash tables to hold digits already used, 9 for the each column, 9 for each row, 9 for each sub rectangle.

With this two advice, the complexity of the recursive will be O(N).

If you want a perfect performance, I advice you to learn Dancing Links invented by Knuth. The main idea of this algorithm is using a 2 dimension double linked list to store all candidate of all positions and accelerate finding the next position and the next candidate, delete invalid candidates and recover when backtracing.

http://en.wikipedia.org/wiki/Dancing_Links

konjac
  • 757
  • 8
  • 14
  • I'm not quite sure I understand what you are getting at; is there something inside my solver function that I need to mess with or does this stuff take place in main? Is there a way, for example, to start at the most populated area of the board to start checking? – user3366369 Mar 05 '14 at 05:12