Home > Mobile >  (Sudoku board validator) loop through every n item in couple lists
(Sudoku board validator) loop through every n item in couple lists

Time:02-03

I'm trying to make a sudoku board validator and I'm stuck at validating columns.

Grid looks like this:

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

I've came up with an idea

  • to loop through every n item in rows, put them in list and by using set() check if all numbers are unique (9 times). My code looks like this:
def grid(*rows):

    #validate columns
    cut = []
    x = range(0,8)
    counter = 0
    while counter != 9:
        for column in rows:
            cut.append(column[x])
            print(len(cut) == len(set(cut)))
            counter  = 1

I suspect there are better and more efficient ways to solve this problem, but I'm new to Python and want to learn. If I want to make it my way, what am I doing wrong?

CodePudding user response:

You can use zip to transpose the matrix, then check the size of the sets while iterating over the columns.

for col in zip(*rows):
    if len({*col}) != len(col):
        print('not unique')
    else:
        print('good')

CodePudding user response:

If I want to make it my way, what am I doing wrong?

  • you initialize cut = [] in front of both loops instead of initializing it every time a new column is validated. You have to place cut = [] within the while and before the for loop going over the rows to prevent the code of collecting in cut all of the extracted values and not only these from the just validated column.
  • x = range(0,8) makes x being a range not a single value required as index, so the code column[x] gives an TypeError: list indices must be integers or slices, not range. You don't need x in your code at all. The value of counter is what you need in place of x.
  • print and counter 1 indentation is wrong. In your code the counter will be increased not only with each new processed column, but also with each row from which the single column value is extracted. This will give counter values from 0 up to 80 and not as expected and should be from 0 to 8.
  • a better approach to sudoku validation will be one validation procedure applied to the three different views on the sudoku grid. For a proposal of code providing functions for generating a column and 3x3 cell view on the sudoku grid generated from the list of rows see the code provided later on along with a proposal of another principle for use in the validation function.

Below your code adjusted in a way that it works as it should:

def grid(rows):
    #validate columns
    counter = 0
    while counter != 9:
        cut = []
        for row in rows: 
            cut.append(row[counter])
        counter  = 1
        print(len(cut) == len(set(cut)))

To get you started using another approach for the logic of a validation procedure, below a suggestion how to get the column and the 3x3 cell views on the sudoku grid list from the list of the grid rows. Having this views the function for validating the columns and the 3x3 cells will be exactly the same as for rows.

The naming of variables in the code should be sufficient as documentation what the code does:

lstSudokuGridRows = [
[6, 2, 5, 8, 4, 3, 7, 9, 1],
[7, 9, 1, 2, 6, 5, 4, 8, 3],
[4, 8, 3, 9, 7, 1, 6, 2, 5],
[8, 1, 4, 5, 9, 7, 2, 3, 6],
[2, 3, 6, 1, 8, 4, 9, 5, 7],
[9, 5, 7, 3, 2, 6, 8, 1, 4],
[5, 6, 9, 4, 3, 2, 1, 7, 8],
[3, 4, 2, 7, 1, 8, 5, 6, 9],
[1, 7, 8, 6, 5, 9, 3, 4, 2]]
print(lstSudokuGridRows)

def getSudokuGridColumns(lstSudokuGridRows):
    return list(zip(*lstSudokuGridRows))
lstSudokuGridColumns = getSudokuGridColumns(lstSudokuGridRows)
print(lstSudokuGridColumns)

def getSudokuGridCells(lstSudokuGridRows):
    lstCells = [[],[],[],[],[],[],[],[],[]]
    #print(lstCells)
    for i_row, row in enumerate(lstSudokuGridRows):
       for i_column, col_row_item in enumerate(row):
           #print(3*(i_row//3) (1 i_column//3), end='|')
           lstCells[3*(i_row//3) (1 i_column//3)-1].append(col_row_item)
    #print()
    return lstCells
lstSudokuGridCells = getSudokuGridCells(lstSudokuGridRows)
print(lstSudokuGridCells)

and the printed output can be checked against the sudoku grid defined as a list of rows if the correct values are in the 9 sublists of the list:

[[6, 2, 5, 8, 4, 3, 7, 9, 1], [7, 9, 1, 2, 6, 5, 4, 8, 3], [4, 8, 3, 9, 7, 1, 6, 2, 5], [8, 1, 4, 5, 9, 7, 2, 3, 6], [2, 3, 6, 1, 8, 4, 9, 5, 7], [9, 5, 7, 3, 2, 6, 8, 1, 4], [5, 6, 9, 4, 3, 2, 1, 7, 8], [3, 4, 2, 7, 1, 8, 5, 6, 9], [1, 7, 8, 6, 5, 9, 3, 4, 2]]
[(6, 7, 4, 8, 2, 9, 5, 3, 1), (2, 9, 8, 1, 3, 5, 6, 4, 7), (5, 1, 3, 4, 6, 7, 9, 2, 8), (8, 2, 9, 5, 1, 3, 4, 7, 6), (4, 6, 7, 9, 8, 2, 3, 1, 5), (3, 5, 1, 7, 4, 6, 2, 8, 9), (7, 4, 6, 2, 9, 8, 1, 5, 3), (9, 8, 2, 3, 5, 1, 7, 6, 4), (1, 3, 5, 6, 7, 4, 8, 9, 2)]
[[6, 2, 5, 7, 9, 1, 4, 8, 3], [8, 4, 3, 2, 6, 5, 9, 7, 1], [7, 9, 1, 4, 8, 3, 6, 2, 5], [8, 1, 4, 2, 3, 6, 9, 5, 7], [5, 9, 7, 1, 8, 4, 3, 2, 6], [2, 3, 6, 9, 5, 7, 8, 1, 4], [5, 6, 9, 3, 4, 2, 1, 7, 8], [4, 3, 2, 7, 1, 8, 6, 5, 9], [1, 7, 8, 5, 6, 9, 3, 4, 2]]

For validation of the board I would suggest not to implement the idea of the number of unique elements as the not yet solved sudoku board can have also the zero ( 0 ) as value or just wrong values beyond the span of 1 to 9 what will then be not detected by the validation and therefore making it much harder to debug the code in eventual case of problems. Below a proposal of validation function based on comparing a sorted line of the sudoku grid view (which can be one of row view, column view and 3x3 cell view) with [1,2,3,4,5,6,7,8,9]:

def validateSudokuView(lstSudokuGridView):
    gridViewOK = True
    for line in lstSudokuGridView:
        if sorted(line) != [1,2,3,4,5,6,7,8,9]:
            gridViewOK = False
            break
    return gridViewOK

which can be also coded as:

def validateSudokuView(lstSudokuGridView):
    return all(
        sorted(line)==[1,2,3,4,5,6,7,8,9] for line in lstSudokuGridView
    )

using the Python all() function.

  • Related