Merge sort python 3 - python

I implemented such merge sorting algorithm, hoverer I got some issues
import sys
if __name__ == '__main__':
input = sys.stdin.read()
data = list(map(int, input.split()))
n = data[0]
a = data[1:]
print(merge_sort(a))
def merge(left,rigt):
result = []
i = j = 0
while i < len(left) and j < len(rigt):
if left[i] <= rigt[j]:
result.append(left[i])
i += 1
else:
result.append(rigt[j])
j += 1
result += left[i:]
result += rigt[j:]
return result
def merge_sort(a):
if len(a) <= 2:
return 1
middle = len(a)//2
left = a[:middle]
right = a[middle:]
left = merge_sort(left)
right = merge_sort(right)
return list(merge(left,right))
I got such error
TypeError: object of type 'int' has no len()
I can't understand, where I went wrong, why program thinks that "left" and "right" are int, however it is array.

You should replace
if len(a) <= 2:
return 1
with
if len(a) == 1:
return a
to return a list which is not partitionable.

You are forgetting the terminating case of your merge_sort function, which returns 1. Thus, left and rigt are int when the recursion reaches the bottom, and you need to take account for that in your code.

Related

Python: Find longest binary gap in binary representation of an integer number

I would like to know if my implementation is efficient.
I have tried to find the simplest and low complex solution to that problem using python.
def count_gap(x):
"""
Perform Find the longest sequence of zeros between ones "gap" in binary representation of an integer
Parameters
----------
x : int
input integer value
Returns
----------
max_gap : int
the maximum gap length
"""
try:
# Convert int to binary
b = "{0:b}".format(x)
# Iterate from right to lift
# Start detecting gaps after fist "one"
for i,j in enumerate(b[::-1]):
if int(j) == 1:
max_gap = max([len(i) for i in b[::-1][i:].split('1') if i])
break
except ValueError:
print("Oops! no gap found")
max_gap = 0
return max_gap
let me know your opinion.
I do realize that brevity does not mean readability nor efficiency.
However, ability to spell out solution in spoken language and implement it in Python in no time constitutes efficient use of my time.
For binary gap: hey, lets convert int into binary, strip trailing zeros, split at '1' to list, then find longest element in list and get this element lenght.
def binary_gap(N):
return len(max(format(N, 'b').strip('0').split('1')))
Your implementation converts the integer to a base two string then visits each character in the string. Instead, you could just visit each bit in the integer using << and &. Doing so will avoid visiting each bit twice (first to convert it to a string, then to check if if it's a "1" or not in the resulting string). It will also avoid allocating memory for the string and then for each substring you inspect.
You can inspect each bit of the integer by visiting 1 << 0, 1 << 1, ..., 1 << (x.bit_length).
For example:
def max_gap(x):
max_gap_length = 0
current_gap_length = 0
for i in range(x.bit_length()):
if x & (1 << i):
# Set, any gap is over.
if current_gap_length > max_gap_length:
max_gap_length = current_gap_length
current_gap_length = 0
else:
# Not set, the gap widens.
current_gap_length += 1
# Gap might end at the end.
if current_gap_length > max_gap_length:
max_gap_length = current_gap_length
return max_gap_length
def max_gap(N):
xs = bin(N)[2:].strip('0').split('1')
return max([len(x) for x in xs])
Explanation:
Both leading and trailing zeros are redundant with binary gap finding
as they are not bounded by two 1's (left and right respectively)
So step 1 striping zeros left and right
Then splitting by 1's yields all sequences of 0'z
Solution: The maximum length of 0's sub-strings
As suggested in the comments, itertools.groupby is efficient in grouping elements of an iterable like a string. You could approach it like this:
from itertools import groupby
def count_gap(x):
b = "{0:b}".format(x)
return max(len(list(v)) for k, v in groupby(b.strip("0")) if k == "0")
number = 123456
print(count_gap(number))
First we strip all zeroes from the ends, because a gap has to have on both ends a one. Then itertools.groupby groups ones and zeros and we extract the key (i.e. "0" or "1") together with a group (i.e. if we convert it into a list, it looks like "0000" or "11"). Next we collect the length for every group v, if k is zero. And from this we determine the largest number, i.e. the longest gap of zeroes amidst the ones.
I think the accepted answer dose not work when the input number is 32 (100000). Here is my solution:
def solution(N):
res = 0
st = -1
for i in range(N.bit_length()):
if N & (1 << i):
if st != -1:
res = max(res, i - st - 1)
st = i
return res
def solution(N):
# write your code in Python 3.6
count = 0
gap_list=[]
bin_var = format(N,"b")
for bit in bin_var:
if (bit =="1"):
gap_list.append(count)
count =0
else:
count +=1
return max(gap_list)
Here is my solution:
def solution(N):
num = binary = format(N, "06b")
char = str(num)
find=False
result, conteur=0, 0
for c in char:
if c=='1' and not find:
find = True
if find and c=='0':
conteur+=1
if c=='1':
if result<conteur:
result=conteur
conteur=0
return result
this also works:
def binary_gap(n):
max_gap = 0
current_gap = 0
# Skip the tailing zero(s)
while n > 0 and n % 2 == 0:
n //= 2
while n > 0:
remainder = n % 2
if remainder == 0:
# Inside a gap
current_gap += 1
else:
# Gap ends
if current_gap != 0:
max_gap = max(current_gap, max_gap)
current_gap = 0
n //= 2
return max_gap
Old question, but I would solve it using generators.
from itertools import dropwhile
# a generator that returns binary
# representation of the input
def getBinary(N):
while N:
yield N%2
N //= 2
def longestGap(N):
longestGap = 0
currentGap = 0
# we want to discard the initial 0's in the binary
# representation of the input
for i in dropwhile(lambda x: not x, getBinary(N)):
if i:
# a new gap is found. Compare to the maximum
longestGap = max(currentGap, longestGap)
currentGap = 0
else:
# extend the previous gap or start a new one
currentGap+=1
return longestGap
Can be done using strip() and split() function :
Steps:
Convert to binary (Remove first two characters )
Convert int to string
Remove the trailing and starting 0 and 1 respectively
Split with 1 from the string to find the subsequences of strings
Find the length of the longest substring
Second strip('1') is not mandatory but it will decrease the cases to be checked and will improve the time complexity
Worst case T
def solution(N):
return len(max(bin(N)[2:].strip('0').strip('1').split('1')))
Solution using bit shift operator (100%). Basically the complexity is O(N).
def solution(N):
# write your code in Python 3.6
meet_one = False
count = 0
keep = []
while N:
if meet_one and N & 1 == 0:
count+=1
if N & 1:
meet_one = True
keep.append(count)
count = 0
N >>=1
return max(keep)
def solution(N):
# write your code in Python 3.6
iterable_N = "{0:b}".format(N)
max_gap = 0
gap_positions = []
for index, item in enumerate(iterable_N):
if item == "1":
if len(gap_positions) > 0:
if (index - gap_positions[-1]) > max_gap:
max_gap = index - gap_positions[-1]
gap_positions.append(index)
max_gap -= 1
return max_gap if max_gap >= 0 else 0
this also works:
def solution(N):
bin_num = str(bin(N)[2:])
list1 = bin_num.split('1')
max_gap =0
if bin_num.endswith('0'):
len1 = len(list1) - 1
else:
len1 = len(list1)
if len1 != 0:
for i in range(len1):
if max_gap < len(list1[i]):
max_gap = len(list1[i])
return max_gap
def solution(number):
bits = [int(digit) for digit in bin(number)[2:]]
occurences = [i for i, bit in enumerate(bits) if(bit==1)]
res = [occurences[counter+1]-a-1 for counter, a in enumerate(occurences) if(counter+1 < len(occurences))]
if(not res):
print("Gap: 0")
else:
print("Gap: ", max(res))
number = 1042
solution(number)
This works
def solution(number):
# convert number to binary then strip trailing zeroes
binary = ("{0:b}".format(number)).strip("0")
longest_gap = 0
current_gap = 0
for c in binary:
if c is "0":
current_gap = current_gap + 1
else:
current_gap = 0
if current_gap > longest_gap:
longest_gap = current_gap
return longest_gap
def max_gap(N):
bin = '{0:b}'.format(N)
binary_gap = []
bin_list = [bin[i:i+1] for i in range(0, len(bin), 1)]
for i in range(len(bin_list)):
if (bin_list[i] == '1'):
# print(i)
# print(bin_list[i])
# print(binary_gap)
gap = []
for j in range(len(bin_list[i+1:])):
# print(j)
# print(bin_list[j])
if(bin_list[i+j+1]=='1'):
binary_gap.append(j)
# print(j)
# print(bin_list[j])
# print(binary_gap)
break
elif(bin_list[i+j+1]=='0'):
# print(i+j+1)
# print(bin_list[j])
# print(binary_gap)
continue
else:
# print(i+j+1)
# print(bin_list[i+j])
# print(binary_gap)
break
else:
# print(i)
# print(bin_list[i])
# print(binary_gap)
binary_gap.append(0)
return max(binary_gap)
pass
def find(s, ch):
return [i for i, ltr in enumerate(s) if ltr == ch]
def solution(N):
get_bin = lambda x: format(x, 'b')
binary_num = get_bin(N)
print(binary_num)
binary_str = str(binary_num)
list_1s = find(binary_str,'1')
diffmax = 0
for i in range(len(list_1s)-1):
if len(list_1s)<1:
diffmax = 0
break
else:
diff = list_1s[i+1] - list_1s[i] - 1
if diff > diffmax:
diffmax = diff
return diffmax
pass
def solution(N: int) -> int:
binary = bin(N)[2:]
longest_gap = 0
gap = 0
for char in binary:
if char == '0':
gap += 1
else:
if gap > longest_gap:
longest_gap = gap
gap = 0
return longest_gap
Here's a solution using iterators and generators that will handle edge cases such as the binary gap for the number 32 (100000) being 0 and the binary gap for 0 being 0. It doesn't create a list, instead relying on iterating and processing elements of the bit string one step at a time for a memory efficient solution.
def solution(N):
def counter(n):
count = 0
preceeding_one = False
for x in reversed(bin(n).lstrip('0b')):
x = int(x)
if x == 1:
count = 0
preceeding_one = True
yield count
if preceeding_one and x == 0:
count += 1
yield count
yield count
return(max(counter(N)))
Here is one more that seems to be easy to understand.
def count_gap(x):
binary_str = list(bin(x)[2:].strip('0'))
max_gap = 0
n = len(binary_str)
pivot_point = 0
for i in range(pivot_point, n):
zeros = 0
for j in range(i + 1, n):
if binary_str[j] == '0':
zeros += 1
else:
pivot_point = j
break
max_gap = max(max_gap, zeros)
return max_gap
This is really old, I know. But here's mine:
def solution(N):
gap_list = [len(gap) for gap in bin(N)[2:].strip("0").split("1") if gap != ""]
return max(gap_list) if gap_list else 0
Here is another efficient solution. Hope it may helps you. You just need to pass any number in function and it will return longest Binary gap.
def LongestBinaryGap(num):
n = int(num/2)
bin_arr = []
for i in range(0,n):
if i == 0:
n1 = int(num/2)
bin_arr.append(num%2)
else:
bin_arr.append(n1%2)
n1 = int(n1/2)
if n1 == 0:
break
print(bin_arr)
result = ""
count = 0
count_arr = []
for i in bin_arr:
if result == "found":
if i == 0:
count += 1
else:
if count > 0:
count_arr.append(count)
count = 0
if i == 1:
result = 'found'
else:
pass
if len(count_arr) == 0:
return 0
else:
return max(count_arr)
print(LongestBinaryGap(1130)) # Here you can pass any number.
My code in python 3.6 scores 100
Get the binary Number .. Get the positions of 1
get the abs differennce between 1.. sort it
S = bin(num).replace("0b", "")
res = [int(x) for x in str(S)]
print(res)
if res.count(1) < 2 or res.count(0) < 1:
print("its has no binary gap")
else:
positionof1 = [i for i,x in enumerate(res) if x==1]
print(positionof1)
differnce = [abs(j-i) for i,j in zip(positionof1, positionof1[1:])]
differnce[:] = [differnce - 1 for differnce in differnce]
differnce.sort()
print(differnce[-1])
def solution(N):
return len(max(bin(N).strip('0').split('1')[1:]))
def solution(N):
maksimum = 0
zeros_list = str(N).split('1')
if zeros_list[-1] != "" :
zeros_list.pop()
for item in zeros_list :
if len(item) > maksimum :
maksimum = len(item)
return(maksimum)
def solution(N):
# Convert the number to bin
br = bin(N).split('b')[1]
sunya=[]
groupvalues=[]
for i in br:
count = i
if int(count) == 1:
groupvalues.append(len(sunya))
sunya=[]
if int(count) == 0:
sunya.append('count')
return max(groupvalues)
def solution(N):
bin_num = str(bin(N)[2:])
bin_num = bin_num.rstrip('0')
bin_num = bin_num.lstrip('0')
list1 = bin_num.split('1')
max_gap = 0
for i in range(len(list1)):
if len(list1[i]) > max_gap:
max_gap = len(list1[i])
return (max_gap)

python3 binary search not working [duplicate]

I am trying to implement the binary search in python and have written it as follows. However, I can't make it stop whenever needle_element is larger than the largest element in the array.
Can you help? Thanks.
def binary_search(array, needle_element):
mid = (len(array)) / 2
if not len(array):
raise "Error"
if needle_element == array[mid]:
return mid
elif needle_element > array[mid]:
return mid + binary_search(array[mid:],needle_element)
elif needle_element < array[mid]:
return binary_search(array[:mid],needle_element)
else:
raise "Error"
It would be much better to work with a lower and upper indexes as Lasse V. Karlsen was suggesting in a comment to the question.
This would be the code:
def binary_search(array, target):
lower = 0
upper = len(array)
while lower < upper: # use < instead of <=
x = lower + (upper - lower) // 2
val = array[x]
if target == val:
return x
elif target > val:
if lower == x: # these two are the actual lines
break # you're looking for
lower = x
elif target < val:
upper = x
lower < upper will stop once you have reached the smaller number (from the left side)
if lower == x: break will stop once you've reached the higher number (from the right side)
Example:
>>> binary_search([1,5,8,10], 5) # return 1
1
>>> binary_search([1,5,8,10], 0) # return None
>>> binary_search([1,5,8,10], 15) # return None
Why not use the bisect module? It should do the job you need---less code for you to maintain and test.
array[mid:] creates a new sub-copy everytime you call it = slow. Also you use recursion, which in Python is slow, too.
Try this:
def binarysearch(sequence, value):
lo, hi = 0, len(sequence) - 1
while lo <= hi:
mid = (lo + hi) // 2
if sequence[mid] < value:
lo = mid + 1
elif value < sequence[mid]:
hi = mid - 1
else:
return mid
return None
In the case that needle_element > array[mid], you currently pass array[mid:] to the recursive call. But you know that array[mid] is too small, so you can pass array[mid+1:] instead (and adjust the returned index accordingly).
If the needle is larger than all the elements in the array, doing it this way will eventually give you an empty array, and an error will be raised as expected.
Note: Creating a sub-array each time will result in bad performance for large arrays. It's better to pass in the bounds of the array instead.
You can improve your algorithm as the others suggested, but let's first look at why it doesn't work:
You're getting stuck in a loop because if needle_element > array[mid], you're including element mid in the bisected array you search next. So if needle is not in the array, you'll eventually be searching an array of length one forever. Pass array[mid+1:] instead (it's legal even if mid+1 is not a valid index), and you'll eventually call your function with an array of length zero. So len(array) == 0 means "not found", not an error. Handle it appropriately.
This is a tail recursive solution, I think this is cleaner than copying partial arrays and then keeping track of the indexes for returning:
def binarySearch(elem, arr):
# return the index at which elem lies, or return false
# if elem is not found
# pre: array must be sorted
return binarySearchHelper(elem, arr, 0, len(arr) - 1)
def binarySearchHelper(elem, arr, start, end):
if start > end:
return False
mid = (start + end)//2
if arr[mid] == elem:
return mid
elif arr[mid] > elem:
# recurse to the left of mid
return binarySearchHelper(elem, arr, start, mid - 1)
else:
# recurse to the right of mid
return binarySearchHelper(elem, arr, mid + 1, end)
def binary_search(array, target):
low = 0
mid = len(array) / 2
upper = len(array)
if len(array) == 1:
if array[0] == target:
print target
return array[0]
else:
return False
if target == array[mid]:
print array[mid]
return mid
else:
if mid > low:
arrayl = array[0:mid]
binary_search(arrayl, target)
if upper > mid:
arrayu = array[mid:len(array)]
binary_search(arrayu, target)
if __name__ == "__main__":
a = [3,2,9,8,4,1,9,6,5,9,7]
binary_search(a,9)
Using Recursion:
def binarySearch(arr,item):
c = len(arr)//2
if item > arr[c]:
ans = binarySearch(arr[c+1:],item)
if ans:
return binarySearch(arr[c+1],item)+c+1
elif item < arr[c]:
return binarySearch(arr[:c],item)
else:
return c
binarySearch([1,5,8,10,20,50,60],10)
All the answers above are true , but I think it would help to share my code
def binary_search(number):
numbers_list = range(20, 100)
i = 0
j = len(numbers_list)
while i < j:
middle = int((i + j) / 2)
if number > numbers_list[middle]:
i = middle + 1
else:
j = middle
return 'the index is '+str(i)
If you're doing a binary search, I'm guessing the array is sorted. If that is true you should be able to compare the last element in the array to the needle_element. As octopus says, this can be done before the search begins.
You can just check to see that needle_element is in the bounds of the array before starting at all. This will make it more efficient also, since you won't have to do several steps to get to the end.
if needle_element < array[0] or needle_element > array[-1]:
# do something, raise error perhaps?
It returns the index of key in array by using recursive.
round() is a function convert float to integer and make code fast and goes to expected case[O(logn)].
A=[1,2,3,4,5,6,7,8,9,10]
low = 0
hi = len(A)
v=3
def BS(A,low,hi,v):
mid = round((hi+low)/2.0)
if v == mid:
print ("You have found dude!" + " " + "Index of v is ", A.index(v))
elif v < mid:
print ("Item is smaller than mid")
hi = mid-1
BS(A,low,hi,v)
else :
print ("Item is greater than mid")
low = mid + 1
BS(A,low,hi,v)
BS(A,low,hi,v)
Without the lower/upper indexes this should also do:
def exists_element(element, array):
if not array:
yield False
mid = len(array) // 2
if element == array[mid]:
yield True
elif element < array[mid]:
yield from exists_element(element, array[:mid])
else:
yield from exists_element(element, array[mid + 1:])
Returning a boolean if the value is in the list.
Capture the first and last index of the list, loop and divide the list capturing the mid value.
In each loop will do the same, then compare if value input is equal to mid value.
def binarySearch(array, value):
array = sorted(array)
first = 0
last = len(array) - 1
while first <= last:
midIndex = (first + last) // 2
midValue = array[midIndex]
if value == midValue:
return True
if value < midValue:
last = midIndex - 1
if value > midValue:
first = midIndex + 1
return False

Maximum Recursion Depth reached Merge Sort

I have been trying to implement merge sort but I keep running into a "Maximum Recursion Depth" error. My current theory is that "if listlen <= 1:" isn't catching it but I can't figure out why
def mergesort(listin):
listlen = len(listin)
if listlen <= 1:
return listin
left = []
right = []
i = 0
while i < listlen:
if i <= listlen / 2:
left.append(listin[i])
else:
right.append(listin[i])
i += 1
left = mergesort(left)
right = mergesort(right)
return merge(left, right)
def merge(listlef, listrig):
result = []
while len(listlef) != 0 and len(listrig) != 0:
if listlef[0] <= listrig[0]:
result.append(listlef[0])
listlef = listlef[1:]
else:
result.append(listrig[0])
listrig = listrig[1:]
while len(listlef) != 0:
result.append(listlef[0])
listlef = listlef[1:]
while len(listrig) != 0:
result.append(listrig[0])
listrig = listrig[1:]
return result
For a list of size 2, note that i will only be 0 and 1, both of which are less than or equal to 2/1 == 1.
Instead of fiddling with indices, though, just alternate which list you append to:
left = []
right = []
for item in listin:
left.append(item)
left, right = right, left

QuickSort with Pivot Function issue?

I have been looking at this for the past couple hours and can still not understand where I have messed up. I keep getting Index out of bounds errors like below:
Each small edit or change i have done, has run me into another error, then i end back up here after trying to simplify my code.
def quickSort(alist):
firstList = []
secondList = []
thirdList = []
if(len(alist) > 1):
#pivot = pivot_leftmost(alist)
#pivot = pivot_best_of_three(alist)
pivot = pivot_ninther(alist)
#pivot = pivot_random(alist)
for item in alist:
if(item < pivot):
firstList.append(item)
if(item == pivot):
secondList.append(item)
if(item > pivot):
thirdList.append(item)
sortedList = quickSort(firstList) + secondList + quickSort(thirdList)
return sortedList
else:
print("list:", alist)
print("sorted, nothing to do") #debug
print("") #debug
return alist
def pivot_ninther(alist):
listLength = int(len(alist))
third = int(listLength / 3)
leftList = alist[:third]
midlist = alist[third:(third * 2)]
lastlist = alist[(third * 2):(third * 3)]
leftBest = pivot_best_of_three(leftList)
midBest = pivot_best_of_three(midlist)
lastBest = pivot_best_of_three(lastlist)
pivots = [leftBest, midBest, lastBest]
return pivot_best_of_three(pivots)
I am pretty sure a fresh pair of eyes can easily find it, but i have been lookig at it for hours. Thanks!
UPDATE: (My Best_of_three function)
def pivot_best_of_three(alist):
leftmost = 0
middle = int(len(alist) / 2)
rightmost = len(alist) - 1
if (alist[leftmost] <= alist[middle] <= alist[rightmost] or alist[rightmost] <= alist[middle] <= alist[leftmost]):
return alist[middle]
elif (alist[middle] <= alist[leftmost] <= alist[rightmost] or alist[rightmost] <= alist[leftmost] <= alist[middle]):
return alist[leftmost]
else:
return alist[rightmost]
The IndexError occurs when pivot_best_of_three tries to find the rightmost member of a list of zero items. The simple way to fix that is to simply not pass it such lists. :)
Here are slightly modified versions of those functions. I've tested these versions with lists of various lengths, down to length zero, and they appear to function correctly.
def pivot_ninther(alist):
listLength = len(alist)
if listLength < 3:
return alist[0]
third = listLength // 3
leftList = alist[:third]
midlist = alist[third:-third]
lastlist = alist[-third:]
leftBest = pivot_best_of_three(leftList)
midBest = pivot_best_of_three(midlist)
lastBest = pivot_best_of_three(lastlist)
pivots = [leftBest, midBest, lastBest]
return pivot_best_of_three(pivots)
def pivot_best_of_three(alist):
leftmost = alist[0]
middle = alist[len(alist) // 2]
rightmost = alist[-1]
if (leftmost <= middle <= rightmost) or (rightmost <= middle <= leftmost):
return middle
elif (middle <= leftmost <= rightmost) or (rightmost <= leftmost <= middle):
return leftmost
else:
return rightmost
As you can see, I've simplified pivot_best_of_three so it doesn't index alist multiple times for the same value.
But it can be simplified further by using a simple sorting network:
def sort3(a, b, c):
if c < b: b, c = c, b
if b < a: a, b = b, a
if c < b: b, c = c, b
return a, b, c
def pivot_best_of_three(alist):
leftmost = alist[0]
middle = alist[len(alist) // 2]
rightmost = alist[-1]
return sort3(leftmost, middle, rightmost)[1]
Try a smaller count (<= 20) and check to see what happens in pivot_ninther() when third == 0 (at the deepest level of recursion)? Seems like it would create empty arrays and then try to index them.
The code should check to make sure length >= 9 before calling pivot_ninther(), then >= 3 if calling ...best_of_three(). If just one or two items, pick one.
Suggestion, after you get the quicksort to work, back up the source code and rather than make new arrays, the pivot function should work with the original array and first / middle / last indexes.
You can use swaps to simplify finding the median of 3. This will help in cases like starting with a reversed order array.
// median of 3
i = lo, j = (lo + hi)/2, k = hi;
if (a[k] < a[i])
swap(a[k], a[i]);
if (a[j] < a[i])
swap(a[j], a[i]);
if (a[k] < a[j])
swap(a[k], a[j]);
pivot = a[j];
wiki article:
http://en.wikipedia.org/wiki/Quicksort#Choice_of_pivot

Quicksort intermediate list printing Python

The prompt for this HackerRank problem has me stumped. It is essentially a quicksort implemention but as an exception you are required to print the intermediate (or semi-sorted) "original" array in its entirety each iteration.
My working code without printing intermediates. It works as expected.
def quicksort(array):
if len(array) > 1:
left = 0
right = len(array)-2
pivot = len(array)-1
while left <= right:
while array[left] < array[pivot]:
left +=1
while array[right] > array[pivot]:
right -= 1
if left <= right:
array[left], array[right] = array[right], array[left]
left += 1
right -=1
array[left], array[pivot] = array[pivot], array[left]
return quicksort(array[0:left]) + quicksort(array[left::])
else:
# return single element arrays
return array
And below is my attempt at implementing a way to print intermediates. I.e. I am trying to keep the indices separate instead of just passing the spliced list like the above example so that I will always have access to the full array in the first function parameter.
def quicksort2(array, start=0, end=None):
size = len(array[start:end])
if size > 1:
left = start
right = len(array[start:end])-2
pivot = len(array[start:end])-1
print("Print")
print("left: {}\nright: {}\npivot: {}".format(left, right, pivot))
while left <= right:
while array[left] < array[pivot]:
left +=1
while array[right] > array[pivot]:
right -= 1
if left <= right:
array[left], array[right] = array[right], array[left]
left += 1
right -=1
array[left], array[pivot] = array[pivot], array[left]
print(array)
print("the end is {}".format(end))
size = len(array[0:left]) # 3
return quicksort2(array, start=0, end=left) + quicksort2(array, start=left, end=left+(size-len(array)))
else:
# return single element arrays
return array
if __name__ == '__main__':
size = int(input()) # size is 7
arr = [int(i) for i in input().split()]
print(quicksort2(arr, start=0, end=size))
However, now the list are not fully sorted on the second half of the input list so I am sure it has something to do with the end keyword parameter that is passed at the bottom of the quicksort2 definition.
Figured out what I was doing wrong. I really needed to use the Lomuto Partitioning method in order to satisfy the requirements of the print statements.
Code for anyone searching for this in the future
def partition(array, lo, hi):
pivot_index = hi
pivot_value = array[pivot_index]
store_index = lo
for i in range(lo, hi):
if array[i] <= pivot_value:
array[i], array[store_index] = array[store_index], array[i]
store_index += 1
array[pivot_index], array[store_index] = array[store_index], array[pivot_index]
return store_index
def quicksort(array, lo, hi):
if lo < hi:
p = partition(array, lo, hi)
print(' '.join([str(i) for i in array]))
quicksort(array, lo, p-1)
quicksort(array, p+1, hi)
if __name__ == '__main__':
size = int(input())
ar = [int(i) for i in input().split()]
quicksort(ar, 0, size-1)

Categories