MergeSort in python - python

def merge(A,l,m,r):
i = l
j = m+1
new = []
while i <= m and j <= r:
if A[i] <= A[j]:
new.append(A[i])
i += 1
else:
new.append(A[j])
j += 1
while i <= m:
new.append(A[i])
i += 1
while j <= r:
new.append(A[j])
j += 1
return new
This function doesn't work due to an error, can you help me to understand what is the error and how to fix it?

This statement doesn't make sense:
return new
Since you nowhere use the return of the function. So the function merge() does nothing.
I believe you need to change the array A directly inside the function. No need to create and return the new array.

Related

change in list in the recursive call in python

I was studying merge sort and I understood the whole concept of it but when i went through the code i have a doubt this is the code
def mergeSort(arr):
if len(arr) > 1:
print('array before function', arr)
# Finding the mid of the array
mid = len(arr) // 2
print('mid',mid)
# Dividing the array elements
L = arr[:mid]
# into 2 halves
R = arr[mid:]
# Sorting the first half
mergeSort(L)
# Sorting the second half
mergeSort(R)
print('array after function',arr)
print('l is',L)
print('R is',R)
i = j = k = 0
# Copy data to temp arrays L[] and R[]
while i < len(L) and j < len(R):
if L[i] < R[j]:
arr[k] = L[i]
i += 1
else:
arr[k] = R[j]
j += 1
k += 1
# Checking if any element was left
while i < len(L):
arr[k] = L[i]
i += 1
k += 1
while j < len(R):
arr[k] = R[j]
j += 1
k += 1
# Code to print the list
def printList(arr):
for i in range(len(arr)):
print(arr[i], end=" ")
print()
# Driver Code
if __name__ == '__main__':
arr = [3,1,2,5,4]
print("Given array is", end="\n")
printList(arr)
mergeSort(arr)
print("Sorted array is: ", end="\n")
printList(arr)
what i cant understand is when mergeSort(L) is called how are the changes made in arr in the recursive call reflect back after scope of the recursive call is over.How is this possible ,if for example l=[2,3,1] is passed in mergesort(L) it will sort L but why is this sorted L value change when the recursive call is over ,is this only in the case of Recursion and If so How
arr is a global variable. when mergeSort is called, the recursive calls are slices of the list, which are local copies of the list. This goes on until the situation when len(mergeSort) == 1. Thus, in the call stack of the requisite function, for each call, there is a separate copy of the arr list.
Next, python passes mutable data (in particular, a list) by reference. When using arr [k], even though writing to a local variable occurs, this local variable refers to the object created in the mergeSort functions earlier.

Recursive function in python looks like it's acting out of scope, but it is not. What do I miss?

I was trying to figure out how the following code works,
def mergeSort(a):
if len(a) > 1:
mid = len(a)//2
left = a[:mid]
right = a[mid:]
mergeSort(left)
mergeSort(right)
i = j = k = 0
while i < len(left) and j < len(right):
if left[i] < right[j]:
a[k] = left[i]
i += 1
else:
a[k] = right[j]
j += 1
k += 1
while i < len(left):
a[k] = left[i]
i += 1
k += 1
while j < len(right):
a[k] = right[j]
j += 1
k += 1
return a
with Python tutor, when I noticed that the while-loop manipulates the 'A' list from the previous call. For me it looks like it's acting out of scope, but clearly it isn't.
Can you tell me what I'm missing that I'm thinking it's replacing elements of a list out of scope?
There is no such this as "acting out of scope". The rules of python guarntee that a variable can only be modified when it is in scope.
However, sometimes multiple variables refer to the same object. In the case of a function, this often happens with pass by reference. Here's an example:
def change_element(a):
a[1] = 42
x = list(range(10)
print(x)
change_element(x)
print(x)
Here you will see the element of x changes because the list is passed to change_element() by reference. This means that x and a both refer to the same list object.
Your example actually does exactly this kind of thing.

How to fix an 'index out of range' error in Python?

I would like to write en auxiliar function which is counting the occurences of every integer between 0 and li[-1], saying that li is a sorted list.
I can't see my mistake... I know what this kind of error message means, but I don't know where the variable j is reaching a limit.
def aux_compter_occurence(li):
resu = [0] * (li[-1]+1)
i = 0
j = 0
while i < (li[-1] + 1):
while li[j] == i:
resu[i] += 1
j +=1
i += 1
return resu
For example, with the input [2,4,4,4,7,8,8], the output should be [0,0,1,0,3,0,0,1,2]
collections.Counter can be passed an iteratable and will count each occurance, we can then use a simple comprehension to generate the result
import collections
def aux_compter_occurence(li):
counts = collections.Counter(li)
return [counts.get(i, 0) for i in range(li[-1] + 1)]
Or if you wish to use the previous method of incrementing the values in a list, you already know the index in the list because it is equal to the integer value. We can simplify quite a bit
def aux_compter_occurence(li):
resu = [0] * (li[-1] + 1)
for i in li:
resu[i] += 1
return resu
I added "j < len(li)" to your code and now it works.
def aux_compter_occurence(li):
resu = [0] * (li[-1]+1)
i = 0
j = 0
while i < (li[-1] + 1):
while j < len(li) and li[j] == i:
resu[i] += 1
j +=1
i += 1
return resu

QuickSort in Python. Increment in array trouble

I am trying to implement quicksort in python. Problem is how to increment/decrement value of i/j in array a. I know that I should write i=i+1 and there are no such thing like i++ in python, but I don't understand in which way I should do this.
I am newbie, here is my code.
def quicksort(a,lo,hi):
if(hi<=lo):
return
i = lo - 1
j = hi
v = a[hi]
while True:
while(a[++i] < v):
pass
while(v < a[--j]):
if(j==lo):
break
if(i>=j):
break
t = a[i]
a[i] = a[j]
a[j] = t
t = a[i]
a[i] = a[hi]
a[hi] = t
quicksort(a, lo, i - 1)
quicksort(a, i + 1, hi)
in python, you cannot assign and get the value, that's an intentional limitation to avoid issues with typos, find the proper sequence point...
You have no choice than to "emulate" the C-ported code:
while(a[++i] < v):
pass
while(v < a[--j]):
if(j==lo):
break
(note that both constructs generate an infinite loop because:
++i == i
and
--j == j
(applying unary plus any number of times or unary minus an even number of times gives the same number, see Why Don't Two Plus Operators Throw an Error (e.g., 1 + + 2))
So change to:
i += 1
while(a[i] < v):
i += 1
j -= 1
while(v < a[j]):
if(j==lo):
break
j -= 1
The following construct does not work the same way in Python as it does in C++:
while(a[++i] < v):
as well as this one:
while(v < a[--j]):
The way you change the code is the following:
def quicksort(a,lo,hi):
if(hi<=lo):
return
i = lo - 1
j = hi
v = a[hi]
while True:
i += 1
while(a[i] < v):
i += 1
pass
j -= 1
while(v < a[j]):
j -= 1
if(j==lo):
break
if(i>=j):
break
t = a[i]
a[i] = a[j]
a[j] = t
t = a[i]
a[i] = a[hi]
a[hi] = t
quicksort(a, lo, i - 1)
quicksort(a, i + 1, hi)

Deleting element in a python list iterated by index

folks
i have the following code:
for i in range(len(self.corpses)):
for j in range(len(self.corpses))[i+1:]:
if self.corpses[i].collides(self.corpses[j]):
self.corpses[i] = self.corpses[i] + self.corpses[j]
self.corpses.remove(self.corpses[j])
but this keeps going out of index.I would like to know what I do to remove the corpse under those conditions.
Thanks in advance.
You changed the length of the list. You could use a while loop instead:
i, l = 0, len(self.corpses)
while i < l:
j = i + 1
while j < l:
if self.corpses[i].collides(self.corpses[j]):
self.corpses[i] = self.corpses[i] + self.corpses[j]
del self.corpses[j]
l -= 1
else:
j += 1
i += 1
This way you keep full control over all changes.

Categories

Resources