This is a sudoku solver, in the second function when I try to return the solved board it appears as none, but if you print the board you can see the solution. here is the code:
board = [[5,3,0,0,7,0,0,0,0],
[6,0,0,1,9,5,0,0,0],
[0,9,8,0,0,0,0,6,0],
[8,0,0,0,6,0,0,0,3],
[4,0,0,8,0,3,0,0,1],
[7,0,0,0,2,0,0,0,6],
[0,6,0,0,0,0,2,8,0],
[0,0,0,4,1,9,0,0,5],
[0,0,0,0,8,0,0,7,9]]
def solution(row, col, number):
for i in range(9):
if board[row][i] == number:
return False
if board[i][col] == number:
return False
row0 = (row // 3) *3
col0 = (col // 3) * 3
for i in range(3):
for j in range(3):
if board[row0+i][col0+j] == number:
return False
return True
def solve():
global board
for row in range(9):
for col in range(9):
if board[row][col] == 0:
for number in range(1,10):
if solution(row, col, number):
board[row][col] = number
solve()
board[row][col] = 0
return
[print(x) for x in board]
return board
print(solve())
How can I make the solve function return the new board?
The issue with your code is that you have two exiting points, one that returns the board:
return board
and one that returns nothing (i.e. None)
return
If you follow how the recursion calls are invoked, you realize that the parent call is actually returning from the None exit point.
However, just passing board to that exit point does not fix the issue as you have recursive calls to solve() which are followed by setting back to 0 specific cells.
So essentially, you first solve the sudoku and then unwind the whole solution back to where you started.
To solve this you need to keep track of when you actually solve the sudoku and skip the setting back to 0 if the sudoku is solved.
One way of doing this (slightly rewritten to avoid the perilous use of global) is:
board = [[5,3,0,0,7,0,0,0,0],
[6,0,0,1,9,5,0,0,0],
[0,9,8,0,0,0,0,6,0],
[8,0,0,0,6,0,0,0,3],
[4,0,0,8,0,3,0,0,1],
[7,0,0,0,2,0,0,0,6],
[0,6,0,0,0,0,2,8,0],
[0,0,0,4,1,9,0,0,5],
[0,0,0,0,8,0,0,7,9]]
def solution(board, row, col, number):
for i in range(9):
if board[row][i] == number:
return False
if board[i][col] == number:
return False
row0 = (row // 3) *3
col0 = (col // 3) * 3
for i in range(3):
for j in range(3):
if board[row0+i][col0+j] == number:
return False
return True
def solve(board):
for row in range(9):
for col in range(9):
if board[row][col] == 0:
is_solved = False
for number in range(1, 10):
if solution(board, row, col, number):
board[row][col] = number
is_solved = solve(board)
if not is_solved:
board[row][col] = 0
return is_solved
return True
def print_board(board):
for row in board:
print(row)
print()
print_board(board)
# [5, 3, 0, 0, 7, 0, 0, 0, 0]
# [6, 0, 0, 1, 9, 5, 0, 0, 0]
# [0, 9, 8, 0, 0, 0, 0, 6, 0]
# [8, 0, 0, 0, 6, 0, 0, 0, 3]
# [4, 0, 0, 8, 0, 3, 0, 0, 1]
# [7, 0, 0, 0, 2, 0, 0, 0, 6]
# [0, 6, 0, 0, 0, 0, 2, 8, 0]
# [0, 0, 0, 4, 1, 9, 0, 0, 5]
# [0, 0, 0, 0, 8, 0, 0, 7, 9]
solve(board)
print_board(board)
# [5, 3, 4, 6, 7, 8, 9, 1, 2]
# [6, 7, 2, 1, 9, 5, 3, 4, 8]
# [1, 9, 8, 3, 4, 2, 5, 6, 7]
# [8, 5, 9, 7, 6, 1, 4, 2, 3]
# [4, 2, 6, 8, 5, 3, 7, 9, 1]
# [7, 1, 3, 9, 2, 4, 8, 5, 6]
# [9, 6, 1, 5, 3, 7, 2, 8, 4]
# [2, 8, 7, 4, 1, 9, 6, 3, 5]
# [3, 4, 5, 2, 8, 6, 1, 7, 9]
Where essentially the solve() function is changed so that:
it accepts a board parameter which is modified in-place
it returns if the board was solved or not
if the board is already solved it does not unwind the solution
(a print_board() helper function is included for simpler visualization)
(also the solution() has been changed to include a board parameter, to avoid relying on the global board definition, and the final block is outside of the main loop because it is looped there pointlessly).
The function does not need to return board because it gets modified in-place.
If one really needs the board to be returned, one can simply include it in the return.
Note that if you just replace the lone return inside the loops with a break, this does not seem to work.
If it does work, it will take a huge amount of time.
I suspect this will eventually lead to infinite looping because you just find some partial solution and unroll it back and forth forever (this assumption is based on replacing the return in my code with a break which yields a partial solution).
Related
Im trying to create a function that will transform a regular Matrix into CSR form (I don't want to use the scipy.sparse one).
To do this, I'm using a nested for-loop to run through a given matrix to create a new matrix with three rows.
The first row ('Values') should contain all non-zero values. The second ('Cols') should contain the column index for each number in 'Values'. The third row should contain the index value in 'Values' for the first non-zero value on each row.
My question regards the second and third rows:
Is there a way of getting the column ID for the element 'i' in the for-loop?
M=array([[4,0,39],
[0,5,0],
[0,0,7]])
def Convert(x):
CSRMatrix = []
Values = []
Cols = []
Rows = []
for k in x:
for i in k:
if i != 0:
Values.append(i)
Cols.append({#the column index value of 'i'})
Rows.append[#theindex in 'Values' of the first non-zero element on each row]
CSRMatrix.append(Values)
CSRMatrix.append(Cols)
CSRMatrix.append(Rows)
return(CSRMatrix)
Convert(M)
I'm not sure of what you want exactly for Cols.append() because of the way you commented it in the code between curly braces.
Is it a dict containing the index:value of all non 0 value? Or a list of sets containing the indexes of all non 0 values (which would be weird), or is it all the indexes of each row in your array?
Anyway I put the 2 most likely candidates (dict and list of indexes for each row) test each one and delete the unwanted one and if none are right please add some more specifics:
import numpy as np
m = np.array([[4,0,39],
[0,5,0],
[0,0,7]])
def Convert(x):
CSRMatrix = []
Values = []
Cols = []
Rows = []
for num in x:
for i in range(len(num)):
if num[i] != 0:
Values.append(num[i])
Cols.append({i:num[i]}) # <- if dict. Remove if not what you wanted
Rows.append(i)
Cols.append(i) # <- list of all indexes in the array for each row. Remove if not what you wanted
CSRMatrix.append(Values)
CSRMatrix.append(Cols)
CSRMatrix.append(Rows)
return(CSRMatrix)
x = Convert(m)
print(x)
enumerate() passes an index for every iteration.
Thereby the second row can be easily created by appending num2.
For the third row you have to check again if you have already added a value in that row. If not append num2 and set the non_zero check to False. For the next row non_zero check is set to True again.
def Convert(x):
CSRMatrix = []
Values = []
Cols = []
Rows = []
for num, k in enumerate(x):
non_zero = True
for num2, i in enumerate(k):
if i != 0:
Values.append(i)
Cols.append(num2)
if non_zero:
Rows.append(num2)
non_zero = False
CSRMatrix.append(Values)
CSRMatrix.append(Cols)
CSRMatrix.append(Rows)
return (CSRMatrix)
Here is a numpythonic implementation, use the nonzero method to directly obtain the row and column index of non-zero elements, and then use a comparison to generate a mask. Finally, use nonzero for the mask to get the row indices:
>>> M = np.array([[ 4, 0, 39],
... [ 0, 5, 0],
... [ 0, 0, 7]])
>>> r, c = M.nonzero()
>>> mask = np.concatenate(([True], r[1:] != r[:-1]))
>>> [M[r, c], c, *mask.nonzero()]
[array([ 4, 39, 5, 7]), array([0, 2, 1, 2]), array([0, 2, 3])]
Test of a larger array:
>>> a = np.random.choice(10, size=(8, 8), p=[0.73] + [0.03] * 9)
>>> a
array([[0, 0, 0, 0, 8, 0, 0, 1],
[1, 0, 5, 4, 0, 0, 9, 0],
[0, 0, 9, 0, 0, 0, 0, 1],
[0, 0, 0, 8, 9, 0, 0, 4],
[0, 0, 5, 0, 0, 6, 0, 0],
[0, 8, 0, 0, 0, 0, 0, 9],
[0, 0, 0, 0, 0, 0, 0, 9],
[0, 9, 0, 0, 0, 4, 0, 0]])
>>> r, c = a.nonzero()
>>> mask = np.concatenate(([True], r[1:] != r[:-1]))
>>> pp([a[r, c], c, *mask.nonzero()])
[array([8, 1, 1, 5, 4, 9, 9, 1, 8, 9, 4, 5, 6, 8, 9, 9, 9, 4]),
array([4, 7, 0, 2, 3, 6, 2, 7, 3, 4, 7, 2, 5, 1, 7, 7, 1, 5], dtype=int64),
array([ 0, 2, 6, 8, 11, 13, 15, 16], dtype=int64)]
I have a list of integers which I want to separate according to a certain condition. I want to get the sum and the count of the list elements, stopping when three or more consecutive elements are equal to 0; then the sum and count orders restart again from where they stopped.
For example, part of the list is:
[8, 2, 1, 1, 2, 0, 0, 0, 0, 0, 6, 0, 2, 0, 0, 0, 8, 0, 0, 2, 0, 0, 0, 6, 0, 0]
The process would be:
8, 2, 1, 1, 2 -> sum: 14, length: 5
0, 0, 0, 0, 0
6, 0, 2 -> sum: 8, length: 3
0, 0, 0
8, 0, 0, 2 -> sum: 10, length: 4
0, 0, 0
6, 0, 0 -> sum: 6, length: 3
So the output I want is:
[[14, 5], [8, 3], [10, 4], [6, 3]]
What I've written so far computes the sum okay, but my problem is that zeros within sections aren't counted in the lengths.
Current (incorrect) output:
[[14, 5], [8, 2], [10, 2], [6, 2]]
Code:
arr = [8, 2, 1, 1, 2, 0, 0, 0, 0, 0, 6, 0, 2, 0, 0, 0, 8, 0, 0, 2, 0, 0, 0, 6, 0, 0]
result = []
summed, count = 0, 0
for i in range(0, len(arr) - 2):
el, el1, el2 = arr[i], arr[i + 1], arr[i + 2]
if el != 0:
summed = summed + el
count = count + 1
if el == 0 and el1 == 0 and el2 == 0:
if summed != 0:
result.append([summed, count])
summed = 0
count = 0
elif i == len(arr) - 3:
summed = el + el1 + el2
count = count + 1
result.append([summed, count])
break
print(result)
It is quite hard to understand what your code does. Working with Strings seems more straightforward and readable, your output can be achieved in just two lines (thanks to #CrazyChucky for the improvement):
import re
arr = [8, 2, 1, 1, 2, 0, 0, 0, 0, 0, 6, 0, 2, 0, 0, 0, 8, 0, 0, 2, 0, 0, 0, 6, 0, 0]
# Convert to String by joining integers, and split into substrings, the separator being three zeros or more
strings = re.split(r'0{3,}', ''.join(str(i) for i in arr))
# Sums and counts using list comprehensions
output = [[sum(int(x) for x in substring), len(substring)] for substring in strings]
Output:
>>>output
>>>[[14, 5], [8, 3], [10, 4], [6, 3]]
Remember that readability is always the most important factor in any code. One should read your code for the first time and understand how it works.
If the full list contains numbers with more than one digit, you can do the following:
# Convert to String by joining integers, seperating them by a commade, and split into substrings, the separator being three zeros or more
strings = re.split(r',?(?:0,){3,}', ','.join(str(i) for i in arr))
# Make a list of numbers from those strings
num_lists = [string.split(',') for string in strings]
# # Sums and counts using list comprehensions
output = [[sum(int(x) for x in num_list), len(num_list)] for num_list in num_lists]
This answer is not so much to suggest a way I'd recommend doing it, as to highlight how clever Paul Lemarchand's idea of using a regular expression is. Without Python's re module doing the heavy lifting for you, you have to either look ahead to see how many zeros are coming (as in Prakash Dahal's answer), or keep track of how many zeros you've seen as you go. I think this implementation of the latter is about the simplest and shortest way you could solve this problem "from scratch":
input_list = [8, 2, 1, 1, 2, 0, 0, 0, 0, 0, 6, 0, 2, 0, 0, 0, 8, 0, 0, 2, 0, 0,
0, 6, 0, 0]
output_list = []
current_run = []
pending_zeros = 0
for num in input_list:
# If the number is 0, increment the number of "pending" zeros. (We
# don't know yet if they're part of a separating chunk or not.)
if num == 0:
pending_zeros += 1
# If this is the first nonzero after three or more zeros, process
# the existing run and start over from the current number.
elif pending_zeros >= 3:
output_list.append((sum(current_run), len(current_run)))
current_run = [num]
pending_zeros = 0
# Otherwise, the pending zeros (if any) should be included in the
# current run. Add them, and then the current number.
else:
current_run += [0] * pending_zeros
current_run.append(num)
pending_zeros = 0
# Once we're done looping, there will still be a run of numbers in the
# buffer (assuming the list had any nonzeros at all). It may have
# pending zeros at the end, too. Include the zeros if there are 2 or
# fewer, then process.
if current_run:
if pending_zeros <= 2:
current_run += [0] * pending_zeros
output_list.append((sum(current_run), len(current_run)))
print(output_list)
[(14, 5), (8, 3), (10, 4), (6, 3)]
One note: I made each entry in the list a tuple rather than a list. Tuples and lists have a lot of overlap, and in this case either would probably work perfectly well... but a tuple is a more idiomatic choice for an immutable data structure that will always be the same length, in which each position refers to something different. (In other words, it's not a list of equivalent items, but rather a well-defined combination of (sum, length).)
Use this:
a = [8, 2, 1, 1, 2, 0, 0, 0, 0, 0, 6, 0, 2, 0, 0, 0, 8, 0, 0, 2, 0, 0, 0, 6, 0,0]
total_list = []
i = 0
sum_int = 0
count_int = 0
for ind, ele in enumerate(a):
if ind < (len(a) - 2):
sum_int += ele
if sum_int != 0:
count_int += 1
if (a[ind] == 0) and (a[ind+1] == 0) and (a[ind+2] == 0):
if sum_int != 0:
count_int -= 1
total_list.append([sum_int, count_int])
sum_int = 0
count_int = 0
else:
sum_int += ele
count_int += 1
if sum_int != 0:
total_list.append([sum_int, count_int+1])
sum_int = 0
count_int = 0
print(total_list)
Hi I have a problem with changing the element of the second list. This program is for making bowling score chart.
I have two lists
rollA = [10, 6, 8, 3, 10, 10, 6, 7, 8, 10]
rollB = [0, 3, 0, 6, 0, 0, 0, 1, 2, 10]
In the program, I add the two lists in the same index, for example, I add 10 with 0, and 6 with 3 and 8 with 0 and so on. I want to make a program that changes the element of rollB into / when the element of the specific index of rollA is not 10, but the added sum of rollA and rollB of the specific index is 10. For example, if I add 8 and 2, the added sum will be 10, and I want to change the 2 into /.
for i in range(0, 10):
if rollA[i] != 10 and (rollA[i] + rollB[i] == 10):
rollB[i] == "/"
This is the program I devised so far, but the elements of the second list won't change if I make the code like this. How should I fix this program to function properly?
Using the zip() function we are iterating over rollA and rollB. Then if the conditions you mentioned - the sum of them are 10 and the element is not equal to 10, the element of the rollB is replaced with the /
rollA = [10, 6, 8, 3, 10, 10, 6, 7, 8, 10]
rollB = [0, 3, 0, 6, 0, 0, 0, 1, 2, 10]
for i, j in zip(rollA, rollB):
if i + j == 10 and i < 10:
rollB[rollB.index(j)] = '/'
Error is in rollB[i] == "/" it returns either True or False .The assignment symbol is =, not ==. The later one checks for matches. Change your code to :
for i in range(0, 10):
if rollA[i] != 10 and (rollA[i] + rollB[i] == 10):
rollB[i] = "/"
== is the equality check operator. In order to assign a value, you need to use the = operator:
rollB[i] = "/"
If you want a comprehension way:
rollA = [10, 6, 8, 3, 10, 10, 6, 7, 8, 10]
rollB = [0, 3, 0, 6, 0, 0, 0, 1, 2, 10]
rollB = ["/" if x + y == 10 and x < 10 else y for x,y in zip(rollA, rollB)]
You can do the following:
rollA = [10, 6, 8, 3, 10, 10, 6, 7, 8, 10]
rollB = [0, 3, 0, 6, 0, 0, 0, 1, 2, 10]
new_list = []
for count, val in enumerate(rollB):
if val + rollA[count] == 10:
new_list.append('/')
else:
new_list.append(val + rollA[count])
By creating an if and else statement within your enumerated (indexed) for loop.
check your demands and then change rollB[idx] = "/"
def my_func(rollA, rollB):
for idx, elem in enumerate(rollB):
rollB[idx] = "/" if (elem + rollA[idx] == 10) \
and (rollB[idx] > 0) else rollB[idx]
return rollA, rollB
my_func([10, 6, 8, 3, 10, 10, 6, 7, 8, 10],
[0, 3, 0, 6, 0, 0, 0, 1, 2, 10])
I have been trying to implement Sudoku in Python, but the backtracking is not working at all. When I input a 4x4 grid of 0's, I get output, but most of the time it fails to provide the result for a 3x3. This test case progresses correctly until it reaches the last element of the second row.
import math
solution=[[3,0,6,5,0,8,4,0,0],
[5,2,0,0,0,0,0,0,0],
[0,8,7,0,0,0,0,3,1],
[0,0,3,0,1,0,0,8,0],
[9,0,0,8,6,3,0,0,5],
[0,5,0,0,9,0,6,0,0],
[1,3,0,0,0,0,2,5,0],
[0,0,0,0,0,0,0,7,4],
[0,0,5,2,0,6,3,0,0]]
#solution=[[0 for x in range(4)] for y in range(4)]
N=9
row=0
col=0
def positionFound():
global row,col
for x in range(N):
for y in range(N):
if solution[x][y] is 0:
row,col=x,y
return row,col
return False
def isSafe(row,col,num):
global N
for c in range(N):
if solution[row][c] is num:
return False
for r in range(N):
if solution[r][col] is num:
return False
r=row-row%int(math.sqrt(N))
c=col-col%int(math.sqrt(N))
for x in range(r,r+int(math.sqrt(N))):
for y in range(c,c+int(math.sqrt(N))):
if solution[x][y] is num:
return False
return True
back=1
def sudoku(solution):
global row,col
if positionFound() is False:
print('SUCCESS')
for x in solution:
print(x)
return True
for number in range(1,N+1):
if isSafe(row,col,number):
solution[row][col]=number
if sudoku(solution) is True:
return True
solution[row][col]=0
return False
sudoku(solution)
for x in solution:
print(x)
OUTPUT:
[3, 1, 6, 5, 2, 8, 4, 9, 7]
[5, 2, 4, 1, 3, 7, 8, 6, 0]
[0, 8, 7, 0, 0, 0, 0, 3, 1]
[0, 0, 3, 0, 1, 0, 0, 8, 0]
[9, 0, 0, 8, 6, 3, 0, 0, 5]
[0, 5, 0, 0, 9, 0, 6, 0, 0]
[1, 3, 0, 0, 0, 0, 2, 5, 0]
[0, 0, 0, 0, 0, 0, 0, 7, 4]
[0, 0, 5, 2, 0, 6, 3, 0, 0]
The reason your backtracking isn't working is that you haven't implemented backtracking. Once you fail to place a number in a given location, you have no provision to return your [row, col] cursor to the previous position. You need to involve a way to know what the previous filled position was and resume with the next legal number for that position. Your recursion holds previous board positions in the stack, but you've lost the cursor position -- and your re-try loop assumes that it gets reset.
One strong possibility is to make row and col local variables, keeping them coordinated with the solution grid they describe. Make them part of the parameter passing, so the stack maintains those values for you.
If I have a list that is made up of indexes from a list of lists, how would I use an index collected from a value in that list and find out which list it is in?
Here is an example:
listolists = [
[0, 8, 4, 0, 7],
[3, 6, 0, 9, 0],
[4, 0, 3, 7, 0],
[7, 0, 7, 0, 6]
]
section1 = [listolists[0][0], listolists[0][1], listolists[1][0], listolists[1][1]]
section2 = [listolists[3][4], listolists[2][4], listolists[3][3], listolists[2][3]]
for c row in enumerate(listolists):
if 0 in row:
*if 1, 2, and 3 are in whichever "section"(section1 or section2) the 0 is in*
print ("Success")
The goal of this would be for the program to look at the index of the 0 that it has found. Then it should see if the 0's index matches up with any of the "sections." Then it should look in the section that the 0 is in and check if that list contains 1, 2, or 3. The part with the * around it is obviously incorrect and is the part that I need to find the correct syntax on. I have looked all over the internet and have been unable to find any help for this topic.
Thanks.
I have fixed up some typoes, avoided the scroll bar, shown the contents of section and section2, and added a print statement:
table = [
[0, 8, 4, 0, 7],
[3, 6, 0, 9, 0],
[4, 0, 3, 7, 0],
[7, 0, 7, 0, 6]
]
section1 = [table[0][0], table[0][1], table[1][0], table[1][1]]
print "section1:", section1
section2 = [table[3][4], table[2][4], table[3][3], table[2][3]]
print "section2:", section2
def mystery(query_value, sections, some_integers_whose_purport_is_unknown):
return "Not a clue"
qv = 0
for row_index, row in enumerate(table):
if qv in row:
# if 1, 2, and 3 are in X
# where X = whichever "section"(section1 or section2) the 0 is in
a_boolean = mystery(qv, (section1, section2), (1, 2, 3))
print "row_index: %r, condition_value: %r" % (row_index, a_boolean)
Output:
section1: [0, 8, 3, 6]
section2: [6, 0, 0, 7]
row_index: 0, condition_value: 'Not a clue'
row_index: 1, condition_value: 'Not a clue'
row_index: 2, condition_value: 'Not a clue'
row_index: 3, condition_value: 'Not a clue'
You need to explain what those condition_values are, and how they are derived. Including:
(1) what X = whichever "section"(section1 or section2) the 0 is in means ... noting that 0 appears in BOTH section1 and section2
(2) what 1, 2, and 3 are in X means: perhaps 1 in X and 2 in X and 3 in X, but that would be False for all cases (no 1, no 2, only one 3 in either of the sections).