Skip to content

Commit 4af1c3d

Browse files
committed
Initial commit.
0 parents  commit 4af1c3d

13 files changed

+347
-0
lines changed

Diff for: .gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
*.pyc

Diff for: __init__.py

Whitespace-only changes.

Diff for: __main__.py

+75
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
#!/usr/bin/env python
2+
# coding: utf-8
3+
4+
from __future__ import print_function
5+
import os
6+
import sys
7+
import glob
8+
import random
9+
import argparse
10+
import importlib
11+
12+
from tabulate import tabulate
13+
14+
15+
def sort_algos(sample, sample_size, no_of_times, sample_range):
16+
pretty_print = lambda char, count: (print("{}".format(char*count)))
17+
current_dir = os.path.dirname(os.path.realpath(__file__))
18+
19+
sorting_algos = glob.glob("{}/*_sort.py".format(current_dir))
20+
sorting_algos = [x.split('/')[-1][:-3] for x in sorting_algos]
21+
22+
time_taken = [['Algorithm Name', 'Time Taken (Less Is Better!!)'], ]
23+
for algo in sorting_algos:
24+
module = importlib.import_module(algo)
25+
time_taken.append([algo.title().replace('_', ' '),
26+
"{0:.20f} sec".format(getattr(module, algo)(array=sample[:],
27+
repeat=no_of_times).time)])
28+
pretty_print('|', 50)
29+
print(
30+
"Sorting Algorithms Ran!\nArray Details And Algorithms Summary As Follow")
31+
pretty_print('|', 50)
32+
pretty_print('-', 50)
33+
print("Length Of Array: {}".format(sample_size))
34+
print("Range Of Numbers In Array: 0 to {}".format(sample_range-1))
35+
print("Number Of Times Array Were Sorted: {}".format(no_of_times))
36+
pretty_print('-', 50)
37+
print(tabulate(sorted(time_taken, key=lambda x: x[1], reverse=True),
38+
headers='firstrow', tablefmt="fancy_grid"))
39+
40+
41+
def run():
42+
"""
43+
Main Function to execute sorting algorithms
44+
"""
45+
parser = argparse.ArgumentParser()
46+
parser.add_argument("-s", "--size",
47+
type=int,
48+
help="Size of array to be sorted",
49+
default=1000)
50+
parser.add_argument("-l", "--loop",
51+
type=int,
52+
help="Number of times array sorting should be repeated",
53+
default=1)
54+
parser.add_argument("-r", "--range",
55+
type=int,
56+
help="Max range of number that should be present in array",
57+
default=None)
58+
args = parser.parse_args()
59+
60+
size = args.size
61+
repeat = args.loop
62+
max_range = args.range if args.range else size
63+
64+
# Generate sample which will be sorted by all algorithms
65+
sample = []
66+
try:
67+
sample = random.sample(range(max_range), size)
68+
except ValueError:
69+
print("Provided values range has to be greater than sample size")
70+
return None
71+
# Run all sorting algorithms
72+
sort_algos(sample, size, no_of_times=repeat, sample_range=max_range)
73+
74+
if __name__ == "__main__":
75+
run()

Diff for: bubble_sort.py

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#!/usr/bin/env python
2+
# coding: utf-8
3+
"""
4+
|------------------------------------------------------------|
5+
| Bubble Sort |
6+
|------------------------------------------------------------|
7+
|Also known as || sinking sort |
8+
|Worst case performance || О(n2) |
9+
|Best case performance || O(n) |
10+
|Average case performance || О(n2) |
11+
|Worst case space complexity || O(1) auxiliary |
12+
|------------------------------------------------------------|
13+
"""
14+
15+
from decorators import timethis
16+
17+
18+
@timethis
19+
def bubble_sort(array):
20+
size = len(array)
21+
for i in range(size):
22+
for j in range(i+1, size):
23+
if array[j] < array[i]:
24+
array[j], array[i] = array[i], array[j]
25+
return array

Diff for: decorators.py

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import timeit
2+
from collections import namedtuple
3+
4+
def _template_func(setup, func):
5+
"""
6+
Monkey Patching original timer function's _template_func.
7+
This is used if the "statement" is a callable. and returns a
8+
namedtuple containing 'output' property which has callable's
9+
result and 'time' property which has time taken by the to complete
10+
"""
11+
12+
Result = namedtuple('Result', ['time', 'output'])
13+
def inner(_it, _timer, _func=func):
14+
setup()
15+
_t0 = _timer()
16+
for _i in _it:
17+
output = _func()
18+
_t1 = _timer()
19+
timetaken = _t1 - _t0
20+
return Result(timetaken, output)
21+
return inner
22+
23+
timeit._template_func = _template_func
24+
25+
def timethis(fun):
26+
def _wrapped(*args, **kwargs):
27+
t = timeit.Timer(lambda: fun(*args, **kwargs))
28+
return t.timeit(number=kwargs.pop('repeat', 1))
29+
return _wrapped

Diff for: insertion_sort.py

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# coding: utf-8
2+
"""
3+
|------------------------------------------------------------|
4+
| Insertion Sort |
5+
|------------------------------------------------------------|
6+
|Type || In-place stable sort |
7+
|Worst case performance || O(n2) comparisons, swaps |
8+
|Best case performance || Ω(n) comparisons, O(1) swaps|
9+
|Average case performance || O(n2) comparisons, swaps |
10+
|Worst case space complexity || O(n) total, O(1) auxiliary |
11+
|------------------------------------------------------------|
12+
"""
13+
14+
from decorators import timethis
15+
16+
17+
@timethis
18+
def insertion_sort(array):
19+
size = len(array)
20+
for index in range(1, size):
21+
val = array[index]
22+
position = index
23+
24+
while position > 0 and array[position-1] > val:
25+
array[position] = array[position-1]
26+
position = position-1
27+
28+
array[position] = val
29+
return array

Diff for: merge_sort.py

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
"""
2+
|-----------------------------------------------------------|
3+
| Merge Sort |
4+
|-----------------------------------------------------------|
5+
|Type || Comparison base stable sort|
6+
|Worst case performance || O(n log n) |
7+
|Best case performance || O(n log n) or O(n) |
8+
|Average case performance || O(n log n) |
9+
|Worst case space complexity || O(n) or O(log n) |
10+
|-----------------------------------------------------------|
11+
"""
12+
13+
from decorators import timethis
14+
15+
16+
@timethis
17+
def merge_sort(array):
18+
def _sort(array):
19+
# Actual Merge Sort Function
20+
if len(array) == 1:
21+
return array
22+
else:
23+
mid = len(array)/2
24+
left = _sort(array[:mid])
25+
right = _sort(array[mid:])
26+
27+
left_counter, right_counter, counter = 0, 0, 0
28+
29+
while left_counter < len(left) and right_counter < len(right):
30+
if left[left_counter] < right[right_counter]:
31+
array[counter] = left[left_counter]
32+
left_counter += 1
33+
counter += 1
34+
else:
35+
array[counter] = right[right_counter]
36+
right_counter += 1
37+
counter += 1
38+
39+
remaining = left if left_counter < right_counter else right
40+
r = left_counter if remaining == left else right_counter
41+
42+
while r < len(remaining):
43+
array[counter] = remaining[r]
44+
r += 1
45+
counter += 1
46+
return array
47+
# Call the Merge Sort Function
48+
return _sort(array)

Diff for: quick_sort.py

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
"""
2+
|-----------------------------------------------------------|
3+
| Quick Sort |
4+
|-----------------------------------------------------------|
5+
|Type || Comparison sort |
6+
|Worst case performance || O(n2) |
7+
|Best case performance || O(n log n) or O(n) |
8+
|Average case performance || O(n log n) |
9+
|Worst case space complexity || O(n) or O(log n) |
10+
|-----------------------------------------------------------|
11+
"""
12+
13+
from decorators import timethis
14+
15+
16+
@timethis
17+
def quick_sort(array):
18+
def _sort(array):
19+
# Actual Quick Sort Function
20+
less = []
21+
equal = []
22+
greater = []
23+
if len(array) > 1:
24+
pivot = array[0]
25+
for x in array:
26+
if x < pivot:
27+
less.append(x)
28+
elif x == pivot:
29+
equal.append(x)
30+
else:
31+
greater.append(x)
32+
return _sort(less)+equal+_sort(greater)
33+
else:
34+
return array
35+
# Call the Quick Sort Function
36+
return _sort(array[:])

Diff for: requirements.txt

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
tabulate

Diff for: selection_sort.py

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
"""
2+
|-----------------------------------------------------------|
3+
| Selection Sort |
4+
|-----------------------------------------------------------|
5+
|Type || In-place comparison sort |
6+
|Worst case performance || O(n2) |
7+
|Best case performance || O(n2) |
8+
|Average case performance || O(n2) |
9+
|Worst case space complexity || O(n) total, O(1) auxiliary |
10+
|-----------------------------------------------------------|
11+
"""
12+
13+
from decorators import timethis
14+
15+
16+
@timethis
17+
def selection_sort(array):
18+
size = len(array)
19+
for i in range(size):
20+
smallest = i
21+
for x in range(i+1, size):
22+
if array[smallest] > array[x]:
23+
smallest = x
24+
array[i], array[smallest] = array[smallest], array[i]
25+
return array

Diff for: shell_sort.py

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
"""
2+
|-----------------------------------------------------------|
3+
| Shell Sort |
4+
|-----------------------------------------------------------|
5+
|Type || In-place comparison sort |
6+
|Worst case performance || O(n2) |
7+
|Best case performance || O(n log2 n) |
8+
|Average case performance || depends on gap sequence |
9+
|Worst case space complexity || O(n) total, O(1) auxiliary |
10+
|-----------------------------------------------------------|
11+
"""
12+
13+
from decorators import timethis
14+
15+
16+
@timethis
17+
def shell_sort(array):
18+
mid = len(array) / 2
19+
while mid:
20+
for i in range(len(array)):
21+
j = i
22+
temp = array[i]
23+
while j >= mid and array[j-mid] > temp:
24+
array[j] = array[j - mid]
25+
j -= mid
26+
array[j] = temp
27+
mid = mid/2 if mid/2 else (0 if mid == 1 else 1)
28+
return array

Diff for: test.py

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import os
2+
import glob
3+
import random
4+
import importlib
5+
import unittest
6+
7+
class SortAlgosTest(unittest.TestCase):
8+
def setUp(self):
9+
"""
10+
Common setup to load all sorting modules in current package
11+
following name convention of endswith('_sort.py'). Imprt
12+
"""
13+
current_dir = os.path.dirname(os.path.realpath(__file__))
14+
sorting_algos = glob.glob("{}/*_sort.py".format(current_dir))
15+
sorting_algos = [x.split('/')[-1][:-3] for x in sorting_algos]
16+
modules = [importlib.import_module(algo) for algo in sorting_algos]
17+
18+
self.sorting_algos = zip(sorting_algos, modules)
19+
20+
def test_algos_with_sequential_array(self):
21+
"""
22+
Test a shuffeld sample of 50 numbers. Sorted array contains
23+
50 numbers in sequence. Strating from 0 to 49
24+
"""
25+
self.array = random.sample(range(50), 50)
26+
for algo, module in self.sorting_algos:
27+
print ("Testing {}".format(algo))
28+
result = getattr(module, algo)(array=self.array[:], repeat=1).output
29+
for index, val in enumerate(range(50)):
30+
assert val == result[index]
31+
if __name__ == '__main__':
32+
unittest.main()

Diff for: tim_sort.py

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
"""
2+
|-----------------------------------------------------------|
3+
| Tim Sort |
4+
|-----------------------------------------------------------|
5+
|Created By Tim Roberts || Python's Builtin Sort |
6+
|Worst case performance || O(n log n) |
7+
|Best case performance || O(n) |
8+
|Average case performance || O(n log n) |
9+
|Worst case space complexity || O(n) |
10+
|-----------------------------------------------------------|
11+
"""
12+
13+
from decorators import timethis
14+
15+
16+
@timethis
17+
def tim_sort(array):
18+
return sorted(array)

0 commit comments

Comments
 (0)