I have gotten this error a few times in my code and I've never come across it before. Sudoku is a 2d numpy array. Can anyone tell me why and how to fix it?
An example of the sudoku array would be
sudoku = np.array([[0, 2, 4, 7, 6, 3, 5, 9, 1], [3, 9, 7, 4, 5, 0, 8, 2, 6], [8, 5, 6, 9, 2, 0, 0, 4, 7], [0, 8, 9, 5, 3, 6, 7, 1, 4], [7, 3, 1, 2, 9, 4, 6, 5, 8], [6, 4, 5, 8, 1, 7, 9, 3, 2], [4, 7, 2, 3, 8, 9, 1, 6, 5], [9, 1, 8, 6, 4, 5, 2, 7, 3], [5, 6, 3, 1, 7, 2, 4, 8, 9]])
import numpy as np
import copy
global subgrids
sudoku = np.array([[0, 2, 4, 7, 6, 3, 5, 9, 1], [3, 9, 7, 4, 5, 0, 8, 2, 6], [8, 5, 6, 9, 2, 0, 0, 4, 7], [0, 8, 9, 5, 3, 6, 7, 1, 4], [7, 3, 1, 2, 9, 4, 6, 5, 8], [6, 4, 5, 8, 1, 7, 9, 3, 2], [4, 7, 2, 3, 8, 9, 1, 6, 5], [9, 1, 8, 6, 4, 5, 2, 7, 3], [5, 6, 3, 1, 7, 2, 4, 8, 9]])
ad = sudoku.tolist()
frontier = sudoku
subgrids = []
moves = [1,2,3,4,5,6,7,8,9]
columns = []
for i in range(0,9):
columns.append([row[i] for row in sudoku])
def is_possible(sudoku):
for i in range(0, 9):
for j in range(1, 10):
if np.any([ad[i].count(j) > 1] or [columns[i].count(j) > 1]):
return False
return True
sc = copy.deepcopy(ad)
for i in range(0,9,3):
for j in range(0,9,3):
subgrids.append(sc[i][j:j+3]+sc[i+1][j:j+3]+sc[i+2][j:j+3])
def get_next_zero(sudoku):
for i in range(0,9):
for j in range(0,9):
if sudoku[i][j] == 0:
index = [i,j] #i is row index, j is column index
possible_values(index,subgrids)
return True
def is_solution(sudoku):
if is_possible(sudoku) == False:
return False
for i in range(0,9):
for j in range(0,9):
if sudoku[i][j] == 0:
return False
return True
def possible_values(ind,grid):
possible_num = []
row = [a for a in sudoku[ind[0]]]
row = list(row)
column = []
for i in range(0,9):
column.append(sudoku[i][ind[1]])
column = list(column)
if ind[0] < 3:
if ind[1] < 3:
sub = grid[0]
elif 2 < ind[1] < 6:
sub = grid[1]
else:
sub = grid[2]
if 2 < ind[0] < 6:
if ind[1] < 3:
sub = grid[3]
elif 2 < ind[1] < 6:
sub = grid[4]
else:
sub = grid[5]
if ind[0] > 5:
if ind[1] < 3:
sub = grid[6]
elif 2 < ind[1] < 6:
sub = grid[7]
else:
sub = grid[8]
sub = list(sub)
for num in moves:
if num not in row and num not in column and num not in sub:
possible_num.append(num)
solver(possible_num, ind)
def solver(actions, where):
if len(actions) < 1:
np.delete(frontier,len(frontier)-1)
else:
for action in actions:
sudoku[where[0]][where[1]] = action
new_state = sudoku
if is_possible(new_state) == True:
np.append(frontier,new_state)
else:
np.delete(frontier,sudoku)
new_state = frontier.pop()
sudoku_solver(new_state)
def sudoku_solver(sudoku):
if is_possible(sudoku) == False:
print (np.full((9,9),-1))
elif is_solution(sudoku) == True:
print(sudoku)
else:
get_next_zero(sudoku)
sudoku_solver(sudoku)
for num in moves:
if num not in row and num not in column and num not in sub:
possible_num.append(num)
solver(possible_num, ind)
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
Another point in the code too
def is_solution(sudoku):
if is_possible(sudoku) == False:
return False
for i in range(0,9):
for j in range(0,9):
if sudoku[i][j] == 0:
return False
return True
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
Related
I think I'm missing something obvious. Consider the following code:
import numpy as np
a = np.array([[ 0, 2, 0, 5, 4, 6, 2, 4],
[ 3, 4, 0, 1, 0, 7, 4, 6],
[ 2, 6, 3, 5, 2, 5, 5, 8],
[ 0, 1, 0, 8, 0, 5, 8, 10],
[ 7, 9, 2, 7, 0, 6, 7, 2],
[ 0, 1, 4, 9, 0, 7, 9, 9],
[ 0, 6, 7, 5, 6, 2, 4, 13],
[ 0, 1, 1, 4, 1, 3, 2, 3]]
# isolate columns 2,3,6,7
mask = [False,False, True, True,False,False, True, True]
b = a[:,mask]
# determine rows of b having unique elements
s = np.sort(b, axis=1)
c = b[~(s[:,:-1] == s[:,1:]).any(1)]
c looks like:
c = [[ 0, 5, 2, 4],
[ 0, 1, 4, 6],
[ 7, 5, 4, 13],
[ 1, 4, 2, 3]]
QUESTION: How do I 'recover' the rows of a that gave rise to the rows of c?
The output should be like:
d = [[ 0, 2, 0, 5, 4, 6, 2, 4],
[ 3, 4, 0, 1, 0, 7, 4, 6],
[ 0, 6, 7, 5, 6, 2, 4, 13],
[ 0, 1, 1, 4, 1, 3, 2, 3]]
Given this divide algorithm and sample data:
const data = [
1, 2, 3, 4, 5, 6, 7, 8, 9, 0,
1, 2, 3, 4, 5, 6, 7, 8, 9, 0,
1, 2, 3, 4, 5, 6, 7, 8, 9, 0,
1, 2, 3, 4, 5, 6, 7, 8, 9, 0,
1, 2, 3, 4, 5, 6, 7, 8, 9, 0,
1, 2, 3, 4, 5, 6, 7, 8, 9, 0,
1, 2, 3, 4, 5, 6, 7, 8, 9, 0,
1, 2, 3, 4, 5, 6, 7, 8, 9, 0,
1, 2, 3, 4, 5, 6, 7, 8, 9, 0,
1, 2, 3, 4, 5, 6, 7, 8, 9, 0
]
function divide(data, size) {
const result = []
for (let i = 0; i < data.length; i += size) {
const chunk = data.slice(i, i + size);
result.push(chunk)
}
if (result.length > size) {
return divide(result, size)
}
return result;
}
const result = divide(data, 5);
console.log(result)
How do you calculate the number of levels in the resulting tree? In this case of block size 5, I think there are 3 are 4 levels about, but what is the equation to use so you don't have to compute the actual tree? Basically getDepth(numItems, blockSize)?
Every recursive call reduces the input size by a factor of blocksize.
Starting with your example of 100 items. This is grouped into 20, these 20 are grouped into 4 and the algorithm ends.
The expression that capture this is log with a base of blocksize.
f(n,m) = ceil(log_base_m(n))
The depth of the example tree is
ceil(log5(99))
In general:
ceil(logchunksize(datasize-1))
arr = [4, 9, 0, -3, 16, 7]
Is there any simple way to find the indicies of the lowest x elements? Something like this?
arr.min_index(4)
arr.each_index.min_by(x) { |i| arr[i] }
or
arr.each_with_index.min(x).map(&:last)
Demo:
> arr, x = [4, 9, 0, -3, 16, 7], 4
=> [[4, 9, 0, -3, 16, 7], 4]
> arr.each_index.min_by(x) { |i| arr[i] }
=> [3, 2, 0, 5]
> arr.each_with_index.min(x).map(&:last)
=> [3, 2, 0, 5]
Here's one simple way to do it:
class Array
def min_index(n)
each_with_index.sort.map(&:last).first(n)
end
end
>> arr = [4, 9, 0, -3, 16, 7]
>> arr.min_index(4)
#> [3, 2, 0, 5]
>> [4, 2, 2].min_by(2)
#> [1, 2]
Is there any method to split an array like this?
[1, 2, 3, 4, 5, 6, 7, 8, 9].split(3, 4, 2)
#=> [[1, 2, 3],[4, 5, 6, 7],[8, 9]]
Immutable version with λ:
▶ splitter = ->(array, *parts) do
parts.reduce([[], 0]) do |acc, i|
right = acc.last + i
[acc.first << (acc.last...right), right]
end.first.map { |r| array[r] }
end
#⇒ #<Proc:0x0055ae3d9ae7c8#(pry):18 (lambda)>
▶ splitter.((1..9).to_a, 3, 4, 2)
#⇒ [[1, 2, 3], [4, 5, 6, 7], [8, 9]]
No, there is none, but you can easily write one yourself.
class Array
def in_groups_of_n(*sizes)
sizes.map(&method(:shift))
end
end
Example:
arr = [1, 2, 3, 4, 5, 6, 7, 8, 9]
arr.in_groups_of_n(3, 4, 2)
# => [[1, 2, 3], [4, 5, 6, 7], [8, 9]]
Demonstration
In case you want a none-destructive version, you can use a dup method:
class Array
def in_groups_of_n(*sizes)
duplicate = dup
sizes.map { |size| duplicate.shift(size) }
end
end
arr = [1, 2, 3, 4, 5, 6, 7, 8, 9]
arr.in_groups_of_n(3,4,2)
# => [[1, 2, 3], [4, 5, 6, 7], [8, 9]
arr
# => [1, 2, 3, 4, 5, 6, 7, 8, 9]
Demonstration
Here's a naive Array implementation:
class Array
def multi_split(*sizes)
r = []
e = self.each
sizes.each do |size|
t = []
size.times do
t << e.next
end
r << t
end
r
end
end
p [1, 2, 3, 4, 5, 6, 7, 8, 9].multi_split(3, 4, 2)
# [[1, 2, 3], [4, 5, 6, 7], [8, 9]]
#Stefan mentioned it might make sense to implement it on Enumerable:
module Enumerable
def multi_split(*sizes)
Enumerator.new do |yielder|
e = self.each
sizes.each do |size|
yielder << Array.new(size){ e.next }
end
end
end
end
p [1, 2, 3, 4, 5, 6, 7, 8, 9].multi_split(3, 4, 2).to_a
# [[1, 2, 3], [4, 5, 6, 7], [8, 9]]
Another option (lossless in event the splits are not equal to the array size
def split_at(arr,splits)
rest = arr.last(arr.size - splits.reduce(:+))
enum = arr.to_enum
splits.map do |n|
n.times.map { enum.next }
end.concat(rest.empty? ? [] : [rest])
end
Then called as
split_at (1..9), [3,4,2]
#=> [[1, 2, 3], [4, 5, 6, 7], [8, 9]]
split_at (1..22), [3,4,2]
#=> [[1, 2, 3], [4, 5, 6, 7], [8, 9], [10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22]]
Example
class Array
def split_by_number(*sizes)
sizes.each_with_object([]) { |n,a| a << [a.empty? ? 0 : a.last.sum, n] }.
map { |start, nbr| self[start, nbr] }
end
end
[1, 2, 3, 4, 5, 6, 7, 8, 9].split_by_number 3, 4, 2
#=> [[1, 2, 3], [4, 5, 6, 7], [8, 9]]
Note that
[3, 4, 2].each_with_object([]) { |n,a| a << [a.empty? ? 0 : a.last.sum, n] }
#=> [[0, 3], [3, 4], [7, 2]]
I have this array:
a = [[1,2,3,4,5],[3,5,6,8,12,45],[3,2,1,5,7,9,10,11],[3,5,6,8,2,1,3,4,6]]
I want to merge its inner arrays so that they become:
a = [[1,2,3,4,5,3,5,6,8,12,45],[3,2,1,5,7,9,10,11,3,5,6,8,2,1,3,4,6]]
How can I do this?
You need to do
a = [
[1, 2, 3, 4, 5],
[3, 5, 6, 8, 12, 45],
[3, 2, 1, 5, 7, 9, 10, 11],
[3, 5, 6, 8, 2, 1, 3, 4, 6]
]
a.each_slice(2).map(&:flatten)
# => [
# [1, 2, 3, 4, 5, 3, 5, 6, 8, 12, 45],
# [3, 2, 1, 5, 7, 9, 10, 11, 3, 5, 6, 8, 2, 1, 3, 4, 6]
# ]
Read the method each_slice(n)
Iterates the given block for each slice of n elements. If no block is given, returns an enumerator.