calculate the sum of the intervals based on the binary array - python-3.x

I have two matrix:
Binary A = [[1, 0, 1, 0], [0, 0, 1, 0]];
Matrix of values B = [[100, 200, 300, 400], [400, 300, 100, 200]];
I want to calculate the sum of the intervals that are formed by the rows of the matrix A. For my exmpl. result will be follow: R = [[300, 0, 700, 0], [0, 0, 300, 0]] (generally, it is not necessary to set zeros [[300, 700], [300]] - it's right solution too)
I already wrote the code, but very very terrible (although it works correctly)
def find_halfsum(row1, row2):
i = 0
result = []
count = 0
for j in range(len(row1)):
if row1[j] == 1 and count == 0:
i = j
count += 1
elif row1[j] == 1:
count += 1
if count == 2:
if j == i + 1:
result.append(row2[i])
else:
result.append(sum(row2[i:j]))
i = j
count = 1
if j == len(row1) - 1:
result.append(sum(row2[i:j + 1]))
return result
Someone knows beautiful solutions (which will be faster)(preferably with the help of a numpy)?
Thanks

Not familiar with python, but I don't think you need that many lines
define halfSum(matrixA, matrixB):
sum = 0;
for i in range(len(matrixA)):
if matrixA[i] == 1:
sum += matrixB[i]
return sum;

You can use numpy.add.reduceat:
>>> A = np.array([[1, 0, 1, 0], [0, 0, 1, 0]])
>>> B = np.array([[100, 200, 300, 400], [400, 300, 100, 200]])
>>>
>>> [np.add.reduceat(b, np.flatnonzero(a)) for a, b in zip(A, B)]
[array([300, 700]), array([300])]

Related

How to check the distance between a specific element an index? Python3

A = [1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0]
B = 9
I want to find out the distances between the index[9] (B) and each of it's closest's 1's. For example, If we look at list A, we see that index 9 is this:
A = [1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0]
^
I would like to figure out the distances between B(index 9) and it's nearest 1's. For example, the nearest 1's in this case would be this:
A = [1, 0, 0, 0, 1, 0, 0, 1, 0, B, 0, 0, 1, 0]
^ ^
So in this case the output would be:
>> [2, 3] ##Since the distance between 1, 0, B is 2 and the distance between B, 0, 0, 1 is 3.
So far I've come up with the following code:
def checkDistance(A, B):
for i in A:
if i == 1:
#Check if it is the closest to B
#Check distance
Sadly I'm a beginner in python and I am struggling to finish. Any help would be much appreciated :)
def distance(lst,index):
c=[i for i,j in enumerate(lst) if j==1]
for k,l in zip(c[:-1],c[1:]):
if k < index < l:
return [index-k, l-index]
a = [1, 0, 0, 0, 1, 0, 0, 1, 0, B, 0, 0, 1, 0]
b = 9
distance(a, b)
Out: [2, 3]
You could use the following function. In this case, to make the function more abstract, you needn't force the value for the comparison to be 1 in the function.
In the function below, you do a for loop starting at the position you specified (in Python indexes start at 0, not at 1) and finishing when the list finishes.
The if statement compares element with the value of the list at a given position i
def checkDistance(lst,index,element):
counter = 0
results = []
for i in range(index,len(lst)):
if lst[i] == element:
print("Detected element at distance: " + str(counter))
results.append(counter)
counter += 1
return results

Finding maximal submatrix of all 1's - missing argument error

Program that finds the maximal rectangle containing only 1's of a binary matrix with the maximal histogram problem.
I am trying to do some tests on a code
def maximalRectangle(self, matrix):
if not matrix or not matrix[0]:
return 0
n = len(matrix[0])
height = [0] * (n + 1)
ans = 0
for row in matrix:
for i in range(n):
height[i] = height[i] + 1 if row[i] == '1' else 0
stack = [-1]
for i in range(n + 1):
while height[i] < height[stack[-1]]:
h = height[stack.pop()]
w = i - 1 - stack[-1]
ans = max(ans, h * w)
stack.append(i)
return ans
# Driver Code
if __name__ == '__main__':
matrix = [[0, 1, 0, 1],
[0, 1, 0, 1],
[0, 1, 1, 1],
[1, 1, 1, 1]]
print(maximalRectangle(matrix))
I get TypeError: maximalRectangle() missing 1 required positional argument: 'matrix' error
Solved by removing self and changing the print statement to:
print(maximalRectangle([
["1","0","1","0","0"],
["1","1","1","1","1"],
["1","1","1","1","1"],
["1","0","0","1","0"]]))

Find number of ‘+’ formed by all ones in a binary matrix

The question I have is similar to the problem found here: https://www.geeksforgeeks.org/find-size-of-the-largest-formed-by-all-ones-in-a-binary-matrix/
The difference is the '+' must have all other cells in the matrix to be zeros. For example:
00100
00100
11111
00100
00100
This will be a 5x5 matrix with 2 '+', one inside another.
Another example:
00010000
00010000
00010000
11111111
00010000
00010010
00010111
00010010
This matrix is 8x8, and will have 3 '+', one of it is the small 3x3 matrix in the bottom right, and the other 2 is formed from the 5x5 matrix, one inside another, similar to the first example.
Using the code from the link above, I can only get so far:
M = [[0, 0, 0, 1, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0, 0],
[0, 0, 0, 1, 0, 0, 0, 0], [1, 1, 1, 1, 1, 1, 1, 1],
[0, 0, 0, 1, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0, 1, 0],
[0, 0, 0, 1, 0, 1, 1, 1], [0, 0, 0, 1, 0, 0, 1, 0]]
R = len(M)
N = len(M)
C = len(M[0])
left = [[0 for k in range(C)] for l in range(R)]
right = [[0 for k in range(C)] for l in range(R)]
top = [[0 for k in range(C)] for l in range(R)]
bottom = [[0 for k in range(C)] for l in range(R)]
for i in range(R):
top[0][i] = M[0][i]
bottom[N - 1][i] = M[N - 1][i]
left[i][0] = M[i][0]
right[i][N - 1] = M[i][N - 1]
for i in range(R):
for j in range(1,R):
if M[i][j] == 1:
left[i][j] = left[i][j - 1] + 1
else:
left[i][j] = 1
if (M[j][i] == 1):
top[j][i] = top[j - 1][i] + 1
else:
top[j][i] = 0
j = N - 1 - j
if (M[j][i] == 1):
bottom[j][i] = bottom[j + 1][i] + 1
else:
bottom[j][i] = 0
if (M[i][j] == 1):
right[i][j] = right[i][j + 1] + 1
else:
right[i][j] = 0
j = N - 1 - j
n = 0
for i in range(N):
for j in range(N):
length = min(top[i][j], bottom[i][j], left[i][j], right[i][j])
if length > n:
n = length
print(n)
Currently, it returns the output of the longest side of the '+'. The desired output would be the number of '+' in the square matrix.
I am having trouble checking for all other cells in the matrix to be zeros, and finding a separate '+' if there is one in the entire matrix.
Any help is greatly appreciated.
I don't want to spoil the fun of solving this problem, so rather than a solution, here are some hints:
Try to write a sub-routine (a function), that given a square matrix as input, decides whether this input matrix is a '+' or not (say the function returns a '1' if it is a '+' and a '0' otherwise).
Modify the function from 1. so that you can give it as input a submatrix of the full matrix (in which you want to count '+'). More specifically, the input could be the coordinate of the upper left entry of the submatrix and its size. The return value should be the same as for 1.
Can you write a loop that examines all the submatrices of your given matrix and counts the ones that are '+' using the function from 2.?
Here are some minor remarks: The algorithm that this leads to runs in polynomial time (in the dimension of the input matrix), so basically it shouldn't take to long.
I haven't thought about it too much, but probably the algorithm can be made more efficient.
Also, you should maybe think about whether or not you count a '1' that is surrounded by '0's as a '+' or not.

Dynamic Programming: Tabulation of a Recursive Relation

The following recursive relation solves a variation of the coin exchange problem. Count the number of ways in which we can sum to a required value, while keeping the number of summands even:
def count_even(coins, num_coins, req_sum, parity):
if req_sum < 0:
return 0
if req_sum == 0 and not parity:
return 1
if req_sum == 0 and parity:
return 0
if num_coins == 0:
return 0
count_wout_high_coin = count_even(coins, num_coins - 1, req_sum, parity)
count_with_high_coin = count_even(coins, num_coins, req_sum - coins[num_coins - 1], not parity)
return count_wout_high_coin + count_with_high_coin
This code would yield the required solution if called with parity = False.
I am having issues implementing a tabulation technique to optimize this algorithm. On a first attempt I tried to follow the same pattern as for other DP problems, and took the parity as another parameter to the problem, so I coded this triple loop:
def count_even_tabulation(S, m, n):
if m <= 0 or n < 0:
return 0
if n == 0:
return 1
table = [[[0 for x in range(m)] for x in range(n + 1)] for x in range(2)]
for j in range(m):
table[0][0][j] = 1
table[1][0][j] = 0
for p in range(2):
for i in range(1, n + 1):
for j in range(m):
y = table[p][i][j - 1] if j >= 1 else 0
x = table[1 - p][i - S[j]][j] if i - S[j] >= 0 else 0
table[p][i][j] = x + y
return table[0][n][m - 1]
However, this approach is not creating the right tables for parity equal to 0 and equal to 1:
[1, 1, 1]
[0, 0, 0]
[0, 0, 0]
[0, 0, 0]
[0, 0, 0]
[0, 0, 0]
[1, 1, 1]
[0, 1, 1]
[0, 0, 1]
[0, 0, 0]
How can I adequately implement a tabulation approach for the given recursion relation?

how to fix python fibonacci sequence script?

My assignment is to create a function that produces 3 lists of the numbers in the fibonacci sequence starting at 0. Here is my code so far.
def fibList(n):
a = 0; b = 1; fibList = []
if n <= 0:
return
elif n == 1:
fibList = [a]
elif n == 2:
fibList = [a,b]
else:
for i in range(0,n):
a, b = b, a + b
fibList.append(b)
return fibList
def main():
print (fibList(4))
print (fibList(10))
print (fibList(-4))
what i want my output to look like is [0,1,1,2] for 4, [0,1,1,2,3,5,8,13,21,34,55] for 10, and [] for -4
My issue begins with fibList(4) currently giving an output of [1, 2, 3, 5] and fibList(10) gives an output of [1, 2, 3, 5, 8, 13, 21, 34, 55, 89] and for -4 I get "None" instead of a [].
If I type in fibList(1) I get [0] and for fibList(2) I get [0, 1], but when i test fibList(3) the first 0 and 1 are lost, giving me [1,2,3]
How would I go about making it so any number above 3 starts with [0, 1, 1, 2...]? My main issue is getting the 0 and 1 to be the first two numbers in the sequence and getting fibList(-4) to produce a [].
any help or tips would be greatly appreciated :-)
All that you are missing is to add an empty list in the case of less than or equal to zero, and recurse correctly over your range of Fibonacci numbers greater than 2. Making those small changes like so:
def fibList(n):
if n <= 0:
fibnums = []
elif n == 1:
fibnums = [0]
elif n >= 2:
fibnums = [0, 1]
for i in range(2,n):
fibnums.append(fibnums[i-1]+fibnums[i-2])
return fibnums
Note that this recursive method can get quite slow for large numbers, if that is of concern to you with your program. Best of luck!
With these changes,
print (fibList(4)) => [0, 1, 1, 2]
print (fibList(10)) => [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
print (fibList(-4)) => []
You did not quite define your function. Should the resulting list have n values [f(0), ..., f(n-1)] or n+1 values [f(0), ..., f(n)]? Your examples are contradictory: the 'expected' output for 4 has 4 values ending with f(3) while that for 10 has 11 values ending with f(10).
I am going to assume that the latter is correct. Here is a revised version of your fast iterative solution. (If my assumption is wrong, stop the range at n instead of n+1.)
def fibs(n):
"Return [fib(0), ..., fib(n)."
ret = [0, 1] # fib(0), fib(1)
a, b = ret
if n <= 1:
return ret[:n+1]
else:
for i in range(2, n+1):
a, b = b, a+b # b = f(i)
ret.append(b)
return ret
print(fibs(-4), fibs(0), fibs(2), fibs(4), fibs(10))
#
[] [0] [0, 1, 1] [0, 1, 1, 2, 3] [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]

Resources