-3

I'm trying to write a simple sudoku solver in python. The basic concept is that the sudoku puzzle is partially filled in and the unsolved cells are indicated by zeros. Any cell denoted by a zero can be solved at any stage of the puzzle. So if the first cell is 0, then it means the values in that row, column and 3x3 subgrid ensure that there can only be one possible value for that cell. Here is my code, I seem to be stuck because the output displays more than one possibility. Is my algorithm wrong?

def solveOne (array, posR, posC):

possible = ['1','2','3','4','5','6','7','8','9']

for col in range (9):
    if array[posR][col] in possible:
        possible.remove(array[posR][col])


for row in range (9):
    if array[row][posC] in possible:
        possible.remove(array[row][posC])

for row in range(posR, posR+3):
    for col in range (posC, posC+3):
        if array[row::][col::] in possible:
            possible.remove(array[row][col])

print (possible)
return possible

grid = [["" for _ in range(9)] for _ in range(9)] #define a 9x9 2-dimensional list

for row in range(9):
    aLine = input() #prompt user to enter one line of characters
    for col in range(9):
        grid[row][col] = aLine[col:col+1] #assign every character in a line to a position in the 2-D array

for row in range(9):
    for col in range (9):
        if grid[row][col] == '0':
            r = row
            c = col
            newV = solveOne (grid,r,c)
            grid[row][col] = newV

print()
for i in range (9):
    for k in range(9):
        print(grid[i][k], end = "")
    print()
Rajendra_Prasad
  • 1,300
  • 4
  • 18
  • 36

1 Answers1

1

There are several mistakes:

for row in range(posR, posR+3):
    for col in range (posC, posC+3):
        if array[row::][col::] in possible:
            possible.remove(array[row][col])

will not do what you want it to do. You better try (for python 2.7 - beware of the div operation not doing a float divison but a integer division):

block = ((posR/3)*3,(posC/3)*3) # get the top left cell of the 3x3 block
for row in range(block[0], block[0]+3):
    for col in range (block[1], block[1]+3):
        if array[row][col] in possible:
            possible.remove(array[row][col])

So now it works better. But by doing

for row in range(9):
    for col in range (9):
        if grid[row][col] == '0':
            r = row
            c = col
            newV = solveOne (grid,r,c)
            grid[row][col] = newV

you only go through the sudoku once. It's sometimes neccessary to solve a sudoku in more than one step through - think about that.

And you also have to be aware that not every sudoku has a unique solution. Think about solving an empty sudoku - where you can pretty much "do what you want".

Robsdedude
  • 1,292
  • 16
  • 25
  • Thanks for the nudge in the right direction. I did realise my mistake with regards to the 3x3 subgrid. But if there is only one possible solution for every block wouldn't I only need to go through the suduko once? for instance 059000483 000000012 010028000 098074020 040080030 070630540 000160050 620000000 735000860 there is only one possible value for every zero in this grid – Ollie Hawker May 13 '13 at 11:24
  • nope it wouldn't be enough because sometimes cells are ambiguous unitll you've filled out other cells. – Robsdedude May 13 '13 at 15:33