Quicksort implement in Python run with none stop - python

This is my quicksort algorithms. Very simple
x = 0
def swap(list, a, b):
temp = list[a]
list[a] = list[b]
list[b] = temp
return list
def quicksort2(list, left, right):
if right > left:
global x
x = x + 1
print x , list, left, right
l = left+1
r = right
while l <= r :
while list[l] < list[left]:
l = l + 1
while list[r] > list[left]:
r = r - 1
if l < r:
list = swap(list, l, r)
list = swap(list, left, r)
list = quicksort2(list, left, r-1);
return quicksort2(list, r+1, right);
return list
But when i run my testcase
b = list([1, 2, 2, 3, 4, 5, 6, 12, 6, 32])
quicksort2(b, 0, len(b)-1)
the result is
1 [1, 2, 2, 3, 4, 5, 6, 12, 6, 32] 0 9
2 [1, 2, 2, 3, 4, 5, 6, 12, 6, 32] 1 9
and stop at this...
Anybody have any reason ...

Have you tried to trace the program execution under a debugger...?
The while l <= r loop runs forever, because after several decrements of r
left == 1
l == 2
r == 2
and
l is not incremented, because list[2] is not less than list[1]
r is not decremented any longer, because list[2] is not greater than list[1]
no swap is done, because l is not less than r
and loop will continue, because l is still equal to r.......

I simply modified your code a bit.. Found several mistakes, some already mentioned by others. The rest I am not going to go through.
However, you do not have to return a modified list, as lists in python are always passed by reference.
This should be working:
def quicksort2(list, low, high):
global x
x = x + 1
print x , list, low, high
l = low
r = high
mid = list[(r + l) / 2]
while l <= r:
while list[l] < mid: l += 1
while list[r] > mid: r -= 1
if l <= r:
list[l], list[r] = list[r], list[l] #swap(r,l)
l += 1
r -= 1
if r > low: quicksort2(list, low, r);
if l < high: quicksort2(list, l, high);
if __name__ == '__main__':
x = 0
b = [1, 2, 2, 3, 4, 5, 6, 12, 6, 32]
quicksort2(b, 0, len(b)-1)
print b

Related

How to find the max array from both sides

Given an integer array A, I need to pick B elements from either left or right end of the array A to get maximum sum. If B = 4, then you can pick the first four elements or the last four elements or one from front and three from back etc.
Example input:
A = [5, -2, 3, 1, 2]
B = 3
The correct answer is 8 (by picking 5 from the left, and 1 and 2 from the right).
My code:
def solve(A, B):
n = len(A)
# track left most index and right most index i,j
i = 0
j = n-1
Sum = 0
B2 = B # B for looping and B2 for reference it
# Add element from front
for k in range(B):
Sum += A[k]
ans = Sum
# Add element from last
for _ in range(B2):
# Remove element from front
Sum -= A[i]
# Add element from last
Sum += A[j]
ans = max(ans, Sum)
return ans
But the answer I get is 6.
Solution
def max_bookend_sum(x, n):
bookends = x[-n:] + x[:n]
return max(sum(bookends[i : i + n]) for i in range(n + 1))
Explanation
Let n = 3 and take x,
>>> x = [4, 9, -7, 4, 0, 4, -9, -8, -6, 9]
Grab the "right" n elements, concatenate with the "left" n:
>>> bookends = x[-n:] + x[:n]
>>> bookends # last three elements from x, then first three
[-8, -6, 9, 4, 9, -7]
Take "sliding window" groups of n elements:
>>> [bookends[i : i + n] for i in range(n + 1)]
[[-8, -6, 9], [-6, 9, 4], [9, 4, 9], [4, 9, -7]]
Now, instead of producing the sublists sum them instead, and take the max:
>>> max(sum(bookends[i : i + n]) for i in range(n + 1))
22
For your large array A from the comments:
>>> max(sum(bookends[i : i + n]) for i in range(n + 1))
6253
Solution based on sum of the left and right slices:
Data = [-533, -666, -500, 169, 724, 478, 358, -38, -536, 705, -855, 281, -173, 961, -509, -5, 942, -173, 436, -609,
-396, 902, -847, -708, -618, 421, -284, 718, 895, 447, 726, -229, 538, 869, 912, 667, -701, 35, 894, -297, 811,
322, -667, 673, -336, 141, 711, -747, -132, 547, 644, -338, -243, -963, -141, -277, 741, 529, -222, -684,
35] # to avoid var shadowing
def solve(A, B):
m, ln = None, len(A)
for i in range(B):
r = -(B-i-1) # r is right index to slice
tmp = sum(A[0:i + 1]) + sum(A[r:]) if r < 0 else 0
m = tmp if m is None else max(m, tmp)
return m
print(solve(Data, 48)) # 6253
A recursive approach with comments.
def solve(A, B, start_i=0, end_i=None):
# set end_i to the index of last element
if end_i is None:
end_i = len(A) - 1
# base case 1: we have no more moves
if B == 0:
return 0
# base case 2: array only has two elemens
if end_i - start_i == 1:
return max(A)
# next, we need to choose whether to use one of our moves on
# the left side of the array or the right side. We compute both,
# then check which one is better.
# pick the left side to sum
sum_left = A[start_i] + solve(A, B - 1, start_i + 1, end_i)
# pick the right side to sum
sum_right = A[end_i] + solve(A, B - 1, start_i, end_i - 1)
# return the max of both options
return max(sum_left, sum_right)
arr = [5, -2, 3, 1, 2]
print(solve(arr, 3)) # prints 8
The idea is if we have this list:
[5, 1, 1, 8, 2, 10, -2]
Then the possible numbers for B=3 would be:
lhs = [5, 1, 1] # namely L[+0], L[+1], L[+2]
rhs = [2, 10, -2] # namely R[-3], R[-2], R[-1]
The possible combinations would be:
[5, 1, 1] # L[+0], L[+1], L[+2]
[5, 1, -2] # L[+0], L[+1], R[-1]
[5, 10, -2] # L[+0], R[-2], R[-1]
[2, 10, -2] # R[-3], R[-2], R[-1]
As you can see, we can easily perform forward and backward iterations which will start from all L (L[+0], L[+1], L[+2]), and then iteratively replacing the last element with an R (R[-1], then R[-2], then R[-3]) up until all are R (R[-3], then R[-2], then R[-1]).
def solve(A, B):
n = len(A)
max_sum = None
for lhs, rhs in zip(range(B, -1, -1), range(0, -(B+1), -1)):
combined = A[0:lhs] + (A[rhs:] if rhs < 0 else [])
combined_sum = sum(combined)
max_sum = combined_sum if max_sum is None else max(max_sum, combined_sum)
return max_sum
for A in [
[5, 1, 1, 8, 2, 10, -2],
[5, 6, 1, 8, 2, 10, -2],
[5, 6, 3, 8, 2, 10, -2],
]:
print(A)
print("\t1 =", solve(A, 1))
print("\t2 =", solve(A, 2))
print("\t3 =", solve(A, 3))
print("\t4 =", solve(A, 4))
Output
[5, 1, 1, 8, 2, 10, -2]
1 = 5
2 = 8
3 = 13
4 = 18
[5, 6, 1, 8, 2, 10, -2]
1 = 5
2 = 11
3 = 13
4 = 20
[5, 6, 3, 8, 2, 10, -2]
1 = 5
2 = 11
3 = 14
4 = 22
public int solve(int[] A, int B) {
int sum = 0;
int i = 0;
int n = A.length -1;
for (int k = 0; k < B; k++){
sum += A[k];
}
int ans = sum;
int B2 = B -1;
for (int j = n; j > n -B; j--){
sum -= A[B2];
sum += A[j];
ans = Math.max(ans, sum);
B2--;
}
return ans;
}
}

How to find sum of product of min value and length of sub list

I have a list of n numbers. I want to divide the list into sub lists, such as the sub list consists of continuous increasing numbers or continuous decreasing numbers. Then take the product of each sub list's min value and it's length. Finally take the sum of all this product's
Input:
l = [1,2,6,4,2,3,1,8,9,7]
Output:
32
Details:
[1,2,6],[6,4,2],[2,3],[3,1],[1,8,9],[9,7]
(1*3) +(2*3) + (2*2)+(1*2)+(1*3)+ (7*2) = 32
Code so far:
n = 10
l = [1,2,6,4,2,3,1,8,9,7]
tot = 0
count = 0
inc=dec=False
min_val = 1001 # max value in list won't exceed 1000
for idx, e in enumerate(l):
if idx+1<=n:
if e > l[idx+1]:
count+=1
if min_val > l[idx+1]:
min_val=l[idx+1]
inc=True
dec=False
elif e < l[idx+1]:
count+=1
if min_val > e:
min_val=e
dec=True
# if not inc
inc=False
*Note: No Two adjacent value will be equal in the list.
Update-1:
itemp = [1001]
dtemp = [1001]
result=0
for e in l:
# if not itemp or not dtemp:
# itemp.append(e)
# dtemp.append(e)
if e > itemp[-1]:
if not dtemp:
itemp.append(e)
else:
result+=(min(dtemp)*(len(dtemp)-1))
dtemp=[1001]
itemp.append(e)
elif e < dtemp[-1]:
dtemp.append(e)
if not itemp:
dtemp.append(e)
else:
result+=(min(itemp)*(len(itemp)-1))
itemp=[1001]
dtemp.append(e)
print(result)
This results 0 as output. Can some one help?
l = [1,2,6,4,2,3,1,8,9,7]
local_max= [i for i in range(1, len(l)-1) if l[i-1]<l[i]>l[i+1]]
local_min= [i for i in range(1, len(l)-1) if l[i-1]>l[i]<l[i+1]]
idx= sorted(local_max+local_min +[0,len(l)-1])
idx_pairs = zip(idx[:-1],idx[1:])
sum(min(l[i_1],l[i_2])*(i_2+1-i_1) for i_1,i_2 in idx_pairs)
You could identify the breaking positions (peaks and bottoms) using zip to detect changes of increasing/decreasing values between each sequence of 3 elements. Then use these breaks to form the sub-lists and apply the calculation in a comprehension.
L = [1,2,6,4,2,3,1,8,9,7]
breaks = [i+1 for i,(a,b,c) in enumerate(zip(L,L[1:],L[2:])) if (a<b)==(b>c)]
subL = [ L[s:e+1] for s,e in zip([0]+breaks,breaks+[len(L)]) ]
result = sum(min(s)*len(s) for s in subL)
print(breaks) # [2, 4, 5, 6, 8] indices of peaks and bottoms
# [1,2,6,4,2,3,1,8,9,7]
# ^ ^ ^ ^ ^
# 0 1 2 3 4 5 6 7 8 9
print(subL) # [ [1, 2, 6], [6, 4, 2], [2, 3], [3, 1], [1, 8, 9], [9, 7]]
# 0..2+1 2..4+1 4..5+1 5..6+1 6..8+1 8..len(L)
# | | | | | | | | | | | |
# [0] | + [2, | 4, | 5, | 6, | 8] |
# [2, 4, 5, 6, 8] + [len(L)]
print(result) # 32
tot = start = m = n = 0
direc = -1
for n, x in enumerate(lis):
if n == 0:
m = x
else:
old = lis[n - 1]
if (x > old and direc == 0) or (x < old and direc == 1):
tot += m * (n - start)
start = n - 1
m = min(old, x)
direc ^= 1
else:
direc = 1 if x > old else 0
m = min(m, x)
ln = n - start + 1
if ln > 1:
tot += m * ln

Merge sort in python issue [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
def mergeSort(A, l, r):
if l < r:
mid = (l + r) // 2
mergeSort(A, l, mid)
mergeSort(A, mid + 1, r)
merge(A, l, mid, r)
def merge(arr, l, mid, r):
arr1 = []
arr2 = []
for i in range(mid):
arr1.append(arr[i])
for j in range(mid, r):
arr2.append(arr[j])
i = 0
j = 0
k = 0
while (i < len(arr1) and j < len(arr2)):
if arr1[i] < arr2[j]:
arr[k] = arr1[i]
i += 1
else:
arr[k] = arr2[j]
j += 1
k += 1
while i < len(arr1):
arr[k] = arr1[i]
i += 1
k += 1
while j < len(arr2):
arr[k] = arr2[j]
j += 1
k += 1
arr = [2, 9, 7, 6, 1, 8, 4, 3]
mergeSort(arr, 0, 8)
print(arr)
There's a slight mistake somewhere in the code that I'm not able to find
Please try to run this code on your machine with different test cases.
And Let me know what I'm doing wrong here.
I don't know why I'm getting an incorrect answer: [1, 2, 3, 4, 6, 8, 9, 7]
You have problems with indexes. You wrote code in C style.
Just use slices to fix your problem
Change definition (delete for loops for arr1 and arr2) for arr1 and arr2 to :
arr1 = arr[:mid]
arr2 = arr[mid:]
else:
arr[k] = arr2[j]
j += 1
k += 1
Change the place of
k += 1
To this:
else:
arr[k] = arr2[j]
j += 1
k += 1
Or this:
else:
arr[k] = arr2[j]
j += 1
k += 1
There are multiple problems in your code:
you pass the index of the first element to sort and the index once past the last element of the slice, but you wrote the function mergeSort with different semantics as you assume r to be the index to the last element of the slice.
similarly, merge expects the mid argument to be the start of the right half and you pass mid, which would be the index to the last element of the first half in your approach.
in the merge function, arr1 should be initialized with i varying from l to mid, with for i in range(l:mid):
furthermore, k must be initialized to l, not 0.
note that arr1 and arr2 could be initialized from simple slices of arr.
Here is a modified version:
def mergeSort(A, l, r):
if r - l > 1:
mid = (l + r) // 2
mergeSort(A, l, mid)
mergeSort(A, mid, r)
merge(A, l, mid, r)
def merge(arr, l, mid, r):
arr1 = arr[l : mid]
arr2 = arr[mid : r]
i = 0
j = 0
k = l
while (i < len(arr1) and j < len(arr2)):
if arr1[i] <= arr2[j]:
arr[k] = arr1[i]
i += 1
else:
arr[k] = arr2[j]
j += 1
k += 1
while i < len(arr1):
arr[k] = arr1[i]
i += 1
k += 1
while j < len(arr2):
arr[k] = arr2[j]
j += 1
k += 1
arr = [2, 9, 7, 6, 1, 8, 4, 3]
mergeSort(arr, 0, 8)
print(arr)
Output:
[1, 2, 3, 4, 6, 7, 8, 9]

Get numbers between start and stop and restart counter if maximum is exceeded

My goal is to get all numbers between start and stop, inclusive. If the starting point exceeds a defined maximum (restart_point), it should start from 1 again
For example:
start = 4
stop = 8
restart_point = 12
result should be: [4, 5, 6, 7, 8]
start = 9
stop = 3
restart_point = 12
result should be: [9, 10, 11, 12, 1, 2, 3]
The following code works, but I find it a bit complicated. I would be happy about alternative solutions.
start = 10
stop = 3
restart_point = 12
if stop - start < 0:
difference = restart_point - start + stop
else:
difference = stop - start
numbers = []
r = 0
for i in range(difference + 1):
val = i + start
if val > restart_point:
r += 1
val = r
numbers.append(val)
print(numbers)
# result -> [10, 11, 12, 1, 2, 3]
From your simple examples, it appears that I can assume that both stop and start are between 1 and restart_point, inclusive. This makes it simple enough:
start, stop, restart_point = 10, 3, 12
if stop < start:
stop += restart_point
numbers = []
for i in range(start-1, stop):
val = i % restart_point + 1
numbers.append(val)
print(numbers)
Output:
[10, 11, 12, 1, 2, 3]
Remember to use mod if you need loop in number:
start = 9
stop = 3
restart_point = 12
while start % restart_point != stop:
print(start % restart_point)
start = start + 1
It's 0-index based but it is easy to modified into 1-index based. Leave it to you :)
[i for i in range(start, stop+1)] if start<stop else [i for i in range(start, restart_point+1)] + [i for i in range(1, stop+1)]
I think I would do something like this:
numbers = []
x = start
while x <= stop:
if x > restart_point:
x = 1
numbers.append(x)
x = x + 1
start = 9
stop = 3
restart_point = 12
l = []
if restart_point > stop:
l = l + [i for i in range(start,restart_point)] + [i for i in range(1, stop+1)]
else:
l = l + [i for i in range(start, stop+1)]
print(l)
Output:
(python37) C:\Users\Documents>py test.py
[9, 10, 11, 1, 2, 3]
Here it is:
start, stop, restart_point = (10, 3, 12)
x = list(range(start, 1 + min(stop, restart_point))) + \
list(range(start, 1 + (start>stop) * max(stop, restart_point))) + \
list(range(1, 1 + (start>stop) *stop))
print(x)
Output
[10, 11, 12, 1, 2, 3]

Merge Sort in place for python (Cant find what is wrong)

I was reading about merge sort(In place) in my algorithm book (Intro to algorithms 3rd edition Cormen), and I decided to implement it in Python. The problem is that I can't find what I am doing wrong... I saw some code in C++, but even with that I can't fix it.
Here is my code:
def MERGE(A,start,mid,end):
L=[0]*(mid - start + 1)
for i in range(len(L) - 1):
L[i] = A[start+i]
L[len(L) - 1] = 100000 # centinel, (fix)
R=[0]*(end - mid + 2)
for j in range(len(R) - 1):
R[j] = A[mid+j]
R[len(R) - 1] = 100000
i = 0
j = 0
k = start
for l in range(k,end):
if(L[i] < R[j]):
A[l] = L[i]
i = i + 1
else:
A[k] = R[j]
j = j + 1
def mergeSort(A,p,r):
if p < r:
mid = int((p+r)/2)
mergeSort(A,p,mid)
mergeSort(A,mid+1,r)
MERGE(A,p,mid,r)
A = [20, 30, 15, 21, 42, 45, 31, 0, 9]
mergeSort(A,0,len(A)]
When I run the code I have some index problems:
File "myrealmerge.py", line 9, in MERGE
R[j] = A[mid+j]
IndexError: list index out of range
I know that this my be a "dumb question" and that there is some related post, but I tried the suggestions in there and It does not work for me...
Can anyone help me? T
Thanks!
This code works fine:
def MERGE(A,start,mid,end):
L = A[start:mid]
R = A[mid:end]
i = 0
j = 0
k = start
for l in range(k,end):
if j >= len(R) or (i < len(L) and L[i] < R[j]):
A[l] = L[i]
i = i + 1
else:
A[l] = R[j]
j = j + 1
def mergeSort(A,p,r):
if r - p > 1:
mid = int((p+r)/2)
mergeSort(A,p,mid)
mergeSort(A,mid,r)
MERGE(A,p,mid,r)
A = [20, 30, 21, 15, 42, 45, 31, 0, 9]
mergeSort(A,0,len(A))
print A
I tried to minimize the change from your code.
Good luck!
(Added)
You can check the dividing process by using this code.
def MERGE(A,start,mid,end):
# Do nothing
pass
def mergeSort(A,p,r):
if r - p > 1:
mid = int((p+r)/2)
print A[p:mid],A[mid:r]
mergeSort(A,p,mid)
mergeSort(A,mid,r)
MERGE(A,p,mid,r)
A = [20, 30, 21, 15, 42, 45, 31, 0, 9]
mergeSort(A,0,len(A))
The result is as follows:
[20, 30, 21, 15] [42, 45, 31, 0, 9]
[20, 30] [21, 15]
[20] [30]
[21] [15]
[42, 45] [31, 0, 9]
[42] [45]
[31] [0, 9]
[0] [9]
This is what we want. However, 'mid+1' makes invalid result. Here is the test code:
def MERGE(A,start,mid,end):
# Do nothing
pass
def mergeSort(A,p,r):
if r - p > 1:
mid = int((p+r)/2)
print A[p:mid],A[mid+1:r] # Changed
mergeSort(A,p,mid)
mergeSort(A,mid+1,r) # Changed
MERGE(A,p,mid,r)
A = [20, 30, 21, 15, 42, 45, 31, 0, 9]
mergeSort(A,0,len(A))
result:
[20, 30, 21, 15] [45, 31, 0, 9]
[20, 30] [15]
[20] []
[45, 31] [9]
[45] []
(Added)
Here is a code using 'mid+1':
# New indexing function that includes the right index.
def get_partial_list(origin_list, left_index, right_index): # Added
return origin_list[left_index:right_index+1]
def MERGE(A,start,mid,end):
L = get_partial_list(A,start,mid)
R = get_partial_list(A,mid+1,end)
i = 0
j = 0
k = start
for l in range(k,end+1): # changed
if j >= len(R) or (i < len(L) and L[i] < R[j]):
A[l] = L[i]
i = i + 1
else:
A[l] = R[j]
j = j + 1
def mergeSort(A,p,r):
if r - p > 0: # changed
mid = int((p+r)/2)
mergeSort(A,p,mid)
mergeSort(A,mid+1,r) # changed
MERGE(A,p,mid,r)
A = [20, 30, 21, 15, 42, 45, 31, 0, 9]
mergeSort(A,0,len(A)-1) # changed
print A
I've added new indexing function. Is this the code you expected?
The solutions provided by lancif and krishna Prasad dont not have space complexity O(1).
Here is algorithm in place merge sorting for Py3 with space complexity O(1).
The main function sort_imerge uses 2 auxiliary functions wmerge and wsort.
This solution based on C code that discussed on:
other SO topic and on good C implementation
Also you can find full Python code with doctests here
def sort_imerge(Seq, l=0, u=None):
""" Merge sorting, mutable input.
Input sequence changed in place.
Time: O(n * log n)
log n -- levels
n -- elements on each level must be merged
Space (additional): O(1)
input changed in place
Returns None
"""
u = len(Seq) if u is None else u
if u - l > 1:
m = l + (u - l) // 2
w = l + u - m
wsort(Seq, l, m, w)
while w - l > 2:
n = w
w = l + (n - l + 1) // 2
wsort(Seq, w, n, l)
wmerge(Seq, l, l + n - w, n, u, w)
n = w
while n > l: # fallback to insert sort
for m in range(n, u):
if Seq[m-1] > Seq[m]:
Seq[m-1], Seq[m] = Seq[m], Seq[m-1]
n -= 1
def wmerge(Seq, i, m, j, n, w):
"""Merge subarrays [i, m) and [j, n) into work area w.
All indexes point into Seq.
The space after w must be enough to fit both subarrays.
"""
while i < m and j < n:
if Seq[i] < Seq[j]:
Seq[i], Seq[w] = Seq[w], Seq[i]
i += 1
else:
Seq[j], Seq[w] = Seq[w], Seq[j]
j += 1
w += 1
while i < m:
Seq[i], Seq[w] = Seq[w], Seq[i]
i += 1
w += 1
while j < n:
Seq[j], Seq[w] = Seq[w], Seq[j]
j += 1
w += 1
def wsort(Seq, l, u, w):
"""Sort subarray [l, u) and put reuslt into work area w.
All indexes point into Seq.
"""
if u - l > 1:
m = l + (u - l) // 2
sort_imerge(Seq, l, m)
sort_imerge(Seq, m, u)
wmerge(Seq, l, m, m, u, w)
else:
while l < u:
Seq[l], Seq[w] = Seq[w], Seq[l]
l +=1
w +=1
Recursively split the array into left and right part and then merge it as per your requirements i.e ASC or DESC, Check the below code:
def merge_sort(a):
if len(a) <= 1:
return a
left = [];
right = [];
mid = len(a)/2
left = a[0:mid]
right = a[mid:(len(a))]
print left
print right
#exit()
left = merge_sort(left)
right = merge_sort(right)
return merge(left, right)
def merge(left, right):
result = []
while len(left) > 0 and len(right) > 0:
lv = left[0]
rv = right[0]
if lv <= rv:
result.append(lv)
left.pop(0)
else:
result.append(rv)
right.pop(0)
while len(left) > 0:
result.append(left.pop(0))
while len(right) > 0:
result.append(right.pop(0))
return result
A = [20, 30, 21, 15, 42, 45, 31, 0, 9]
print A
print merge_sort(A)
For understanding I have printed the intermediate partitioned array have a look into the output:
[20, 30, 21, 15, 42, 45, 31, 0, 9]
[20, 30, 21, 15]
[42, 45, 31, 0, 9]
[20, 30]
[21, 15]
[20]
[30]
[21]
[15]
[42, 45]
[31, 0, 9]
[42]
[45]
[31]
[0, 9]
[0]
[9]
[0, 9, 15, 20, 21, 30, 31, 42, 45]
Hope this will help you to understand the logic.

Categories

Resources