Numpy: Truth comparison of multidimensional arrays - python

So I am writing a sudoku solver using a 9x9 array for the grid and a 9x9x9 array for its possibilities. Due to the backtracking algorithm I am using, I have to check whether the Sudoku is still valid, aka:
If there is a field that does not contain a number and has no possibilities left, return False.
So far I implemented that as follows:
for j in range(9):
for i in range(9):
if puzzle[j,i] == 0 and (solving[j,i] == 0).sum() == 9:
return False
return True
If the square at (j,i) contained, for example, the options 2, 3 and 7, the according possibility array would be:
solving[j,i] = array([0, 2, 3, 0, 0, 0, 7, 0, 0], dtype = int8)
I am trying to avoid such loops here and elsewhere in my solver. I tried this as follows:
solving[where(puzzle == 0)]
This returned an n x 9 array, where n is the amount of empty squares in my puzzle. I want the function to return False if any of the n arrays with shape 1x9 is exactly equal to
array([0,0,0,0,0,0,0,0,0], dtype = int8)
However, I did not have any success with various tries including .any() and .all() experiments. This is the latest code I was using:
def is_valid(self, puzzle, solving):
if (solving[py.where(puzzle == 0)].all() == 0).sum() > 0:
return False
return True
... which always returns False. What's the proper way to code this?

I think the following is the check you want to do:
np.all(puzzle | np.any(solving, axis=-1)
This returns True if all cells either have a value assigned (puzzle), or (|) have at least a non-zero entry in solving (np.any(solving, axis=-1)).

Related

What does sum(x%2==0) mean?? (python)

import numpy as np
x = np.array([1, -1, 2, 5, 7])
print(sum(x%2==0))
This is the code, and I can't understand what does ' sum(x%2==0) ' mean.
Does it mean to sum even number?
I'm studying for school test and My professor said output of the above code is 1.
But I can't understand what does ' sum(x%2==0)' mean..
x % 2 == 0 will change your array to [False, False, True, False, False]
Because every element will be converted to a boolean, which represents, if the number is even or odd
Then the sum gets evaluated, where False = 0 and True = 1
0 + 0 + 1 + 0 + 0 = 1
import numpy as np
x = np.array([1, -1, 2, 5, 7])
# step 1: create an intermediate array which contains the modulo 2 of each element (if the element is even it will be True, otherwise False)
y = x % 2 == 0 # [False, False, True, False, False]
# step 2: sum the intermediate array up. In this case the False values count as 0 and the True values as 1. There is one True value so the sum is 1
z = sum(y) # 1
For your purposes, here's an explanation. For Stack Overflow's purposes, I'm recommending to close this question as it's more coding help than a novel coding question.
The operations in this expresssion are as follows:
# operation 1
intermediate_result_1 = x%2
# operation 2
intermediate_result_2 = (intermediate_result_1 == 0)
# operation 3
sum(intermediate_result_2)
Operation 1: the modulo operator essentially returns the remainder when the first term is divided by the second term. Most basic mathematical operations (e.g. +,-,*,/,%,==,!=, etc) are implemented element-wise in numpy, which means that the operation is performed independently on each element in the array. Thus, the output from operation 1:
intermediate_result_1 = np.Array([1,1,0,1,1])
Operation 2: same for the equality operator ==. Each element of the array is compared to the right-hand value, and the resulting array has True (or 1) where the equality expression holds, and False (or 0) otherwise.
intermediate_result_2 = np.Array([0,0,1,0,0])
Operation 3: Lastly, the default sum() operator for a numpy array sums all values in the array. Note that numpy provides its own sum function which allows for summing along individual dimensions. Quite evidently the sum of this array's elements is 1.
numpy makes it easy for you to operate on the array object
as many answers already suggest that
x%2==0 returns [False, False, True, False, False]
but if you are still confused then try to understand it like this
lets make a function which checks if a value is even or not.
def is_even(ele):
return ele%2==0
then we use the map function
map() function returns a map object(which is an iterator) of the
results after applying the given function to each item of a given
iterable (list, tuple etc.)
NOTE: copied from GeeksforGeeks
then we take a simple list and map it with this function like so:
l=[1, -1, 2, 5, 7] # this is not a np array
print(map(is_even, l)) # this prints [False, False, True, False, False]
print(sum(map(is_even, l))) # this prints 1

how to optimize this code and make it faster on python

determine whether all values of a certain range are used in the array and at the same time there are no values in the array that will not be in the range. For example, the range is [1,5], and the array is [1,2,3,4,5] - everything is correct. Or the range [1,5], and the array [1,2,1,2,3,3,4,5] - everything is also true.
the range is [1,5], and the array [0,2,2,3,3,4,5] is already incorrect since there is no 0 in the range, and there is also a 1 missing in the array
I did this, but it's slow with big values and terrible:
def func(segment, arr):
segment_arr = []
for i in range(segment[0], segment[1] + 1):
segment_arr.append(i)
arr_corr = True
if min(arr) != min(segment_arr) or max(arr) != max(segment_arr):
arr_corr = False
else:
for i in range(len(arr)):
if arr[i] in segment_arr:
for a in range(len(segment_arr)):
if segment_arr[a] in arr:
continue
else:
arr_corr = False
else:
arr_corr = False
return arr_corr
To test if every member of a list/array/range x is in another list/array y:
all(e in y for e in x)
to test if only members of a list/array/range x are in another list/array y:
all(e in x for e in y)
The speed of these operations depends on the container type. all short circuits, so it will be faster when the test fails. in is very fast on set but can be slow on lists. Creation of set is slow and can eliminate the gains from the speed of doing in on a set. If you are working with numpy arrays, it will be faster to use numpy's intersect.
This should do what you're asking. If it is too slow, you will need to optimize the types. At that point, you will probably need to edit the question to give some clear examples of when it is too slow and what your constraints are:
def func(segment, arr):
return all(e in segment for e in arr) and all(e in arr for e in segment)
def func(segment, arr):
return set(list(range(segment[0], segment[1]+1))) == set(arr)
Build a set from allowed values
If the resulting set has "full" length, all is correct.
left, right = [1, 5]
values = [0, 2, 3, 4, 5]
values_are_correct = (
len({i for i in values if left <= i <= right}) == (right - left) + 1
)

Check if an Integer Array can be Equalized using Recursion in Python

Given an integer array of size 5 with arbitrary positive values and m, I am tasked to create a program that will check if it is possible to equalize this array (all integers are equal) with the following process:
With m being the current position, it will jump to another integer, and by jumping, the integer in that position gets reduced based of the distance from this integer's position from m.
Example: [2, 2, 4, 2, 2] with m = 0 (first position)
we jump to the third position to equalize the integer array, that means 4 minus (distance from current position to 4)
v (m = 0)
[2, 2, 4, 2, 2]
v jump to index 2 (3rd position)
[2, 2, (4 - abs(2-0)), 2, 2]
= [2, 2, 2, 2, 2] (all integer is equal)
since there is a way to equalize the array, return True.
Integers in the array must only be positive. If there is no possible way to equalize the array, return False.
I managed to make a code but it's not working for the hidden cases (this is a problem from our school).
def canEqual(array, m):
if min(array) == max(array): return True # Array can be Equalized, Return True
for integer in array:
if integer < 1: return False # If there is an integer in the array
# less than 1, then return False since
# it cannot be.
for index, integer in enumerate(array): # Treats the min value in the array as the
if integer > min(array) and index != m: # basis for equalizing. If an element is greater
temp = array[:] # than the minimum, the program will jump to this position
temp[index] = integer-abs(m-index) # and the cycle continues until either the array
# is equalized or there exists a non positive integer.
if canEqual(temp, index): return canEqual(temp, index)
I'm not really sure if my approach to this problem is correct.
Take a look at that (and try to understand it better by investigate it), uncomment the two prints to understand better the process, and ask for clarifications if something not make sense to you.
def canEqual(cur_arr, m):
if min(cur_arr) < 0:
return False
if min(cur_arr) == max(cur_arr):
return True
else:
for iter, item in enumerate(cur_arr):
if iter!=m:
cur_arr[iter] = cur_arr[iter]-abs(m-iter)
# print(iter)
# print(cur_arr)
if canEqual(cur_arr, iter):
return True
else:
cur_arr[iter] = cur_arr[iter]+abs(m-iter)
return False
print(canEqual([2, 2, 4, 2, 2], 2))
output:
True

function `any()` applied to several arrays rather than just one

I want to apply the function any() to all the rows of a matrix at the same time.
If I use any() with a vector, of course it will return True (or 1 in my case) whenever any element would return True:
import numpy as np
print any(np.array([0,0,0,1]))*1
Now suppose I have a matrix instead. If I want to obtain a vector with 1 and 0 depending on whether each element of the matrix would return True when taken alone, I can do it with a for loop:
matrix=np.array([[0,0,0],[0,0,1],[0,1,0]])
result=np.zeros(len(matrix)).astype('int')
i=0
for line in matrix:
result[i]=any(matrix[i])
i+=1
print result
However, this method does not seem very practical, because the elements of the matrix will be handled once at a time with the for loop. Is there a better way to extend any to a matrix input, in such a way that it returns a vector of several 1 and 0 as above?
Note that I do not want to use matrix.any() because it will just return a single True or False statement, whereas I want it to be applied to each individual element of the matrix.
numpy.any(matrix, axis=1)
numpy.any already has the functionality you want.
You can do this:
import numpy as np
matrix = np.array([[0, 0, 0], [0, 0, 1], [0, 1, 0]])
matrix_sums = np.sum(matrix, axis=1)
are_truthy_matrix_sums = matrix_sums > 0
print are_truthy_matrix_sums
We use np.sum to simplify the matrix to a 1D array with the sums, before comparing these sums against 0 to see if there were any truthy values in these rows.
This prints:
[False True True]

How to check if an array is multidimensional

I am trying to write a code to check if n is the maximum of the array A if it is return True if it isnt return False but I have two conditions if the value is a multidimentional or unidimentional I don't know how to write that:
if [A is unidimentional]:
maximum=A[0]
for i in range(A.shape[0]):
if max(A[i],maximum)==A[i]:
maximum=A[i]
if max(n,maximum)!=n:
return False
return True
else:
maximum=A[0][0]
for i in range(A.shape[0]):
for j in range(A.shape[1]):
if max(A[i][j],maximum)==A[i][j]:
maximum=A[i][j]
if max(n,maximum)!=n:
return False
return True
if someone knows how I can write that condition it would be very helpful Thanks
def is_multidimensional(A):
return A.ndim > 1
Try the following:
import numpy as np
my_array = np.array([[1,2,3],[4,5,6]])
d = len(my_array.shape)
print(d) # Output: 2
Now, you can test against d, if its value is 2, then your array is 2 dimensions.
If you just want to check whether an array is multidimensional, just check the length of the shape of the array
arr = np.array([[1,2,3],[4,5,6],[7,8,9]])
print len(arr.shape)
If that value is greater than 1, then your array is multidimensional
But if all you want to do is check whether n is equal to the largest value in the array, you dont need to manually implement that. np.amax will tell you that:
largest_element = np.amax(arr)
if n == largest_element:
return True
else:
return False
If the matrix is multidimensional then max will return a list.
Otherwise it will return an int.
if type(max(A))== list:
# do some stuff for handling multidimensional
else:
# do some stuff for handling unidimensional
Or you could use numpy in which case
np.max(A)
returns an int regardless of A's dimensions.
A =[[1,2,3,4],[1,4,5,6]]
max(A)
Out[57]: [1, 4, 5, 6]
np.max(A)
Out[64]: 6

Categories

Resources