How can I divide indices in massive - python

I have an sort algorithm
def partition(competitors, left, right):
pivot = competitors[left]
i = left + 1
j = right - 1
while True:
if (i <= j and competitors[j] > pivot):
j -= 1
elif (i <= j and competitors[i] < pivot):
i += 1
elif (competitors[j] > pivot) or (competitors[i] < pivot):
continue
if i <= j:
competitors[i], competitors[j] = competitors[j], competitors[i]
else:
competitors[left], competitors[j] = competitors[j], competitors[left]
return j
def quick_sort(competitors, left, right):
if ((right - left) > 1):
p = partition(competitors, left, right)
quick_sort(competitors, left, p)
quick_sort(competitors, p + 1, right)
def transformation(competitors):
competitors[1] = - int(competitors[1])
competitors[2] = int(competitors[2])
return [competitors[1], competitors[2], competitors[0]]
if __name__ == '__main__':
number = int(input())
competitors = [transformation(input().split()) for _ in range(number)]
quick_sort(competitors, left=0, right=len(competitors))
print(*(list(zip(*competitors))[2]), sep="\n")
Here
pivot = competitors[left]
Reviewer said that i can get a pivot by divide first and last index in array.
I was try many options and one of that is
pivot = competitors[left // right]
But output is wrong
Here description of task
**
Let's get two pointers left and right, which appear on the left and right ends of the segment, respectively. Then we will move the left pointer to the right until it triggers an alarm on the element smaller than the pivot. Similarly, we move the right pointer to the left while it is on the element that exceeds the reference one.As a result, it turns out that to the left of left all elements exactly belong to the first group, and to the right of right - to the second. Elements with pointers are out of order. Let's swap them (most programming languages ​​use the swap() function) and advance pointers to the next elements. We will repeat this action until left and right collide.
**
Input:
5
alla 4 100
gena 6 1000
gosha 2 90
rita 2 90
timofey 4 80
Output:
gena
timofey
alla
gosha
rita
And my output is: gena
timofey
alla
<rita>
<gosha>
Please help me to figure out how solve this algorithm

So this is a new algorithm, I was update it with pivot = competitors[(left + right) // 2] string
def partition(competitors, left, right):
if right <= left:
return
pivot = (left + right) // 2
part = competitors[pivot]
begin = left
end = right
while begin <= end:
while part > competitors[begin]:
begin += 1
while part < competitors[end]:
end -= 1
if begin <= end:
competitors[begin], competitors[end] = competitors[
end], competitors[begin]
begin += 1
end -= 1
partition(competitors, left, end)
partition(competitors, begin, right)
def quick_sort(competitors):
partition(competitors, 0, len(competitors) - 1)
return [line[2] for line in competitors]
if __name__ == '__main__':
n = int(input())
competitors = [None] * n
for x in range(n):
login, Pi, Fi = input().split()
competitors[x] = (-int(Pi), int(Fi), login)
result = quick_sort(competitors)
print(*result, sep="\n")

Related

max_heapify iterative way to go down the heaps to get the next level nodes

I am trying to write a iterative control loop instead of recursion because it is more efficient can someone tell me if my code makes sense:
Recursive version:
def max_heapify(array, i):
left = 2 * i
right = 2 * i + 1
length = len(array) - 1 # for termination condition check
largest = i
if left <= length and array[i] < array[left]:
largest = left
if right <= length and array[largest] < array[right]:
largest = right
if largest != i:
array[i], array[largest] = array[largest], array[i]
max_heapify(array, largest)
Iterative version(I think this is wrong??)
def max_heapify(array, i):
left = 2 * i
right = 2 * i + 1
length = len(array) - 1 # for termination condition check
largest = i
if left <= length and array[i] < array[left]:
largest = left
if right <= length and array[largest] < array[right]:
largest = right
if largest != i:
array[i], array[largest] = array[largest], array[i]
i= largest
Can I get suggestions to what is wrong with iterative version
Actually I think I figured
def max_heapify(array, i):
left = 2 * i
right = 2 * i + 1
length = len(array) - 1 # for termination condition check
largest = i
if left <= length and array[i] < array[left]:
largest = left
if right <= length and array[largest] < array[right]:
largest = right
if largest != i:
array[i], array[largest] = array[largest], array[i]
i= largest
else:
break

How can I count the swaps in a Merge Sort Algorithm in Python [duplicate]

This question already has answers here:
Counting inversions in an array
(38 answers)
Closed 5 years ago.
I've done the MergeSort algorithm, but I don't know how to count the swaps.
My code is:
def mergesortInv(list):
if len(list) < 2:
return list
else:
middle = len(list) // 2
left = mergesortInv(list[:middle]) #definim les dues meitats
right = mergesortInv(list[middle:])
swaps=???
return mergeInv(left, right,swaps)
def mergeInv(left, right,swaps):
if len(left) < 1:
return right
if len(right) < 1:
return left
if left[0] <= right[0]:
return [left[0]] + mergeInv(left[1:],right,swaps)
else:
return [right[0]] + mergeInv(left,right[1:],swaps)
The output of this algorithm would be the sorted list(the algorithm works in this part) and the number of swaps: mergesortInv(list) == ([1, 2, 3, 4, 5, 7, 8], 6) 6 is the number of swaps.
Here is a slightly modified version of your code that appears to work:
def mergesortInv(list, mergeInv):
if len(list) < 2:
return list, 0
else:
middle = len(list) // 2
left, lc = mergesortInv(list[:middle], mergeInv) #definim les dues meitats
right, rc = mergesortInv(list[middle:], mergeInv)
merge, mc = mergeInv(left, right)
return merge, lc + rc + mc
def mergeInvRec(left, right):
if len(left) < 1:
return right, 0
if len(right) < 1:
return left, 0
if left[0] <= right[0]:
res, cnt = mergeInvRec(left[1:], right)
return [left[0]] + res, cnt
else:
res, cnt = mergeInvRec(left, right[1:])
return [right[0]] + res, len(left) + cnt
def mergeInvFlat(left, right):
res, cnt = [], 0
il, ir = 0, 0
nl, nr = len(left), len(right)
while il < nl and ir < nr:
if left[il] <= right[ir]:
res.append(left[il])
il += 1
else:
res.append(right[ir])
ir += 1
cnt += nl - il
res.extend(left[il:])
res.extend(right[ir:])
return res, cnt
It's mostly a matter of book keeping. Count the number of swaps at each step and add them. In the very last branch the first element of right bubbles all the way past every element of left which is why we tally len(left) swaps there.
Edit: As #PM2Ring points out the recursion in mergeInv is a bit reckless and will exceed Python's maximum recursion depth for moderately sized lists.
I've added a non-recursive version. You can switch between the recursive and nonrecursive versions by passing their name as the second arg to the main function.
I didn't test this, but this is just to give you an idea about what I suggested in the comment to your question.
def mergesortInv(list):
if len(list) < 2:
return list
else:
middle = len(list) // 2
left = mergesortInv(list[:middle]) #definim les dues meitats
right = mergesortInv(list[middle:])
# swaps=???
return mergeInv(left, right)
def mergeInv(left, right):
""" return a tuple of total swaps and the merged list """
if len(left) < 1:
return (0, right)
if len(right) < 1:
return (0, left)
if left[0] <= right[0]:
swaps, lst = mergeInv(left[1:],right)
return (swaps, [left[0]] + [lst])
else:
swaps, lst = mergeInv(left,right[1:])
return (swaps + 1, [right[0]] + [lst])
Usage,
swaps, lst = mergesortInv(mylist)

Bug with in-place quick selection (aka linear time selection) in Python

I am following the Stanford course "Algorithms: Design and Analysis, Part 1", while trying implement an in place randomized selection algorithm in Python (i.e. selection based on quick sort), I believe my partition function is correct, but I just cannot figure out why the selection part keeps failing, any suggestion is greatly appreciated. My code is as follows:
import random
def random_selection(nums, start, end, i):
if end == start:
return nums[start]
elif start < end:
pivot = partition(nums, start, end)
if pivot == i:
return nums[pivot]
elif pivot < i:
# original code suffering from logic error with indices, fixed by changing 'i - pivot' into 'i'
# return random_selection(nums, pivot + 1, end, i - pivot)
return random_selection(nums, pivot + 1, end, i)
elif pivot > i:
return random_selection(nums, start, pivot - 1, i)
else:
return False
def partition(nums, start, end):
pivot_value = nums[start]
left = start + 1
right = end
done = False
while not done:
while left <= right and nums[left] < pivot_value:
left += 1
while left <= right and nums[right] > pivot_value:
right -= 1
if left > right:
done = True
else:
nums[left], nums[right] = nums[right], nums[left]
nums[start], nums[right] = nums[right], nums[start]
return right
test = range(10)
for i in range(10):
random.shuffle(test)
print random_selection(test, 0, len(test)-1, i)
Below are the results I am receiving with the test case:
0
1
None
3
4
None
5
4
8
None
The problem is you need to decide whether your indices are based on 0, or based on start.
Most of the code uses indices based on 0, except the recursive call to random_selection:
return random_selection(nums, pivot + 1, end, i - pivot)
which adjusts the i index to i - start (i.e. assuming the indices are based on start).
Changing this to:
return random_selection(nums, pivot + 1, end, i)
should give the expected results.

Majority Element Python

I'm having trouble getting the right output on my "Majority Element" divide and conquer algorithm implementation in Python 3.
This should be relatively correct; however, it would still appear that I'm missing something or it is slightly off and I cannot figure out why that is.
I've tried some debugging statement and different things. It looks like on the particular case listed in the comment above the code, it's resolving -1 for "left_m" and 941795895 for "right_m" when it does the recursive calls. When it compares the element at each index to those variables, the counter will obviously never increment.
Am I going about this the wrong way? Any help would be greatly appreciated.
Thanks.
# Input:
# 10
# 2 124554847 2 941795895 2 2 2 2 792755190 756617003
# Your output:
# 0
#
# Correct output:
# 1
def get_majority_element(a, left, right):
if left == right:
return -1
if left + 1 == right:
return a[left]
left_m = get_majority_element(a, left, (left + right - 1)//2)
right_m = get_majority_element(a, (left + right - 1)//2 + 1, right)
left_count = 0
for i in range(0, right):
if a[i] == left_m:
left_count += 1
if left_count > len(a)//2:
return left_m
right_count = 0
for i in range(0, right):
if a[i] == right_m:
right_count += 1
if right_count > len(a)//2:
return right_m
return -1
if __name__ == '__main__':
input = sys.stdin.read()
n, *a = list(map(int, input.split()))
if get_majority_element(a, 0, n) != -1:
print(1)
else:
print(0)
When counting the appearance of left and right major elements, your loops go over the range(0, right). Instead, they should be going over the range(left, right). Starting from 0 may, and will cause returning incorrect major elements in the smaller subproblems.
Also, in addition to the problem of having incorrect starting indices in ranges your for loops cover, you seem to have a problem in your recursive call arguments, probably due to your intuition causing you to overlook some details. Throughout the get_majority_element function, you treat parameter right to be the first index that is not in the list, as opposed to right being the index of the rightmost element in the list.
However, in your first recursive call, you give the third argument as if it is the last element included in that list. If right is the index of the first element not in that list, it should actually be the same with the second parameter of the second recursive call you're making in the following line. So, the third argument of the first recursive call you're making is less than it should be, by 1, causing you to overlook 1 element each time you recursively go down.
Thirdly, you have an error in the if statements following the for loops, similar to the problem you had with loop ranges. You are dividing the occurances of the element for all len(a) elements, although you should only care about the subproblem you are currently working on. So, you should divide it by the number of elements in that subproblem, rather than len(a). (i.e. (right - left)//2)
You can find the working code below, and look here in order to observe it's execution.
def get_majority_element(a, left, right):
if left == right:
return -1
if left + 1 == right:
return a[left]
left_m = get_majority_element(a, left, (left + right - 1)//2 + 1)
right_m = get_majority_element(a, (left + right - 1)//2 + 1, right)
left_count = 0
for i in range(left, right):
if a[i] == left_m:
left_count += 1
if left_count > (right-left)//2:
return left_m
right_count = 0
for i in range(left, right):
if a[i] == right_m:
right_count += 1
if right_count > (right-left)//2:
return right_m
return -1
if __name__ == '__main__':
input = sys.stdin.read()
n, *a = list(map(int, input.split()))
print("n=" + str(n))
if get_majority_element(a, 0, len(a)) != -1:
print(1)
else:
print(0)
I am trying to use Boyers and Moore's algorithm to find the majority element among a list. I am using a inbuilt function, count; so, if the majority element is greater than half size of the list then it gives output of 1, otherwise 0. You can find more in this link about Boyers and Moore's Algorithm on finding majority Algorithm information here
# Uses python3
import sys
def get_majority_element(a,n):
maximum = a[0]
amount = 1
for i in (a[1:]):
if not maximum == i:
if amount >= 1:
amount = amount - 1
else:
maximum = i
amount = 1
else:
amount = amount + 1
output = a.count(maximum)
if output > n//2:
return 1
return 0
if __name__ == '__main__':
input = sys.stdin.read()
n, *a = list(map(int, input.split()))
print (get_majority_element(a,n))

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