-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsorting_algorithms.py
More file actions
166 lines (129 loc) · 4.77 KB
/
sorting_algorithms.py
File metadata and controls
166 lines (129 loc) · 4.77 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
# We have a determined object
class Notebook:
def __init__(self, title, username, likes):
self.title, self.username, self.likes = title, username, likes
def __repr__(self):
return 'Notebook <"{}/{}", {} likes>'.format(self.username, self.title, self.likes)
# We can have a default_compare function that wil work with ints for example, but not objects
def default_compare(x, y):
if x < y:
return 'less'
elif x == y:
return 'equal'
else:
return 'greater'
# then we adapt sorting algorithms to use a custom compare function.
def insertion_sort(objs, compare):
nums = list(objs)
for i in range(len(objs)):
cur = nums.pop(i)
j = i-1
while j >=0:
result = compare(nums[j], cur)
if result == 'lesser' or result == 'equal':
break
else:
j -= 1
nums.insert(j+1, cur)
return nums
def bubble_sort(objs, compare):
nums = list(objs)
for _ in range(len(objs) - 1):
for i in range(len(objs) - 1):
result = compare(nums[i], nums[i+1])
if result == "greater":
nums[i], nums[i+1] = nums[i+1], nums[i]
return nums
# Here is an interesting use, in the partition function for finding the pivot in quicksort
def partition(objs, start=0, end=None, compare=default_compare):
# print('partition', nums, start, end)
if end is None:
end = len(objs) - 1
# Initialize right and left pointers
l, r = start, end-1
# Iterate while they're apart
while r > l:
result_l = compare(objs[l], objs[end])
result_r = compare(objs[r], objs[end])
# Increment left pointer if number is less or equal to pivot
if result_l == "lesser" or result_l == "equal":
l += 1
# Decrement right pointer if number is greater than pivot
elif result_r == "greater":
r -= 1
# Two out-of-place elements found, swap them
else:
objs[l], objs[r] = objs[r], objs[l]
# print(' ', nums, l, r)
# Place the pivot between the two parts
if compare(objs[l], objs[end]) == "greater":
objs[l], objs[end] = objs[end], objs[l]
return l
else:
return end
def quicksort(objs, start=0, end=None, compare=default_compare):
if end is None:
nums = list(objs)
end = len(objs) - 1
if start < end:
pivot = partition(objs, start, end, compare)
quicksort(objs, start, pivot-1, compare)
quicksort(objs, pivot+1, end, compare)
return objs
# The with mergesort
def merge_sort(objs, compare=default_compare):
if len(objs) < 2:
return objs
mid = len(objs) // 2
return merge(merge_sort(objs[:mid], compare),
merge_sort(objs[mid:], compare),
compare)
def merge(left, right, compare=default_compare):
i, j, merged = 0, 0, []
while i < len(left) and j < len(right):
result = compare(left[i], right[j])
if result == 'lesser' or result == 'equal':
merged.append(left[i])
i += 1
else:
merged.append(right[j])
j += 1
return merged + left[i:] + right[j:]
# Then, having these objects:
nb0 = Notebook('pytorch-basics', 'aakashns', 373)
nb1 = Notebook('linear-regression', 'siddhant', 532)
nb2 = Notebook('logistic-regression', 'vikas', 31)
nb3 = Notebook('feedforward-nn', 'sonaksh', 94)
nb4 = Notebook('cifar10-cnn', 'biraj', 2)
nb5 = Notebook('cifar10-resnet', 'tanya', 29)
nb6 = Notebook('anime-gans', 'hemanth', 80)
nb7 = Notebook('python-fundamentals', 'vishal', 136)
nb8 = Notebook('python-functions', 'aakashns', 74)
nb9 = Notebook('python-numpy', 'siddhant', 92)
notebooks = [nb0, nb1, nb2, nb3, nb4, nb5,nb6, nb7, nb8, nb9]
# We can use any comparing function, for example:
# We define a compare function with any object property
def compare_likes(nb1, nb2):
if nb1.likes > nb2.likes:
return 'lesser'
elif nb1.likes == nb2.likes:
return 'equal'
elif nb1.likes < nb2.likes:
return 'greater'
# We call in the sorting functions and sort them
print("Sorting by likes:")
print(merge_sort(notebooks, compare=compare_likes))
print(quicksort(notebooks, compare=compare_likes))
print(insertion_sort(notebooks, compare=compare_likes))
print(bubble_sort(notebooks, compare=compare_likes))
# We can change the comparing function, for example with titles
def compare_title(nb1, nb2):
if nb1.title > nb2.title:
return 'lesser'
elif nb1.title == nb2.title:
return 'equal'
elif nb1.title < nb2.title:
return 'greater'
print("Sorting by title:")
print(merge_sort(notebooks, compare=compare_title))
# Then we can use the algorithms to compare anything, just defining the function and adjusting the comparison