Related
I have this method which returns the max sum of the path from top left to bottom right (can move only to the right or bottom).
def max_path(grid):
N = len(grid)
M = len(grid[0])
sum = [[0 for i in range(M + 1)] for i in range(N + 1)]
for i in range(1, N + 1):
for j in range(1, M + 1):
sum[i][j] = (max(sum[i - 1][j], sum[i][j - 1]) + grid[i - 1][j - 1])
return sum[N][M]
matrix = [[1, 2, 3], [3, 4, 5]]
print(max_path(matrix))
output : 1 + 3 + 4 + 5 = 13
But what I want to get is also the coordinates of the points of the path:
[(0,0) (1,0) (1,1) (1,2)]
You can try the below code to get your job done.
from itertools import permutations, product
def get_max_sum(table):
height, width = len(table), len(table[0])
sum_, *pos = max((sum(table[x][y] for x, y in zip(*pairs)), *zip(*pairs))
for pairs in product(
permutations(range(height)),
([*range(i, width), *range(i)] for i in range(width))))
return (sum_, *sorted(pos))
sum_, *pos = get_max_sum(
[[1, 2, 3],
[2, 3, 5],
[4, 9, 16]]
)
Output:
20 #maximum sum
(0, 1) (1, 0) (2, 2) #co -ordinates
The variable sum after the nested-for loops (as written in your code) is
[0, 0, 0, 0],
[0, 1, 3, 6],
[0, 4, 8, 13]
You can work out the coordinates of the max sum by having a initial "pointer" at the bottom right corner (i=1, j =2, ignoring the zeros), and comparing the values that is on the top (i=0, i=2) and on the left (i=1, j=1). Since 8 is larger than 6, we move the "pointer" to the left, and now i=1, j=1.
4 is larger than 3, so we move the pointer to 4 (i=1, j=0)
1 is larger than 0, so we move the pointer to 1 (i=0, j=0)
A basic (untested) implementation of the algorithm is as follows:
def max_path(grid):
N = len(grid)
M = len(grid[0])
sum = [[0 for i in range(M + 1)] for i in range(N + 1)]
for i in range(1, N + 1):
for j in range(1, M + 1):
sum[i][j] = (max(sum[i - 1][j], sum[i][j - 1]) + grid[i - 1][j - 1])
j = M
i = N
path = []
while i > 0 and j > 0:
path.append((i-1,j-1))
if sum[i-1][j] <= sum[i][j-1]:
j -= 1
else:
i -= 1
path.reverse()
return sum[N][M],path
matrix = [[1, 2, 3], [3, 4, 5]]
print(max_path(matrix))
I am trying to implement the erosion function for a binary image without using standard libraries (cv2,..). That's what I got at the moment. Is it possible to simplify my code so that there are only vector or matrix operations? Any other suggestions are also welcome.
mask = np.array([
[1, 1, 1, 1, 1],
[1, 1, 1, 1, 1],
[1, 1, 1, 1, 1],
[1, 1, 1, 1, 1],
[1, 1, 1, 1, 1]
])
def erosion(image, mask):
mask_size = mask.shape[0]
left_half = int(mask_size / 2)
right_half = int(mask_size / 2)
if mask_size % 2 == 0:
right_half += 1
result = image.copy()
# Идем по изображению
for i in range(left_half, result.shape[0] - right_half):
for j in range(left_half, result.shape[1] - right_half):
left_border = int(mask_size / 2)
mask_i = 0
mask_j = 0
flag = False
right_border = left_border
if mask_size % 2 != 0:
right_border += 1
# Идем по маске, перебираем каждый элемент маски
for k in range(i - left_border, i + right_border):
mask_j = 0
for l in range(j - left_border, j + right_border):
if mask[mask_i, mask_j] == 1 and image[k, l] == 0:
result[i, j] = 0
flag = True
break
mask_j += 1
mask_i += 1
if(flag):
break
if not (flag):
result[i, j] = 255
return result
I'm working on a problem right now on tridiagonal matrix, i used the tridiagonal matrix algorithim in wiki https://en.wikipedia.org/wiki/Tridiagonal_matrix_algorithm to implement a solution and i have attempted it but my solution is not complete.
I'm confused and i need help also here is my script using jupyter notebook
import numpy as np
# The diagonals and the solution vector
b = np.array((5, 6, 6, 6, 6, 6, 6, 6, 5), dtype=float) # Main Diagonal
a= np.array((1, 1, 1, 1, 1, 1, 1, 1), dtype = float) # Lower Diagonal
c = np.array((1, 1, 1, 1, 1, 1, 1, 1), dtype = float) # Upper Diagonal
d = np.array((3, 2, 1, 3, 1, 3, 1, 2, 3), dtype = float) # Solution Vector
#number of rows
n = d.size
newC = np.zeros(n, dtype= float)
newD = np.zeros(n, dtype = float)
x = np.zeros(n, dtype = float)
# the first coefficents
newC[0] = c[0] / b[0]
newD[0] = d[0] / b[0]
for i in range(1, n - 1):
newC[i] = c[i] / (b[i] - a[i] * newC[i - 1])
for i in range(1, n -1):
newD[i] = (d[i] - a[i] * newD[i - 1]) / (b[i] - a[i] * newC[i - 1])
x[n - 1] = newD[n - 1]
for i in reversed(range(0, n - 1)):
x[i] = newD[i] - newC[i] * x[i + 1]
x
The vectors a and c should be the same length as b and d, so just prepend/append zero the them respectively. Additionally, the range should be range(1,n) otherwise your last solution element is 0 when it shouldn't be. You can see this modified code, as well as a comparison to a known algorithm, showing that it gets the same answer.
import numpy as np
# The diagonals and the solution vector
b = np.array((5, 6, 6, 6, 6, 6, 6, 6, 5), dtype=float) # Main Diagonal
a= np.array((0, 1, 1, 1, 1, 1, 1, 1, 1), dtype = float) # Lower Diagonal
c = np.array((1, 1, 1, 1, 1, 1, 1, 1, 0), dtype = float) # Upper Diagonal
d = np.array((3, 2, 1, 3, 1, 3, 1, 2, 3), dtype = float) # Solution Vector
print(b.size)
print(a.size)
#number of rows
n = d.size
newC = np.zeros(n, dtype= float)
newD = np.zeros(n, dtype = float)
x = np.zeros(n, dtype = float)
# the first coefficents
newC[0] = c[0] / b[0]
newD[0] = d[0] / b[0]
for i in range(1, n):
newC[i] = c[i] / (b[i] - a[i] * newC[i - 1])
for i in range(1, n):
newD[i] = (d[i] - a[i] * newD[i - 1]) / (b[i] - a[i] * newC[i - 1])
x[n - 1] = newD[n - 1]
for i in reversed(range(0, n - 1)):
x[i] = newD[i] - newC[i] * x[i + 1]
# Test with know algorithme
mat = np.zeros((n, n))
for i in range(n):
mat[i,i] = b[i]
if i < n-1:
mat[i, i+1] = a[i+1]
mat[i+1, i] = c[i]
print(mat)
sol = np.linalg.solve(mat, d)
print(x)
print(sol)
That's because of how a, b, c and d are defined in the wikipedia article. If you look carefully, you'll see that the first element of a is a2, also the loop for newD goes to n. So, to have understandable indices to the arrays, i suggest you add a phantom element a1. And you get:
import numpy as np
# The diagonals and the solution vector
b = np.array((5, 6, 6, 6, 6, 6, 6, 6, 5), dtype=float) # Main Diagonal
a = np.array((np.nan, 1, 1, 1, 1, 1, 1, 1, 1), dtype = float) # Lower Diagonal
# with added a1 element
c = np.array((1, 1, 1, 1, 1, 1, 1, 1), dtype = float) # Upper Diagonal
d = np.array((3, 2, 1, 3, 1, 3, 1, 2, 3), dtype = float) # Solution Vector
#number of rows
n = d.size
newC = np.zeros(n, dtype= float)
newD = np.zeros(n, dtype = float)
x = np.zeros(n, dtype = float)
# the first coefficents
newC[0] = c[0] / b[0]
newD[0] = d[0] / b[0]
for i in range(1, n - 1):
newC[i] = c[i] / (b[i] - a[i] * newC[i - 1])
for i in range(1, n): # Add the last iteration `n`
newD[i] = (d[i] - a[i] * newD[i - 1]) / (b[i] - a[i] * newC[i - 1])
x[n - 1] = newD[n - 1]
for i in reversed(range(0, n - 1)):
x[i] = newD[i] - newC[i] * x[i + 1]
x
I have a zero list with size of m. I wanna randomly select p indexes and change them to 1.
Y = [0 for x in range(M)]
What is the best way to do this?
You can use Python's random module:
import random
m, p = 5, 2
l = [0] * m
indices = list(range(len(l)))
random.shuffle(indices)
for i in indices[:p]:
l[i] = 1
As mentioned by #MrT in the comments if you don't already have your "zero list" you can do:
l = [0] * (m - p) + [1] * p
random.shuffle(l)
You can use random.sample()
import random
m,p = 10, 5
my_list = [0]*m
index = random.sample(range(len(my_list)), p)
for i in index:
my_list[i] = 1
import random
x = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
x = [1 if bool(random.getrandbits(1)) else 0 for i in x]
print(x) # [1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1]
-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-
import random
leninp = int(input("len"))
raninp = int(input("random"))
x = [0 for i in range(leninp-raninp)] + [1 for i in range(raninp)]
random.shuffle(x)
print(x)
For a square matrix, each cell is either black (1) or white (0), trying to find the max sub-square whose border is black. Here is my code with Python 2.7, wondering if logically correct? And any performance improvements? Thanks.
My major ideas is, keep track of how many black nodes are on top (continuously) and on left (continuously), which is left and top matrix represents. Then, based on the left and top tracking, for any node, I will try to find minimal value of top and left continuous black node, then I will base the minimal value to see if a square could be formed.
A=[[1,1,0,0,0],
[1,1,1,1,1],
[0,0,1,0,1],
[0,0,1,1,1],
[0,0,0,0,0]]
top=[[0] * len(A[0]) for i in range(len(A))]
left=[[0] * len(A[0]) for i in range(len(A))]
result = 0
for i in range(len(A)):
for j in range(len(A[0])):
if A[i][j] == 1:
top[i][j] = top[i-1][j] + 1 if i > 0 else 1
left[i][j] = left[i][j-1] + 1 if j > 0 else 1
print top
print left
for i in range(len(A)):
for j in range(len(A[0])):
if A[i][j] == 1:
top[i][j] = top[i-1][j] + 1 if i > 0 else 1
left[i][j] = left[i][j-1] + 1 if j > 0 else 1
x = min(top[i][j], left[i][j])
if x > 1:
y = min(left[i-x+1][j], top[i][j-x+1])
result = max(result, y)
print result
Edit 1, fix an issue, which is pointed by j_random_hacker.
A = [[1, 1, 0, 0, 0],
[1, 1, 1, 1, 1],
[0, 0, 1, 0, 1],
[0, 0, 1, 1, 1],
[0, 0, 0, 0, 0]]
A = [[0,1,1],
[1,0,1],
[1,1,1]]
top = [[0] * len(A[0]) for i in range(len(A))]
left = [[0] * len(A[0]) for i in range(len(A))]
result = 0
for i in range(len(A)):
for j in range(len(A[0])):
if A[i][j] == 1:
top[i][j] = top[i - 1][j] + 1 if i > 0 else 1
left[i][j] = left[i][j - 1] + 1 if j > 0 else 1
print top
print left
for i in range(len(A)):
for j in range(len(A[0])):
if A[i][j] == 1:
top[i][j] = top[i - 1][j] + 1 if i > 0 else 1
left[i][j] = left[i][j - 1] + 1 if j > 0 else 1
x = min(top[i][j], left[i][j])
if x > 1:
y = min(left[i - x + 1][j], top[i][j - x + 1])
if x == y:
result = max(result, y)
print result
Edit 2, address the issue by j_random_hacker.
A = [[0,1,0,0],
[1,1,1,1],
[0,1,0,1],
[0,1,1,1]]
A = [[0,1,1],
[1,0,1],
[1,1,1]]
A = [[1, 1, 0, 0, 0],
[1, 1, 1, 1, 1],
[0, 0, 1, 0, 1],
[0, 0, 1, 1, 1],
[0, 0, 0, 0, 0]]
top = [[0] * len(A[0]) for i in range(len(A))]
left = [[0] * len(A[0]) for i in range(len(A))]
result = 0
for i in range(len(A)):
for j in range(len(A[0])):
if A[i][j] == 1:
top[i][j] = top[i - 1][j] + 1 if i > 0 else 1
left[i][j] = left[i][j - 1] + 1 if j > 0 else 1
print top
print left
for i in range(len(A)):
for j in range(len(A[0])):
if A[i][j] == 1:
top[i][j] = top[i - 1][j] + 1 if i > 0 else 1
left[i][j] = left[i][j - 1] + 1 if j > 0 else 1
x = min(top[i][j], left[i][j])
while x > 1:
y = min(left[i - x + 1][j], top[i][j - x + 1])
if x == y:
result = max(result, y)
break
x -= 1
print result
Edit 3, new fix
A = [[0,1,0,0],
[1,1,1,1],
[0,1,0,1],
[0,1,1,1]]
A = [[1, 1, 0, 0, 0],
[1, 1, 1, 1, 1],
[0, 0, 1, 0, 1],
[0, 0, 1, 1, 1],
[0, 0, 0, 0, 0]]
A = [[0,1,1],
[1,0,1],
[1,1,1]]
top = [[0] * len(A[0]) for i in range(len(A))]
left = [[0] * len(A[0]) for i in range(len(A))]
result = 0
for i in range(len(A)):
for j in range(len(A[0])):
if A[i][j] == 1:
top[i][j] = top[i - 1][j] + 1 if i > 0 else 1
left[i][j] = left[i][j - 1] + 1 if j > 0 else 1
print top
print left
for i in range(len(A)):
for j in range(len(A[0])):
if A[i][j] == 1:
top[i][j] = top[i - 1][j] + 1 if i > 0 else 1
left[i][j] = left[i][j - 1] + 1 if j > 0 else 1
x = min(top[i][j], left[i][j])
while x > 1:
y = min(left[i - x + 1][j], top[i][j - x + 1])
if x <= y:
result = max(result, x)
break
x -= 1
print result
This isn't logically correct, as the following simple counterexample shows:
011
101
111
This array contains no bordered square, but your code reports that it contains a square of edge length 3. You need either a third nested loop through all candidate square sizes down from x to 1 (making the solution O(n^3)-time) or, possibly, some more sophisticated data structure that enables an equivalent check to be performed faster.
[EDIT to address updated algorithm]
The new algorithm thinks there is no bordered square in either
0100
1111 1111
0101 or 0101
0111 0111
despite there being a 3x3 one in each.
Stop guessing at fixes and think about how to break down the set of all possible locations of bordered squares into sets that you can efficiently (or even not-so-efficiently) check. As I tried to say at the top: For each possible bottom-right corner of a bordered square, your code is currently only checking one rectangle. But many more rectangles could have (i, j) as a bottom-right corner -- where are the tests for them?