Calling one function two time results in strange results in Python - python

In the following code, I call the Sort function two times with a different behavior but it returns the same results. In the advancedSort() function, I called Sort() function two times with different behavior (order) and saved each result in different lists but when I am printing the lists the results are the same!
def Sort(inputs, order = "ascending"):
if order == "ascending":
for i in range(len(inputs)):
for j in range(i + 1, len(inputs)):
if inputs[i] > inputs[j]:
inputs[i], inputs[j] = inputs[j], inputs[i]
elif order == "decending":
for i in range(len(inputs)):
for j in range(i + 1, len(inputs)):
if inputs[i] < inputs[j]:
inputs[i], inputs[j] = inputs[j], inputs[i]
else:
raise ValueError(order)
return inputs
def advancedSort(inputList, inputOrder):
if inputOrder == "ascending":
newList = Sort(inputList, "ascending")
return newList
elif inputOrder == "decending":
newList = Sort(inputList, "decending")
return newList
elif inputOrder == "both":
newList1 = Sort(inputList, "ascending")
newList2 = Sort(inputList, "decending")
return newList1, newList2
else:
raise ValueError(order)
a = [1, 4, 7, 7, 0, 6, 4]
print(a)
b, c = advancedSort(a, "both")
print(b)
print(c)
Output is:
[1, 4, 7, 7, 0, 6, 4]
[7, 7, 6, 4, 4, 1, 0]
[7, 7, 6, 4, 4, 1, 0]

When Sort() runs the first time it'll change the list referenced by a.
When you run it a second time, it's not using the original list you've defined in the beginning, but one already modified by Sort().
To address this you may use a shallow copy of the list:
newList1 = Sort(inputList.copy(), "ascending")
newList2 = Sort(inputList.copy(), "decending")
I used your code to print the memory address of each variable and their behavior in the routines:
def Sort(inputs, order = "ascending"):
if order == "ascending":
print(f"running the ascending routine with inputs = {inputs} ({hex(id(inputs))})")
for i in range(len(inputs)):
for j in range(i + 1, len(inputs)):
if inputs[i] > inputs[j]:
inputs[i], inputs[j] = inputs[j], inputs[i]
elif order == "decending":
print(f"""running the decending routine with inputs = {inputs} ({hex(id(inputs))})""")
for i in range(len(inputs)):
for j in range(i + 1, len(inputs)):
if inputs[i] < inputs[j]:
inputs[i], inputs[j] = inputs[j], inputs[i]
else:
raise ValueError(order)
return inputs
def advancedSort(inputList, inputOrder):
if inputOrder == "ascending":
newList = Sort(inputList, "ascending")
return newList
elif inputOrder == "decending":
newList = Sort(inputList, "decending")
return newList
elif inputOrder == "both":
newList1 = Sort(inputList, "ascending")
newList2 = Sort(inputList, "decending")
return newList1, newList2
elif inputOrder == "shallow":
newList1 = Sort(inputList.copy(), "ascending")
newList2 = Sort(inputList.copy(), "decending")
return newList1, newList2
else:
raise ValueError(order)
a = [1, 4, 7, 7, 0, 6, 4]
print(f"a = {a} ({hex(id(a))})")
print("\ntrying shallow mode")
b, c = advancedSort(a, "shallow")
print(f"b = {b} ({hex(id(b))})")
print(f"c = {c} ({hex(id(c))})")
print("\ntrying both mode")
d, e = advancedSort(a, "both")
print(f"a = {a} ({hex(id(a))})")
print(f"d = {d} ({hex(id(d))})")
print(f"e = {e} ({hex(id(e))})")
print("\nnow trying shallow mode again")
f, g = advancedSort(a, "shallow")
print(f"a = {a} ({hex(id(a))})")
print(f"f = {f} ({hex(id(f))})")
print(f"g = {g} ({hex(id(g))})")
Output:
a = [1, 4, 7, 7, 0, 6, 4] (0x7f4166c71240)
trying shallow mode
running the ascending routine with inputs = [1, 4, 7, 7, 0, 6, 4] (0x7f4166a535c0)
running the decending routine with inputs = [1, 4, 7, 7, 0, 6, 4] (0x7f4166ac8a80)
b = [0, 1, 4, 4, 6, 7, 7] (0x7f4166a535c0)
c = [7, 7, 6, 4, 4, 1, 0] (0x7f4166ac8a80)
trying both mode
running the ascending routine with inputs = [1, 4, 7, 7, 0, 6, 4] (0x7f4166c71240)
running the decending routine with inputs = [0, 1, 4, 4, 6, 7, 7] (0x7f4166c71240)
a = [7, 7, 6, 4, 4, 1, 0] (0x7f4166c71240)
d = [7, 7, 6, 4, 4, 1, 0] (0x7f4166c71240)
e = [7, 7, 6, 4, 4, 1, 0] (0x7f4166c71240)
now trying shallow mode again
running the ascending routine with inputs = [7, 7, 6, 4, 4, 1, 0] (0x7f4166ac88c0)
running the decending routine with inputs = [7, 7, 6, 4, 4, 1, 0] (0x7f4166ac8780)
a = [7, 7, 6, 4, 4, 1, 0] (0x7f4166c71240)
f = [0, 1, 4, 4, 6, 7, 7] (0x7f4166ac88c0)
g = [7, 7, 6, 4, 4, 1, 0] (0x7f4166ac8780)

I think, it is because your function Sort (by the way it is better to rename it with lowercase sort()) it is changing the value of the original list. So, when you call with "ascending" or "descending", there's no problem becuse you only order one time, but with "both" the newList2 = Sort(inputList, "decending") use an a list mutated.
You never must work with the original list, always clone it and make the changes in the clone it. To work:
def Sort(inputs, order = "ascending"):
cloned_list = inputs[:]
if order == "ascending":
for i in range(len(cloned_list)):
for j in range(i + 1, len(cloned_list)):
if cloned_list[i] > cloned_list[j]:
cloned_list[i], cloned_list[j] = cloned_list[j], cloned_list[i]
elif order == "decending":
for i in range(len(cloned_list)):
for j in range(i + 1, len(cloned_list)):
if cloned_list[i] < cloned_list[j]:
cloned_list[i], cloned_list[j] = cloned_list[j], cloned_list[i]
else:
raise ValueError(order)
return cloned_list
Output:
[1, 4, 7, 7, 0, 6, 4] # a
[0, 1, 4, 4, 6, 7, 7] # b
[7, 7, 6, 4, 4, 1, 0] # c

Related

Get Indeces of list of numbers Top N, next top N, and last top N

Given that I have a list of numbers:
raw_list = [10, 9, 2, 8, 1, 3, 5, 4, 6, 7,11]
I want to separate it to top N's three times. Which means I want to rank them.
# Top 6 rank as 3
# Next Top 4 rank as 2
# Last Top 1 rank as 1
ranked_list = [3, 3, 2, 3, 1, 2, 2, 2, 3, 3, 3]
What I tried:
sorted(range(len(raw_list)), key=lambda i: raw_list[i])[-2:]
But this only gives indeces of the topmost and not the next topmost value of the list.
Use:
lst = [10, 9, 2, 8, 1, 3, 5, 4, 6, 7, 11]
indices = sorted(range(len(lst)), key=lambda i: lst[i], reverse=True)
ranked_list = [0 for _ in range(len(lst))]
for i, j in enumerate(indices):
if i < 6:
ranked_list[j] = 3
elif i < 6 + 4:
ranked_list[j] = 2
else:
ranked_list[j] = 1
print(ranked_list)
Output
[3, 3, 2, 3, 1, 2, 2, 2, 3, 3, 3]
Here's a different approach which is significantly faster than the accepted answer (if that's important):
Edited to show performance timings between the original and accepted answer because #funnydman wants proof
from timeit import timeit
L = [10, 9, 2, 8, 1, 3, 5, 4, 6, 7, 11]
def func1(list_):
slist = sorted(list_)
result = []
top6 = set(slist[5:])
top4 = set(slist[1:5])
for e in list_:
if e in top6:
result.append(3)
elif e in top4:
result.append(2)
else:
result.append(1)
return result
def func2(list_):
indices = sorted(range(len(list_)), key=lambda i: list_[i], reverse=True)
ranked_list = [0 for _ in range(len(list_))]
for i, j in enumerate(indices):
if i < 6:
ranked_list[j] = 3
elif i < 6 + 4:
ranked_list[j] = 2
else:
ranked_list[j] = 1
return ranked_list
for func in func1, func2:
print(func.__name__, timeit(lambda: func(L)))
Output:
func1 1.3904414890002954
func2 2.388311982000232
IIUC, this will work for you:
import pandas as pd
list(pd.cut(l, bins=[0, 1, 5, 11], labels=[1, 2, 3]))
Output:
[3, 3, 2, 3, 1, 2, 2, 2, 3, 3, 3]

Python program to accept a List,and extract all elements whose frequency is greater than K?

Python - How can I write a python program to accept a List, and extract all elements whose frequency is greater than K? Please advise?
Sample I/O:
Input List:
[4, 6, 4, 3, 3, 4, 3, 4, 6, 6]
Input K:
2
Required Output : [4, 3, 6]
Use a list comprehension:
a = [4, 6, 4, 3, 3, 4, 3, 4, 6, 6]
k = 2
out = [i for i in set(a) if a.count(i) > k]
Use counter in python
list1 = [4, 6, 4, 3, 3, 4, 3, 4, 6, 6]
d = Counter(list1)
new_list = list([item for item in d if d[item] > 1])
print(new_list) #output: [4, 6, 3]
inputs = 0
user_list = []
while inputs < 8:
user_input = int(input("Enter a number: "))
user_list.append(user_input)
inputs += 1
input_list = [4, 6, 4, 3, 3, 4, 6, 6]
input_k = 2
def extract(x, y):
product = []
for i in x:
list_element = i
if list_element > y:
product.append(i)
else:
break
product = list(set(product))
return product
print(extract(user_list, input_k))
print(extract(input_list, input_k))

Finding ordered array in an ordered array

c = [-1, 0, 1, 2, 3, 4]
d = [-1,0,2,3,4,5,6]
a = [-1, 1, 6, 8, 9, 12]
main = [-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
desired output:
fc = [-1,0,1,2,3],[0,1,2,3,4]
fd = [2,3,4,5,6]
fa = []
I want to find how many times the ordered set is in the larger set given an interval. In my case, I choose 5 since this is for my poker game. Set's won't work since they need to be in order so I don't know what to use.
In my program, I tried using for loops but I'm not getting it.
ns = len(c)-5
nt = range(0,ns)
if ns >= 0:
for n in nt:
templist = c[n:n+5]
I just need a function to compare both lists.
Compare the small lists to slices of main.
c = [-1, 0, 1, 2, 3, 4]
d = [-1,0,2,3,4,5,6]
a = [-1, 1, 6, 8, 9, 12]
main = [-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
for sublist in [c, d, a]:
l = len(sublist)
i = 0
while i + l <= len(main):
if sublist == main[i:i+l]:
print 'sublist %s matches' % sublist
i = i + 1
Neither pretty nor optimal, but it does what seems to be asked:
c = [-1, 0, 1, 2, 3, 4]
d = [-1, 0, 2, 3, 4, 5, 6]
a = [-1, 1, 6, 8, 9, 12]
main = [-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
def find_in_order(to_find, to_search, num_to_find):
solutions = []
for bucket in to_find:
bucket_solutions = []
solutions.append(bucket_solutions)
for thing in [bucket[x:x + num_to_find] for x in range(len(bucket) - num_to_find + 1)]:
for section in [main[y:y + num_to_find] for y in range(len(to_search) - num_to_find + 1)]:
if thing == section:
bucket_solutions.append(thing)
return solutions
fc, fd, fa = find_in_order([c, d, a], main, 5)
# fc == [[-1, 0, 1, 2, 3], [0, 1, 2, 3, 4]]
# fd == [[2, 3, 4, 5, 6]]
# fa == []
There's not bounds-checking in this, so it might be brittle. I also don't like how the additions of the magic number 1 are needed to get things to align. If you care about speed, string searches do things like keeping a rolling checksum and only doing comparisons when the checksums match. This is left as an exercise. Also, I'm on:
sys.version
'3.6.8 |Anaconda, Inc.| (default, Dec 30 2018, 01:22:34) \n[GCC 7.3.0]'
Here is a function that I made that might help you. You can pass your list as an argument and it will compare the lists.
main_set = [-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
c = [-1, 0, 1, 2, 3, 4]
def compare(cmp_array):
new_arrays = []
temp = []
for pos, i in enumerate(cmp_array):
for i2 in range(pos, pos+5):
temp.append(cmp_array[i2])
new_arrays.append(temp)
temp = []
if pos >= len(cmp_array)-5:
break
return_arrays = []
for array in new_arrays:
for pos, i in enumerate(main_set):
match = True
if i == array[0]:
for pos2 in range(pos, pos+5):
if array[pos2-pos] != main_set[pos2]:
match = False
break
if match:
return_arrays.append(array)
return return_arrays
fc = compare(c)
print(fc)

Issue with array assignment in python

I can't figure out why the program is behaving in a peculiar way. The program is meant to rotate an array cyclically for 'K' times. When the list A is assigned to B in function rotate_array(), the program behaves in an incorrect way as shown in the output. Whereas when it is changed with the line B=[0]*len(A), the problem disappears. Could someone please help ?
def rotate_array(A):
#B = [0]*len(A) # This solves the problem
B = A # This seems to cause a problem
print "In rotate_array", A
for index, item in enumerate(A):
print "index:item ={}:{}, length of A={}".format(index, item, len(A))
if index == (len(A) - 1):
B[0] = A[index]
else:
B[index + 1] = item
print B
return B
def solution(A, K):
for index, item in enumerate(A):
print "in fn soln: index:item ={}:{}, length of A={}".format(index, item, len(A))
ctr = 0
while ctr < K:
A = rotate_array(A)
ctr += 1
return A
if __name__ == '__main__':
A = [1,2,3,4]
K = 1
ret_A = solution(A, K)
print ret_A
Output:
in fn soln: index:item =0:1, length of A=4
in fn soln: index:item =1:2, length of A=4
in fn soln: index:item =2:3, length of A=4
in fn soln: index:item =3:4, length of A=4
In rotate_array [1, 2, 3, 4]
index:item =0:1, length of A=4
index:item =1:1, length of A=4
index:item =2:1, length of A=4
index:item =3:1, length of A=4
[1, 1, 1, 1]
[1, 1, 1, 1]
When function rotate_array(A) is changed to have this line
B = [0]*len(A) # This solves the problem
instead of
B = A
The output is now correct -
in fn soln: index:item =0:1, length of A=4
in fn soln: index:item =1:2, length of A=4
in fn soln: index:item =2:3, length of A=4
in fn soln: index:item =3:4, length of A=4
In rotate_array [1, 2, 3, 4]
index:item =0:1, length of A=4
index:item =1:2, length of A=4
index:item =2:3, length of A=4
index:item =3:4, length of A=4
[4, 1, 2, 3]
[4, 1, 2, 3]
I see that John answered your question. I dont know all the details of what you are doing, so you may have a reason for looping, but I wanted to suggest an alternative implementation that didn't require looping K times if all you want is the final answer:
def rotate_array(A,K):
A_length = len(A)
B = [None] * A_length
for A_index in range(len(A)):
B_index = (A_index + K) % A_length
B[B_index] = A[A_index]
return(B)
A = list(range(10))
print("A = ", A)
for K in range(10):
B = rotate_array(A,K)
print("K = ",K, "B = ", B)
A = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
K = 0 B = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
K = 1 B = [9, 0, 1, 2, 3, 4, 5, 6, 7, 8]
K = 2 B = [8, 9, 0, 1, 2, 3, 4, 5, 6, 7]
K = 3 B = [7, 8, 9, 0, 1, 2, 3, 4, 5, 6]
K = 4 B = [6, 7, 8, 9, 0, 1, 2, 3, 4, 5]
K = 5 B = [5, 6, 7, 8, 9, 0, 1, 2, 3, 4]
K = 6 B = [4, 5, 6, 7, 8, 9, 0, 1, 2, 3]
K = 7 B = [3, 4, 5, 6, 7, 8, 9, 0, 1, 2]
K = 8 B = [2, 3, 4, 5, 6, 7, 8, 9, 0, 1]
K = 9 B = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]

Heap sort Python implementation

def heap_sort(nos):
global size
size = len(nos)
print "the size of the List is : %d " %size
Build_heap(size,nos)
for i in range(size-1,0,-1):
nums[0],nums[i] = nums[i],nums[0]
size = size-1
print "\n", nums
heapify(nos,i,size)
print "heap sort array:" ,nums
def left_child(i):
return 2*i+1
def right_child(i):
return 2*i+2
def heapify(nums,i,size):
l = left_child(i)
r = right_child(i)
if l <= size and r <= size:
if r != size:
if nums[l] >= nums[r]:
max = nums[l]
max_index = l
elif nums[l] <= nums[r]:
max = nums[r]
max_index = r
if nums[i] >= max:
print nums
return
elif nums[i] <= max:
nums[i],nums[max_index] = max,nums[i]
heapify(nums,max_index,size)
else:
nums[i],nums[l] = nums[l],nums[i]
print nums
# build a heap A from an unsorted array
def Build_heap(size,elements):
iterate = size//2-1
for i in range(iterate,-1,-1):
print "In %d iteration" %i
heapify(elements,i,size)
print "heapified array is : " ,elements
if __name__ == '__main__':
#get input from user
nums = [6,9,3,2,4,1,7,5,10]
#sort the list
heap_sort(nums)
Output which I get is something like this:
the size of the List is : 9
In 3 iteration
[6, 9, 3, 10, 4, 1, 7, 5, 2]
In 2 iteration
[6, 9, 7, 10, 4, 1, 3, 5, 2]
In 1 iteration
[6, 10, 7, 9, 4, 1, 3, 5, 2]
[6, 10, 7, 9, 4, 1, 3, 5, 2]
In 0 iteration
[10, 6, 7, 9, 4, 1, 3, 5, 2]
[10, 9, 7, 6, 4, 1, 3, 5, 2]
[10, 9, 7, 6, 4, 1, 3, 5, 2]
heapified array is : [10, 9, 7, 6, 4, 1, 3, 5, 2]
heap sort array:
[9, 7, 6, 4, 1, 3, 5, 2, 10]
I tried implementing a heap sort algorithm in python. The final output is not sorted. There is something wrong in the heapify operation which I tried to figure out, but I couldn't find it.
Can someone point out what's wrong in my code and propose a solution for it?
The first item(0) was swaped with the last item. To keep max-heap invairant, you should call heapify with 0.
def heap_sort(nos):
size = len(nos)
build_heap(size,nos)
for i in range(size-1,0,-1):
nums[0],nums[i] = nums[i],nums[0]
size -= 1
heapify(nos, 0, size) # <--- i -> 0
The following is my PYTHON implementation. If the program is "heapsort.py", an example to run it is "python heapsort.py 10", to sort 10 randomly generated numbers.
The validation code is near the end of the program, to verify the correctness of the function, heapsort().
#!/bin/python
#
# TH #stackoverflow, 2016-01-20, HeapSort
#
import sys, random
def pushdown( A, root, size_of_A ):
M = root * 2
if(M <= size_of_A):
if(size_of_A > M):
if(A[M - 1] < A[M]):
M += 1
if(A[root - 1] < A[M - 1]):
A[root - 1], A[M - 1] = A[M - 1], A[root - 1]
pushdown(A, M, size_of_A)
def heapsort( H ):
for i in range(len(H)/2, 0, -1):
pushdown(H, i, len(H))
for i in range(len(H) - 1, 0, -1):
H[i], H[0] = H[0], H[i]
pushdown(H, 1, i)
return H
number_to_numbers = int(sys.argv[1])
X = [ random.randint(0, number_to_numbers) for i in range(number_to_numbers) ]
Y = X
print Y
print heapsort(X)
print sorted(Y)

Categories

Resources