Related
I have been packaging a script to calculate all possible entries in the empty cells of a sudoku game. While the algorithm to screen the vertical column and the horizontal row works, it seems that my script is not able to screen the relevant box where the empty cell is located.
The code that I am using is the following:
def possible(y,x,n):
global grid
for i in range(0,9):
if grid[y][i] == n:
return False
for i in range(0,9):
if grid[i][x] == n:
return False
x0 = (x//3)*3
y0 = (y//3)*3
for i in range(0,3):
for j in range(0,3):
if (grid[y0+i][x0+j] == n):
#print((x0+j),end=' ')
#print((y0+i),end=' ')
return False
list.append(y+1)
list.append(x+1)
list.append(n)
return True
It seems that there is some problem with the append procedure.....
Any assistance is welcome
My general comments:
Seems like you are trying to append to a list which might or might
not be defined outside of the possible() function (it's not in the supplied code).
However, as it is
not defined within the scope of that function, you generally can't
access it from the inside. Related read.)
Also you should change a variable name as
list is a built-in type of Python and it is not
recommended to use builtin types as variable
names unless you absolutely need to do so for some reason.
Generally it is not a best practice to use global variables.
My suggestion would be to move the gathering of possible
numbers outside of this function. Example:
def possible(grid: list[list[int]], num: int, pos: tuple[int, int]) -> bool:
# Check row
if num in grid[pos[0]]:
return False
# Check column
if num in [item[pos[1]] for item in grid]:
return False
# Check box
box_x = pos[1] // 3
box_y = pos[0] // 3
for i in range(box_y * 3, box_y * 3 + 3):
if num in grid[i][box_x * 3: box_x * 3 + 3] \
and (i, grid[i].index(num)) != pos:
return False
return True
Then run this 'cleaner' function in a for loop or list comprehension to collect possible numbers for a given position on the Sudoku grid.
For example (for cycle):
possible_values = []
for i in range(1,10):
if possible(grid, i, (x, y)):
possible_values.append(i)
Or this (list comprehension):
possible_values = [n for n in range(1,10) if possible(grid, n, (0, 2))]
In the Sudoku game world one call the "possible entries" of the empty cells, candidates or pencil-marks.
Here is how we can identify the candidates of the empty cells.
grid = [
[0, 0, 0, 6, 0, 8, 9, 1, 0],
[6, 0, 2, 0, 9, 0, 3, 4, 0],
[1, 9, 8, 3, 0, 0, 0, 6, 7],
[0, 5, 9, 0, 0, 0, 4, 2, 3],
[4, 0, 0, 8, 0, 3, 0, 0, 1],
[7, 1, 3, 0, 2, 0, 8, 0, 0],
[9, 6, 0, 5, 3, 7, 2, 8, 0],
[2, 0, 0, 4, 1, 0, 0, 3, 0],
[3, 4, 0, 2, 8, 0, 1, 7, 9],
]
candidates=bytearray(729)
def identifyCandidates():
for cell in range(81):
row,col=divmod(cell,9)
if grid[row][col] == 0 :
for kan in range(1,10):
if not clueInSector(cell, kan):
candidates[9*cell+(kan - 1)]=1
def clueInSector(cell, clue):
cellrow,cellcol = divmod(cell,9)
for col in range(9):
if (col != cellcol and grid[cellrow][col] == clue) :
return True
for row in range(9):
if (row != cellrow and grid[row][cellcol] == clue) :
return True
rowB = 3 * ((cellrow) // 3)
colB = 3 * ((cellcol) // 3)
for row in range (rowB,rowB + 3) :
for col in range(colB,colB +3) :
if (col != cellcol and row != cellrow and grid[row][col] == clue) :
return True
return False
Print of the 13 first cells:
cell:0 candidates: 5.
cell:1 candidates: 3.7.
cell:2 candidates: 4.5.7.
cell:3 no candidate.
cell:4 candidates: 4.5.7.
cell:5 no candidate.
cell:6 no candidate.
cell:7 no candidate.
cell:8 candidates: 2.5.
cell:9 no candidate.
cell:10 candidates: 7.
cell:11 no candidate.
cell:12 candidates: 1.7.
I'm trying an exercise that wants me to return a new list that contains all the same elements except the negative numbers which are turned into zeros in the returned list.
I have used a for loop to loop through the parameter list and if the number is below 0, I would append it to a new list but times it by 0. However, I get weird outputs such as empty lists. For example, the code below should print:
[0, 0, 9, 0, 0, 34, 1]
[9, 34, 1]
[0, 0, 0]
Please stick to using list methods thanks.
The code:
def get_new_list_no_negs(num_list):
new_list = []
for i in range(len(num_list)):
if i < 0:
new_list.append(num_list[i] * 0)
return new_list
def main():
print("1.", get_new_list_no_negs([-3, -6, 9, 0, 0, 34, 1]))
print("2.", get_new_list_no_negs([9, 34, 1]))
print("3.", get_new_list_no_negs([-9, -34, -1]))
main()
This should do:
def get_new_list_no_negs(num_list):
return [max(num, 0) for num in num_list]
the max function is a python builtin that will return the largest between the passed numbers.
Try this
l = [-2, -1, 0, 1, 2]
# this
l = [i for i in l if i > 0 else 0]
# or
l = [max(i, 0) for i in l]
The enumerate() function adds a counter to an iterable.
So for each element in a cursor, a tuple is produced with (counter, element); the for loop binds that to row_number and row, respectively.
l = [-2, -1, 0, 1, 2]
for index, value in enumerate(l):
if value < 0:
l[index] = 0
print(l)
O/P:
[0, 0, 0, 1, 2]
import numpy as np
def row(board,x,y):
"""Takes in a board and x y coordinates and returns all
the row candidates"""
numbers = np.arange(1,10)
missing = []
for number in numbers:
if number not in board[x]:
missing.append(number)
else:
continue
return missing
def column(board,x,y):
"""Takes an incomplete board and returns all the
column candidates"""
numbers = np.arange(1,10)
missing = []
for number in numbers:
if number not in board[:,y]:
missing.append(number)
else:
continue
return missing
def box(board,x,y):
"""Takes an incomplete board, coordinates and returns the
box wise candidates"""
numbers = list(range(1,10))
missing = []
box1 = np.array([board[0,0:3],board[1,0:3],board[2,0:3]])
box2 = np.array([board[0,3:6],board[1,3:6],board[2,3:6]])
box3 = np.array([board[0,6:10],board[1,6:10],board[2,6:10]])
box4 = np.array([board[3,0:3],board[4,0:3],board[5,0:3]])
box5 = np.array([board[3,3:6],board[4,3:6],board[5,3:6]])
box6 = np.array([board[3,6:10],board[4,6:10],board[5,6:10]])
box7 = np.array([board[6,0:3],board[7,0:3],board[8,0:3]])
box8 = np.array([board[6,3:6],board[7,3:6],board[8,3:6]])
box9 = np.array([board[6,6:10],board[7,6:10],board[8,6:10]])
condition1 = 0<=x<=2 and 0<=y<=2
condition2 = 0<=x<=2 and 3<=y<=5
condition3 = 0<=x<=2 and 6<=y<=8
condition4 = 3<=x<=5 and 0<=y<=2
condition5 = 3<=x<=5 and 3<=y<=5
condition6 = 3<=x<=5 and 6<=y<=8
condition7 = 6<=x<=8 and 0<=y<=2
condition8 = 6<=x<=8 and 3<=y<=5
condition9 = 6<=x<=8 and 6<=y<=8
if condition1:
for number in numbers:
if number not in box1:
missing.append(number)
else:
continue
if condition2:
for number in numbers:
if number not in box2:
missing.append(number)
else:
continue
if condition3:
for number in numbers:
if number not in box3:
missing.append(number)
else:
continue
if condition4:
for number in numbers:
if number not in box4:
missing.append(number)
else:
continue
if condition5:
for number in numbers:
if number in box5:
continue
else:
missing.append(number)
if condition6:
for number in numbers:
if number not in box6:
missing.append(number)
else:
continue
if condition7:
for number in numbers:
if number not in box7:
missing.append(number)
else:
continue
if condition8:
for number in numbers:
if number not in box8:
missing.append(number)
else:
continue
if condition9:
for number in numbers:
if number not in box9:
missing.append(number)
else:
continue
return missing
def sudsolver(board):
"""Give it a board andt it will solve it for your using the functions defined above."""
newboard = board.copy()
for index,n in np.ndenumerate(board):
if board[index] == 0:
x = index[0]
y = index[1]
boxsolution = box(newboard,x,y)
columnsolution = column(newboard,x,y)
rowsolution = row(newboard,x,y)
if len(boxsolution) or len(columnsolution) or len(rowsolution) < 1:
for number in boxsolution:
if number in columnsolution and number in rowsolution:
newboard[index] = number
else:
continue
else:
continue
return newboard
testboard = np.array([
[0, 0, 0, 3, 7, 0, 0, 5, 6],
[5, 0, 0, 0, 1, 0, 9, 7, 0],
[0, 6, 0, 9, 8, 0, 3, 4, 0],
[0, 0, 7, 0, 0, 2, 0, 8, 0],
[0, 0, 9, 0, 3, 0, 6, 0, 0],
[0, 5, 0, 8, 0, 0, 2, 0, 0],
[0, 7, 5, 0, 6, 9, 0, 2, 0],
[0, 4, 8, 0, 2, 0, 0, 0, 5],
[2, 9, 0, 0, 5, 8, 0, 0, 0]
])
pleasework = sudsolver(testboard)
I have created different functions to check the solutions of a given cell, however, when the board is returned from the sudsolver function, the board still has a few 0's in it.
The board which I am using is called testboard and I have been assured that it is possible to solve.
I cannot think of why this is and how to solve it. Any help would be great.
I have a list of integers and I am trying to define a function which loops through every element to check if they are less than 5 and returns the list in string according to their contents.
intlist=[12, 10, 11, 23, 25, 2]
def clear(x):
for i in x:
if i < 5:
x[i] = 0
return str(x)
else:
return str(x)
print clear(intlist)
My code is not working as intended, could anyone enlighten me?
If they are, I am to change all elements in the list to '0'. The outcome should look something like this.
intlist=[0, 0, 0, 0, 0, 0]
However if none of the elements are less than 5, the output should remain the same.
intlist=[12, 10, 11, 23, 25, 2]
Welcome to StackOverflow! Your code has some logic problem. Here's my fix:
intlist=[12, 10, 11, 23, 25, 2]
def clear(x):
for i in x:
if i < 5: # If this is satisfied once, return string with n times of '0'
x = [0]*len(x) # This creates a list of zeros with same length as before
return str(x)
return str(x)
print clear(intlist)
Besides, in your example the element 2 is less than 5, so the output should be 000000
intlist=[12, 10, 11, 23, 25, 2]
def clear(x):
if (any(i<5 for i in intlist)): return [0]*len(intlist)
else: return(x)
print(clear(intlist)) # [0, 0, 0, 0, 0, 0]
check for the any item is <5 then return all zeros or keep the list as it is.
There are a couple of mistakes in the for loop that you have written. First, the return statement is inside the loop, which makes it exit just after the if statement or else statement, whichever it goes to first. Secondly, you are making a mistake with how you are indexing. If you wish to access elements through index, you range in your loop instead. Here is the correct implementation for the function that you want :
def clear(x):
for i in range(len(x)):
if x[i]<5:
x[i]=0
return str(x)
You can do it one one-line, creating a list of zeros if any one of the elements in list is less than 5 or retaining the list otherwise.
intlist = [12, 10, 11, 23, 25, 2]
intlist = [0] * len(intlist) if any(x < 5 for x in intlist) else intlist
print(intlist)
# [0, 0, 0, 0, 0, 0]
I am trying to return the elements starting from the last row which are equal to 1 and not zero.And then traceback the next element by comparing with adjacent elements vertically,horizontally and diagonally.if next element is zero,then return the position,else continue till we reach a position where the next element will be zero and hence return the position.
I have written the following program:
def test():
M=[[0, 0, 0, 0, 0, 0, 0],
[1, 0, 0, 1, 0, 0, 1],
[2, 1, 0, 0, 1, 0, 0]]
list=[]
for i in range(2,0,-1):
for j in range(6,0,-1):
if M[i,j]!=0 and M[i,j]<=k:
s=max(M[i,j-1],M[i-1,j-1],M[i-1,j])
if s==0:
list.append(j+1)
else:
s=M[i,j]
elif j==0:
for i in range(2,0,-1):
if M[i,j]!=0 and M[i,j]<=k:
s=M[i-1,j]
if s==0:
list.append(j+1)
else:
s=M[i,j]
return list
print(test())
Expected answer will be 1,4,7
It returned me values 4,7 but 1 is not showing,can anyone suggest me the additions that it returns me the value '1' as well ?I have tried editing the code,but still it shows the same result.