Python Forum
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Help with sudoku
#1
Just for learning purposes, I am trying to make a script that returns the candidates of every empty cell (I have just put 0) in a sudoku.

I just try to recollect all the numbers in the corresponding line, column and square (the 3x3 region) and get the numbers not included, this is, the candidates for that cell.

For some reason, as I explain in the script itself, the main loop (at the bottom) doesn´t work.
It seems to work fine the first time for any i, j parameters, but starts to fail in the following ones.

I have included some "debug printing" lines (now commented) to check what is happening, and it seems that the first time the "acumulator" function is called, it modifies the original sudoku.
I don´t understand why this happens, for inside the function I am working all the time with a copy of the sudoku list and, as far as I know, it shouldn´t change.

In this image you can see the sudoku and the candidates that the script should return.
[Image: sudoku.jpg]


Any help or advice would be very welcome.
Many thanks.

def acumulator(sudoku, i, j): # Retruns possible candidates for every cell.
	
	sudoku_copy = sudoku.copy() # Makes copy of sudoku list object, for not altering it.

	# acum acumulates values of the line i.
	acum = sudoku_copy[i] 
	
	#print("Debug: acum + line:", acum)

	# acum acumulates values of the column j.
	for n in range(9):
		acum.append(sudoku_copy[n][j]) 

	#print("Debug: acum + column:", acum)

	# acum acumulates values of corresponding square (the 3x3 subsquares that form the sudoku).
	# First line
	if i <= 2 and j <= 2:
		for f in range(3):
			for c in range(3):
				acum.append(sudoku_copy[f][c])

	elif i <= 2 and j <= 5:
		for f in range(3):
			for c in range(3, 6):
				acum.append(sudoku_copy[f][c])

	elif i <= 2 and j <= 8:
		for f in range(3):
			for c in range(6, 9):
				acum.append(sudoku_copy[f][c])

	# Second line:
	elif i > 2 and i <= 5 and j <= 2:
		for f in range(3, 6):
			for c in range(3):
				acum.append(sudoku_copy[f][c])

	elif i > 2 and i <= 5 and j <= 5:
		for f in range(3, 6):
			for c in range(3, 6):
				acum.append(sudoku_copy[f][c])

	elif i > 2 and i <= 5 and j <= 8:
		for f in range(3, 6):
			for c in range(6, 9):
				acum.append(sudoku_copy[f][c])

	# Third line:
	elif i > 5 and j <= 2:
		for f in range(6, 9):
			for c in range(3):
				acum.append(sudoku_copy[f][c])

	elif i > 5 and j <= 5:
		for f in range(6, 9):
			for c in range(3, 6):
				acum.append(sudoku_copy[f][c])

	elif i > 5 and j <= 8:
		for f in range(6, 9):
			for c in range(6, 9):
				acum.append(sudoku_copy[f][c])

	#print("Debug: acum + square:", acum)

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

	# candidates recollects values not present in acum (this is, not present in the corresponding line, column or square)
	candidates = []

	for a in range(9):
		if not(possible_values[a] in acum):
			candidates.append(possible_values[a])		

	return candidates

def main():

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

	# The functions works fine when invoked once:
	# val = acumulator(sudoku, 0, 1) # así sí funciona
	# print(val)

	# But starts failing when invoked again:
	# val = acumulator(sudoku, 0, 3) # así sí funciona
	# print(val)

	# it also fails when included in this loop for checking the candidates of all the cells.

	for i in range(9): # Con esto falla, no sé por qué
		for j in range(9):
			if sudoku[i][j] == 0:
				print("line.", i, " col.", j, " candidates:", sep ="", end =" ")
				val = acumulator(sudoku, i, j)
				print(val)
				
				#print("Debug: sodoku[i]:", sudoku[i])

			else:
				continue

main()
Reply
#2
possible_values = [1, 2, 3, 4, 5, 6, 7, 8, 9]

def rowvals(board, index):
    """Return values that appear in row[index]"""
    return board[index]

def colvals(board, index):
    """Return values that appear in column[index]"""
    return [row[index] for row in board]

def squarevals(board, row, column):
    """Return values that appear in the square containing board[row, column]"""
    row = (row // 3) * 3
    column = (column // 3) * 3
    values = []
    for r in board[row : row+3]:
        values += r[column: column+3]
    return values

def available(board, r, c):
    used = set(rowvals(board, r) + colvals(board, c) + squarevals(board, r, c))
    return [c for c in possible_values if not c in used]

def main():
    sudoku =[[5,0,9,0,0,0,4,0,0],
            [7,0,8,3,0,4,9,0,0,],
            [6,0,1,0,0,0,7,3,0],
            [4,6,2,5,0,0,0,0,0,],
            [3,8,5,7,2,0,6,4,9],
            [1,0,7,4,0,8,2,0,0],
            [2,0,0,1,0,0,0,0,4],
            [0,0,3,0,4,0,0,8,7,],
            [0,7,0,0,5,3,0,0,6]]
 
    for r in range(9):
        for c in range(9):
            if sudoku[r][c] == 0:
                candidates = available(sudoku, r, c)
                print(r, c, candidates)
 
main()
Reply
#3
Did not try the above, but want to point out that your algorithm is flawed as it stands, for example cell 3,7 should also have the possible value 7, which is indeed the correct value for that cell.
Reply
#4
Sure, but that was my mistake making manually the image.

Many thanks, deanhystad.
That´s a much more advanced code. Very useful for learning.
Do you have any idea why mine worked well only for the first iteration but not the rest?
Many thanks again.
Reply
#5
The line below does not initialize acum to the contents of sudoku_copy[i], it makes them the same. Appending anything to accum appends it to sudoku_copy[i]. This is why the first open cell in every row is correct and subsequent open cells are usually missing available values
    acum = sudoku_copy[i] # This is wrong.  Appending to acum appends to sudoku_copy

    acum = sudoku_copy[i].copy()  # This make a copy.  Change acum does not change sudoku_copy
This is what sudoku_copy looks like after processing the first empty cell:
Output:
[5, 0, 9, 0, 0, 0, 4, 0, 0, 0, 0, 0, 6, 8, 0, 0, 0, 7, 5, 0, 9, 7, 0, 8, 6, 0, 1] [7, 0, 8, 3, 0, 4, 9, 0, 0] [6, 0, 1, 0, 0, 0, 7, 3, 0] [4, 6, 2, 5, 0, 0, 0, 0, 0] [3, 8, 5, 7, 2, 0, 6, 4, 9] [1, 0, 7, 4, 0, 8, 2, 0, 0] [2, 0, 0, 1, 0, 0, 0, 0, 4] [0, 0, 3, 0, 4, 0, 0, 8, 7] [0, 7, 0, 0, 5, 3, 0, 0, 6]
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Sudoku Solver in Python - Can someone explain this code ? qwemx 6 2,124 Jun-27-2022, 12:46 PM
Last Post: deanhystad
  Sudoku Solver, please help to solve a problem. AdithyaR 5 2,102 Oct-28-2021, 03:15 PM
Last Post: deanhystad
  building a sudoku solver usercat123 7 2,756 Oct-01-2021, 08:57 PM
Last Post: deanhystad
  Trouble with Sudoku Solver Techmokid 2 2,144 Apr-08-2020, 07:55 AM
Last Post: Techmokid
  editing lists / sudoku solver monagro 5 4,055 May-29-2018, 02:16 PM
Last Post: monagro

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020