The truth value of array is ambigous - arrays

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

Identify rows of one numpy array that gave rise to another numpy array

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]]

How to get depth of tree of arrays given total num items and max array size?

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))

How to get min/max value indices in a Ruby array

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]

Split array in groups of n, m, o groups or more

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]]

Merge arrays inside of arrays

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.

Resources