I am trying to implement python Merge Sort, but for some reason when merging it does not sort it correctly at all. I am trying to turn Pseudo code into Python code and I am failing miserably. If anyone can help, I'd really appreciate it. I have tried to debug it and I am just confused.
def mergeSort(A, p, r):
if p < r:
q = int(((p + (r-1)) / 2))
mergeSort(A, p, q)
mergeSort(A, q + 1, r)
merge(A, p, q, r)
def merge(A, p, q, r): # Issue with sorting
n1 = q - p + 1
n2 = r - q
L = [0] * n1
R = [0] * n2
for i in range(0, n1):
L[i] = A[p + i]
for j in range(0, n2):
R[j] = A[q + j]
L.append(infinity)
R.append(infinity)
i = 0
j = 0
for k in range(p,r):
if L[i] <= R[j]:
A[k] = L[i]
i = i + 1
else:
A[k] = R[j]
j = j + 1
Example Input:
['date', 'apple', 'banana', 'cucumber', 'acorn', 'aaaa']
Example Output:
['banana', 'acorn', 'aaaa', 'cucumber', 'date', 'date']
mergeSort psuedocode
merge pseudocode
The issue with your implementation is that you are not properly updating the indices when merging the two sublists back together. In the following lines:
for k in range(p,r):
if L[i] <= R[j]:
A[k] = L[i]
i = i + 1
else:
A[k] = R[j]
j = j + 1
you should be incrementing k instead of i and j. Also the condition inside of the if statement should be L[i] <= R[j] instead of L[i] >= R[j].
Here is the corrected version of the merge function:
def merge(A, p, q, r):
n1 = q - p + 1
n2 = r - q
L = [0] * n1
R = [0] * n2
for i in range(0, n1):
L[i] = A[p + i]
for j in range(0, n2):
R[j] = A[q + j]
i = 0
j = 0
k = p
while i < n1 and j < n2:
if L[i] <= R[j]:
A[k] = L[i]
i += 1
else:
A[k] = R[j]
j += 1
k += 1
while i < n1:
A[k] = L[i]
i += 1
k += 1
while j < n2:
A[k] = R[j]
j += 1
k += 1
Also, you have to import the math library and use math.inf instead of infinity.
I need to find the biggest sequence of zeros next to each other (up down left right).
for example in this example the function should return 6
mat = [[1,**0**,**0**,3,0],
[**0**,**0**,2,3,0],
[2,**0**,**0**,2,0],
[0,1,2,3,3],]
the zeros that i marked as bold should be the answer (6)
the solution should be implemented without any loop (using recursion)
this is what i tried so far
def question_3_b(some_list,index_cord):
y = index_cord[0]
x = index_cord[1]
list_of_nums = []
def main(some_list,index_cord):
y = index_cord[0]
x = index_cord[1]
def check_right(x,y):
if x + 1 < 0:
return 0
if some_list[y][x+1] == 0:
main(some_list,(y,x+1))
else:
return 0
def check_left(x,y):
if x -1 < 0:
return 0
if some_list[y][x - 1] == 0:
main(some_list,(y, x - 1))
def check_down(x,y):
if y + 1 < 0:
return 0
try:
if some_list[y + 1][x] == 0:
main(some_list,(y + 1, x))
except:
print("out of range")
def check_up(x,y):
counter_up = 0
if y - 1 < 0:
return 0
if some_list[y - 1][x] == 0:
counter_up += 1
main(some_list,(y - 1, x))
list_of_nums.append((x,y))
right = check_right(x,y)
down = check_down(x,y)
left = check_left(x,y)
up = check_up(x, y)
main(some_list,index_cord)
print(list_of_nums)
question_3_b(mat,(0,1))
Solution #1: classic BFS
As I mention in a comment, you can tackle this problem using BFS (Breadth First Search), it will be something like this:
# This function will give the valid adjacent positions
# of a given position according the matrix size (NxM)
def valid_adj(i, j, N, M):
adjs = [[i + 1, j], [i - 1, j], [i, j + 1], [i, j - 1]]
for a_i, a_j in adjs:
if 0 <= a_i < N and 0 <= a_j < M:
yield a_i, a_j
def biggest_zero_chunk(mat):
answer = 0
N, M = len(mat), len(mat[0])
# Mark all non zero position as visited (we are not instrested in them)
mask = [[mat[i][j] != 0 for j in range(M)] for i in range(N)]
queue = []
for i in range(N):
for j in range(M):
if mask[i][j]: # You have visited this position
continue
# Here comes the BFS
# It visits all the adjacent zeros recursively,
# count them and mark them as visited
current_ans = 1
queue = [[i,j]]
while queue:
pos_i, pos_j = queue.pop(0)
mask[pos_i][pos_j] = True
for a_i, a_j in valid_adj(pos_i, pos_j, N, M):
if mat[a_i][a_j] == 0 and not mask[a_i][a_j]:
queue.append([a_i, a_j])
current_ans += 1
answer = max(answer, current_ans)
return answer
mat = [[1,0,0,3,0],
[0,0,2,3,0],
[2,0,0,2,0],
[0,1,2,3,3],]
mat2 = [[1,0,0,3,0],
[0,0,2,3,0],
[2,0,0,0,0], # A slight modification in this row to connect two chunks
[0,1,2,3,3],]
print(biggest_zero_chunk(mat))
print(biggest_zero_chunk(mat2))
Output:
6
10
Solution #2: using only recursion (no for statements)
def count_zeros(mat, i, j, N, M):
# Base case
# Don't search zero chunks if invalid position or non zero values
if i < 0 or i >= N or j < 0 or j >= M or mat[i][j] != 0:
return 0
ans = 1 # To count the current zero we start at 1
mat[i][j] = 1 # To erase the current zero and don't count it again
ans += count_zeros(mat, i - 1, j, N, M) # Up
ans += count_zeros(mat, i + 1, j, N, M) # Down
ans += count_zeros(mat, i, j - 1, N, M) # Left
ans += count_zeros(mat, i, j + 1, N, M) # Right
return ans
def biggest_zero_chunk(mat, i = 0, j = 0, current_ans = 0):
N, M = len(mat), len(mat[0])
# Base case (last position of mat)
if i == N - 1 and j == M - 1:
return current_ans
next_j = (j + 1) % M # Move to next column, 0 if j is the last one
next_i = i + 1 if next_j == 0 else i # Move to next row if j is 0
ans = count_zeros(mat, i, j, N, M) # Count zeros from this position
current_ans = max(ans, current_ans) # Update the current answer
return biggest_zero_chunk(mat, next_i, next_j, current_ans) # Check the rest of mat
mat = [[1,0,0,3,0],
[0,0,2,3,0],
[2,0,0,2,0],
[0,1,2,3,3],]
mat2 = [[1,0,0,3,0],
[0,0,2,3,0],
[2,0,0,0,0], # A slight modification in this row to connect two chunks
[0,1,2,3,3],]
print(biggest_zero_chunk(mat.copy()))
print(biggest_zero_chunk(mat2.copy()))
Output:
6
10
Notes:
The idea behind this solution is still BFS (represented mainly in the count_zeros function). Also, if you are interested in using the matrix values after this you should call the biggest_zero_chunk with a copy of the matrix (because it is modified in the algorithm)
This is the code I have thus far:
def frac_knapsack(n,size, profit,K):
if K <= 0:
return 0
for i in range(0,i):
if profit[i]/size[i]>profit[i-1]/size[i-1]:
profit.append[i] and size.append[i]
s = 0
p = 0
for i in range(n):
if s + size[i] <= K:
p += profit[i]
s += size[i]
else:
p += (K-s) * (profit[i]/size[i])
s = K
break
return p
def Knapsack(i, size):
if i > n or size <= 0:
print(x)
return
if x[j] == 1:
for j in range(0,i-1):
p+=P[j]
if x[j] == 1:
for j in range(0,i-1):
s+=S[j]
if x[i] == 1:
if s+size[i] <= K and (p + profit[i] + B) > MaxProfit:
B = fractional_Knapsack(n-(i+1), size[i+1:], profit[i+1:], T-size[i])
if p+profit[i] > MaxProfit:
MaxProfit=p+profit[i]
x=solution
Knapsack(i+1, T-size[i])
if x[i] == 0:
B = frac_Knapsack(n-(i+1), size[i+1:], profit[i+1:], T)
if (p + B) > MaxProfit:
Knapsack(i+1, T)
I have a problem with sorting in line 4. I have to sort it as weight-efficiency. do i need to use quick sort algorithm?
I want to make input for four things:
n,size,profit and K
do i need to use map? as size and profit is list?
You used
B = fractional_Knapsack(n-(i+1), size[i+1:], profit[i+1:], T)
your method is called
def frac_knapsack(n,size, profit,K):
I have implemented a mergesort function which works correctly, However, I'm having a hard time modifying it to count the number of inversions in the original array before it is sorted.
An inversion is a pair where i < j but a[i] > a[j] an example, a = [5,2,1] has 3 inversions: (5,2),(5,1),(2,1)
def mergeSort(a):
mid = len(a)//2
if len(a) < 2:
return
l = a[:mid]
r = a[mid:]
mergeSort(l)
mergeSort(r)
return merge(l,r,a)
def merge(l,r,a):
i = 0
j = 0
k = 0
inv = 0
while(i < len(l) and j < len(r)):
if(l[i] < r[j]):
a[k] = l[i]
i = i + 1
else:
a[k] = r[j]
inv = inv + 1
j = j + 1
k = k + 1
while i < len(l):
a[k] = l[i]
i = i + 1
k = k + 1
while j < len(r):
a[k] = r[j]
j = j + 1
k = k + 1
inv = inv + 1
return [a,inv]
a = [6,5,4,3,2,1]
print(mergeSort(a))
The above example should return 15 as the count of inversions as n(n-1)/2 is the number of inversions for descending order array.
can someone explain how to count it?
L[i] > R[j] is a single inversion, but note that since the arrays are sorted, if L[k] > R[j] for some k, this means L[k] > R[j] for all i <= k < |L|. So you can subtract the length of the array L from i to give you the total number of inversions.
So the gist of this is a function that takes two sorted lists. It takes a list of negative numbers (people who owe money) and a list of positive number (people who are owed money). It then pays off the people who are owed money from the negative list.
Example:
negatives = [-55.774, -45.884, -40.754, -35.694, -33.734, -29.024, -25.114, -16.144, -14.014, -5.874, -5.554]
positives = [43.936, 42.276, 33.756, 31.116, 30.456, 27.616, 21.526, 18.276, 13.176, 12.376, 11.966, 8.566, 8.486, 4.036]
The first step in my process is negatives[0] will pay off the positives[0], 43.936, then it pays off partially positives[1] until itself negatives[0] is 0, it then moves onto negatives[1] and pays off what is owed to positives[1]. I'm just trying to iterate this process. Here's what I have:
def pay_balances(x, y):
i = 0
j = 0
while i < len(x) and j < len(y):
while abs(x[i]) > abs(y[j]) and abs(round(x[i],4)) != 0:
print y[j]
x[i] = x[i] + y[j]
y[j] = 0
j += 1
print i, j
while abs(x[i]) < abs(y[j]) and abs(round(x[i],4)) != 0:
print -x[i]
y[j] = y[j] + x[i]
x[i] = 0
i += 1
print i, j
So, if you run...
pay_balances(negatives, positives)
This will eventually break due to IndexError: list index out of range
The issue is when we are the end of the lists, and my j value = 14 which is when I want everything to stop. It appears to stay in the loop even though I have this line which I thought would kill it:
while i < len(x) and j < len(y):
What am I doing wrong? As always thanks a lot!!
Since you increment the indices i and j in the inner loops, you need to put the corresponding condition also in the first inner while loop, and add an exit point half-way:
while i < len(x) and j < len(y):
while j < len(y) and abs(x[i]) > abs(y[j]) and abs(round(x[i],4)) != 0:
print y[j]
x[i] = x[i] + y[j]
y[j] = 0
j += 1
print i, j
if j >= len(y):
break
while i < len(x) and abs(x[i]) < abs(y[j]) and abs(round(x[i],4)) != 0:
print -x[i]
y[j] = y[j] + x[i]
x[i] = 0
i += 1
print i, j
I think that this code generates what you want by using one loop:
def pay_balances(x, y):
i = 0
j = 0
while x[-1] != 0 and y[-1] !=0:
if abs(x[i]) > abs(y[j]):
x[i] = x[i] + y[j]
y[j] = 0
j += 1
elif abs(x[i]) < abs(y[j]):
y[j] = y[j] + x[i]
x[i] = 0
i += 1
print x, y
return sum(x) + sum(y)