Reputation: 1
I'm new to python and StackOverflow and trying to write a small program that checks if a sudoku puzzle (i.e. a series of lists) is correct (True) or incorrect (False).
So I broke it down by writing 2 functions, one that checks ROWS (i.e. checks that there is one of EACH number from 1-n - where n is the length of the list - in each list) and one function that checks COLUMNS (to make sure there is no crossover of elements down the lists, and that there is only one of each number from 1-n in position 0, 1, and so forth).
The first function is working fine, but the second one (checking columns) seems to constantly output 'True' even when the puzzle is incorrect. For example, for the list
myList =
[[1,2,3],
[3,1,2],
[3,2,3]],
the output is True, when the puzzle is wrong. I have tried to spot the problem lots of times by going through with e.g.s line by line, but to no avail! Can anyone spot what it is I've done wrong, or share any better ways of coding a sudoku-checker? :)
Thank you!! Here is my code for checking columns:
def check_down(list_of_lists):
a = [] #checking list
i = -1 #list
j = 0 #position
n = len(list_of_lists)
while True:
i = i + 1
if [list_of_lists[i][j]] in a: #if list element already in a, it is a copy so False
return False
break
elif [list_of_lists[i][j]] not in a:
a = a + [list_of_lists[i][j]] #if list element not in a then add it
if i == n-1 and j == n-1: #if loop reaches end of lists, True
return True
break
elif i == n-1 and j!= n-1: #if last list but not last position, move on
j = j +1 #next position to check
i = -1 #reset i to -1
del a[:] #empty the checking list
else:
return False
Upvotes: 0
Views: 1171
Reputation: 1916
The problem in your code is that you are checking the existence of a list in list a instead of checking the existence of the number:
if [list_of_lists[i][j]] in a:
So the brackets around list_of_lists[i][j] are making it a list which contains single element. So you need to remover those brackets and the code will work as expected.
There are several other improvents as mentioned by @Right Leg.
However your logic for Sudoku checker is still wrong as you are missing the grid check. Checking the uniqueness at row level as well as at column level is a necessary condition but it is not sufficient. Consider the following example:
As you can see in the images above, each row has unique elements, each column has unique elements, but there is duplicacy of elements in each 3x3 grid. So even if the answer is False, your solution will return True beacuse you do not have any grid check. So you need to write logic to check uniqueness at grid level as well.
You may use the following code. Note that the following code can be improved by using extra space:
import math
def checkSudoku(sudoku):
# Check uniqueness in each row.
for i in range(len(sudoku)):
lst = []
for j in range(len(sudoku)):
if sudoku[i][j] in lst:
return False
else:
lst.append(sudoku[i][j])
# Check uniqueness in each column.
for j in range(len(sudoku)):
lst =[]
for i in range(len(sudoku)):
if sudoku[i][j] in lst:
return False
else:
lst.append(sudoku[i][j])
# Check uniqueness in each grid.
offset = int(math.sqrt(len(sudoku)))
for rowStart in range(0,len(sudoku),offset):
rowEnd = rowStart + offset
for columnStart in range(0,len(sudoku),offset):
columnEnd = columnStart + offset
lst = []
for i in range(rowStart,rowEnd):
for j in range(columnStart,columnEnd):
if sudoku[i][j] in lst:
return False
else:
lst.append(sudoku[i][j])
# No test was failed, So return True.
return True
Upvotes: 0
Reputation: 16720
First off, your flow is really wrong.
You really should not write things like
while True :
i = i + 1
even if the inside of the while
is supposed to break somewhere. Instead, since you are iterating over the rows, just do:
while i < rowsNumber :
i = i + 1
Then, you write:
if A :
#stuff
elif not A :
#other stuff
else :
#guess what, stuff
But that last else
cannot logically be reached. The right way is:
if A :
#stuff
else :
#other stuff
Besides, you write a = a + [list_of_lists[i][j]]
, which does work, but I would largely prefer a.append(list_of_list[i][j]
, which is way more pythonic.
Also, you don't need to use break
after a return
statement, because return
stops the execution of the function.
Now for your problem: you wrote [list_of_lists[i][j]] in a
, which is False
, because [list_of_lists[i][j]]
is a list. What you want is [list_of_lists[i][j]] in a
, without the brackets.
I corrected this and tried it on your example, and it did return False
.
Upvotes: 1