1

Possible Duplicate:
Sudoku algorithm, brute force

For several days I have tried to write a brute force algorithm for solving sudoku, my problem is that I never realy get the algorithm to work 100 %, can someone please direct me and give some help ?

The Algorithm is located in Square class, recursive function.

public abstract class Square {

private Square next;

private Box box;
private Row row;
private Columne columne;

private int value;

Square(int value, Box box, Row row, Columne columne) {
    this.value = value;
    this.box = box;
    this.row = row;
    this.columne = columne;
}

void setNumberMeAndTheRest(Board board) {
    if(getNext() == null) {
        System.out.println("next == null");
        for(int i = 1; i <= board.getDimension(); i++) {
            if(legalValue(i)) {
                setValue(i);
            }
        }
        board.saveSolution();
        return;
    } else {
        if(this instanceof DefinedSquare) {
            getNext().setNumberMeAndTheRest(board);

        } else {
            for(int i = 1; i <= board.getDimension(); i++) {
                if(legalValue(i)) {
                    setValue(i);
                    getNext().setNumberMeAndTheRest(board);
                }
            }
            return;
        }
    }
}

int getValue() {
    return value;
}

void setValue(int value) {
    this.value = value;
}

void setNext(Square next) {
    this.next = next;
}

public Square getNext() {
    return next;
}

/**
 * Checks if value is legal in box, row and column.
 * @param value to check.
 * @return true if value is legal, else false.
 */
boolean legalValue(int value) {
    if(box.legalValue(value) && row.legalValue(value) && columne.legalValue(value)) {
        return true;
    }
    return false;
}
Community
  • 1
  • 1
user265767
  • 559
  • 3
  • 12
  • 27
  • 2
    It helps to know what's wrong - like input and the expected and received output – dfb Apr 17 '12 at 14:43
  • Brute force will not solve all Sudoku puzzles. Sometimes, you have to guess a number, and be able to backtrack to the guess if you guessed wrong. – Gilbert Le Blanc Apr 17 '12 at 14:44
  • @GilbertLeBlanc you could solve it buy trying every number in every available slot and checking if it worked, so you can solve by brute force, just not nicely – Jacxel Apr 17 '12 at 14:45
  • @GilbertLeBlanc - huh? Brute force to me would be all possible combination of numbers in every position, which surely would find the answer. Sounds like you're talking about a greedy algorithm maybe? This looks like what's going on above too but I'm ot sure – dfb Apr 17 '12 at 14:47
  • For a brute force algorithm, I would expect to see some recursion, iterating over each row to fill in the answers, and a separate function that tests to see if it's solved. – Marcus Adams Apr 17 '12 at 14:51
  • @Jacxel & spinning_plate: You do realize that you're talking about roughly 9 to the 81st power combinations, right? I don't even want to guess how long that would take. Usually when people talk about solving Sudoku by "brute force", they're talking about not coding the solving "rules" that a human would use. – Gilbert Le Blanc Apr 17 '12 at 14:52
  • @GilbertLeBlanc - Of course, I'm just answering the question as it was asked. The code looks like it's backtracking, acutally – dfb Apr 17 '12 at 14:53

2 Answers2

2

I think your problem may lie here

    for(int i = 1; i <= board.getDimension(); i++) {
        if(legalValue(i)) {
            setValue(i);
            getNext().setNumberMeAndTheRest(board);
        }
    }

If legalValue(i) returns true independent of the current state of i, then you're back tracking, if not, you're not backtracking

What most backtracking looks like is osmething like htis

    for(int i = 1; i <= board.getDimension(); i++) {
        if(legalValue(i)) {
            setValue(i);
                // boolean indicating whether solution was found
            if(getNext().setNumberMeAndTheRest(board))
               return true;
            else
               unsetValue(i)
        }
    }

We need more code to know if legalValue returns false when square i is already set

Try this to see if I'm on the right track or post all of your code

    System.out.println("STARTING ITERATION")
    for(int i = 1; i <= board.getDimension(); i++) {

        if(legalValue(i)) {
            System.out.println("GOING " + i)
            setValue(i);
            getNext().setNumberMeAndTheRest(board);
        }
    }
    System.out.println("ENDING ITERATION")

If it fills out the grid and then stops without backtracking, your problem is that you calling setValue(i) and then calling legalValue(i+1) and it is return false because the value is alraedy set, not because it's not legal. If this is so, you need an equivalent 'unset' after the reucrsion

dfb
  • 13,133
  • 2
  • 31
  • 52
  • And unsetValue(i) is doing what ? – user265767 Apr 17 '12 at 15:06
  • Nulling out the value. My fear is that legalValue returns false for the next legal value when the square has been filled – dfb Apr 17 '12 at 15:09
  • Specifically, whats the Box.LegalValue function look like – dfb Apr 17 '12 at 15:10
  • Box, Row and Columne looks like this public boolean legalValue(int value) { for(Square s : squars) { if(s.getValue() == value) { return false; } } return true; } – user265767 Apr 17 '12 at 15:22
  • remove 'box.legalValue(value)' in the legalValue function and tell me what happens – dfb Apr 17 '12 at 15:47
  • I have tried to remove box.legalValue(value) both with the original code and "spinning_plate" suggestion, the latest option gives a total different answer like this: 421653 132546 513264 265431 654320 300102 – user265767 Apr 17 '12 at 15:56
  • I am not sure that I understand unsetValue(i) totally, do unsetValue(i) the same as setValue(i) ? – user265767 Apr 17 '12 at 15:59
  • I can't help you with the specifics because I don't have all the code- I need you to answer this question on the original code above - on each level of recursion, how many times is setValue called - see my eidts – dfb Apr 17 '12 at 16:00
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/10183/discussion-between-user265767-and-spinning-plate) – user265767 Apr 17 '12 at 16:09
  • Here is the output: STARTING ITERATION GOING 4 STARTING ITERATION GOING 2 STARTING ITERATION GOING 5 STARTING ITERATION GOING 6 STARTING ITERATION GOING 1 STARTING ITERATION ENDING ITERATION ENDING ITERATION ENDING ITERATION ENDING ITERATION ENDING ITERATION ENDING ITERATION – user265767 Apr 17 '12 at 18:22
  • entire code https://github.com/cbeberge/Sudoku/tree/master/src – user265767 Apr 17 '12 at 18:23
1

From a quick look at your algorithm, it looks as though it only ever tries a single possible value in each square. When it reaches a square where it can't find a legal value, it just gives up. It needs some mechanism of backtracking and trying alternative legal values in squares that it has previously filled.

As an example, here's a mini 4x4 puzzle:

  1 |    
    | 2  
---------
    |   4
3   |

Your algorithm, from what I can tell, will get this far then quit:

2 1 | 3 X 
    | 2  
---------
    |   4
3   |

Instead of quitting, it ought to go back and change either of the 2 values it has inserted.

vaughandroid
  • 4,315
  • 1
  • 27
  • 33