Skip to content

Commit

Permalink
Adding unit tests for sorting functions, and improving readability on…
Browse files Browse the repository at this point in the history
… some sorting algorithms (TheAlgorithms#784)

* Adding variable to fade out ambiguity

* More readability on merge sorting algorithm

* Updating merge_sort_fastest description and explaining why

* Adding tests file with imports

* Standardazing filenames and function names

* Adding test cases and test functions

* Adding test loop

* Putting 'user oriented code' inside main condition for having valid imports

* Fixing condition

* Updating tests: adding cases and todo list

* Refactoring first euler problem's first solution
  • Loading branch information
alaouimehdi1995 authored and poyea committed May 25, 2019
1 parent 9f982a8 commit 02c0daf
Show file tree
Hide file tree
Showing 14 changed files with 120 additions and 48 deletions.
6 changes: 1 addition & 5 deletions project_euler/problem_01/sol1.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,4 @@
except NameError:
raw_input = input # Python 3
n = int(raw_input().strip())
sum=0
for a in range(3,n):
if(a%3==0 or a%5==0):
sum+=a
print(sum)
print(sum([e for e in range(3, n) if e % 3 == 0 or e % 5 == 0]))
16 changes: 8 additions & 8 deletions sorts/bogosort.py → sorts/bogo_sort.py
Original file line number Diff line number Diff line change
@@ -1,28 +1,28 @@
"""
This is a pure python implementation of the bogosort algorithm
For doctests run following command:
python -m doctest -v bogosort.py
python -m doctest -v bogo_sort.py
or
python3 -m doctest -v bogosort.py
python3 -m doctest -v bogo_sort.py
For manual testing run:
python bogosort.py
python bogo_sort.py
"""

from __future__ import print_function
import random


def bogosort(collection):
def bogo_sort(collection):
"""Pure implementation of the bogosort algorithm in Python
:param collection: some mutable ordered collection with heterogeneous
comparable items inside
:return: the same collection ordered by ascending
Examples:
>>> bogosort([0, 5, 3, 2, 2])
>>> bogo_sort([0, 5, 3, 2, 2])
[0, 2, 2, 3, 5]
>>> bogosort([])
>>> bogo_sort([])
[]
>>> bogosort([-2, -5, -45])
>>> bogo_sort([-2, -5, -45])
[-45, -5, -2]
"""

Expand All @@ -46,4 +46,4 @@ def isSorted(collection):

user_input = raw_input('Enter numbers separated by a comma:\n').strip()
unsorted = [int(item) for item in user_input.split(',')]
print(bogosort(unsorted))
print(bogo_sort(unsorted))
2 changes: 1 addition & 1 deletion sorts/bucket_sort.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,4 @@ def bucket_sort(my_list, bucket_size=DEFAULT_BUCKET_SIZE):
if __name__ == "__main__":
user_input = input('Enter numbers separated by a comma:').strip()
unsorted = [float(n) for n in user_input.split(',') if len(user_input) > 0]
print(bucket_sort(unsorted))
print(bucket_sort(unsorted))
16 changes: 8 additions & 8 deletions sorts/cyclesort.py → sorts/cycle_sort.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,11 @@ def cycle_sort(array):
except NameError:
raw_input = input # Python 3

user_input = raw_input('Enter numbers separated by a comma:\n')
unsorted = [int(item) for item in user_input.split(',')]
n = len(unsorted)
cycle_sort(unsorted)

print("After sort : ")
for i in range(0, n):
print(unsorted[i], end=' ')
user_input = raw_input('Enter numbers separated by a comma:\n')
unsorted = [int(item) for item in user_input.split(',')]
n = len(unsorted)
cycle_sort(unsorted)

print("After sort : ")
for i in range(0, n):
print(unsorted[i], end=' ')
10 changes: 6 additions & 4 deletions sorts/insertion_sort.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,12 @@ def insertion_sort(collection):
>>> insertion_sort([-2, -5, -45])
[-45, -5, -2]
"""
for index in range(1, len(collection)):
while index > 0 and collection[index - 1] > collection[index]:
collection[index], collection[index - 1] = collection[index - 1], collection[index]
index -= 1

for loop_index in range(1, len(collection)):
insertion_index = loop_index
while insertion_index > 0 and collection[insertion_index - 1] > collection[insertion_index]:
collection[insertion_index], collection[insertion_index - 1] = collection[insertion_index - 1], collection[insertion_index]
insertion_index -= 1

return collection

Expand Down
2 changes: 1 addition & 1 deletion sorts/merge_sort.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,4 @@ def merge(left, right):

user_input = raw_input('Enter numbers separated by a comma:\n').strip()
unsorted = [int(item) for item in user_input.split(',')]
print(*merge_sort(unsorted), sep=',')
print(*merge_sort(unsorted), sep=',')
2 changes: 1 addition & 1 deletion sorts/merge_sort_fastest.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
Python implementation of the fastest merge sort algorithm.
Takes an average of 0.6 microseconds to sort a list of length 1000 items.
Best Case Scenario : O(n)
Worst Case Scenario : O(n)
Worst Case Scenario : O(n^2) because native python functions:min, max and remove are already O(n)
'''
from __future__ import print_function

Expand Down
5 changes: 3 additions & 2 deletions sorts/pancake_sort.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Pancake sort algorithm
# Only can reverse array from 0 to i

def pancakesort(arr):
def pancake_sort(arr):
cur = len(arr)
while cur > 1:
# Find the maximum number in arr
Expand All @@ -13,4 +13,5 @@ def pancakesort(arr):
cur -= 1
return arr

print(pancakesort([0,10,15,3,2,9,14,13]))
if __name__ == '__main__':
print(pancake_sort([0,10,15,3,2,9,14,13]))
2 changes: 1 addition & 1 deletion sorts/radix_sort.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
def radixsort(lst):
def radix_sort(lst):
RADIX = 10
placement = 1

Expand Down
74 changes: 74 additions & 0 deletions sorts/tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
from bogo_sort import bogo_sort
from bubble_sort import bubble_sort
from bucket_sort import bucket_sort
from cocktail_shaker_sort import cocktail_shaker_sort
from comb_sort import comb_sort
from counting_sort import counting_sort
from cycle_sort import cycle_sort
from gnome_sort import gnome_sort
from heap_sort import heap_sort
from insertion_sort import insertion_sort
from merge_sort_fastest import merge_sort as merge_sort_fastest
from merge_sort import merge_sort
from pancake_sort import pancake_sort
from quick_sort_3_partition import quick_sort_3partition
from quick_sort import quick_sort
from radix_sort import radix_sort
from random_pivot_quick_sort import quick_sort_random
from selection_sort import selection_sort
from shell_sort import shell_sort
from tim_sort import tim_sort
from topological_sort import topological_sort
from tree_sort import tree_sort
from wiggle_sort import wiggle_sort


TEST_CASES = [
{'input': [8, 7, 6, 5, 4, 3, -2, -5], 'expected': [-5, -2, 3, 4, 5, 6, 7, 8]},
{'input': [-5, -2, 3, 4, 5, 6, 7, 8], 'expected': [-5, -2, 3, 4, 5, 6, 7, 8]},
{'input': [5, 6, 1, 4, 0, 1, -2, -5, 3, 7], 'expected': [-5, -2, 0, 1, 1, 3, 4, 5, 6, 7]},
{'input': [2, -2], 'expected': [-2, 2]},
{'input': [1], 'expected': [1]},
{'input': [], 'expected': []},
]

'''
TODO:
- Fix some broken tests in particular cases (as [] for example),
- Unify the input format: should always be function(input_collection) (no additional args)
- Unify the output format: should always be a collection instead of updating input elements
and returning None
- Rewrite some algorithms in function format (in case there is no function definition)
'''

TEST_FUNCTIONS = [
bogo_sort,
bubble_sort,
bucket_sort,
cocktail_shaker_sort,
comb_sort,
counting_sort,
cycle_sort,
gnome_sort,
heap_sort,
insertion_sort,
merge_sort_fastest,
merge_sort,
pancake_sort,
quick_sort_3partition,
quick_sort,
radix_sort,
quick_sort_random,
selection_sort,
shell_sort,
tim_sort,
topological_sort,
tree_sort,
wiggle_sort,
]


for function in TEST_FUNCTIONS:
for case in TEST_CASES:
result = function(case['input'])
assert result == case['expected'], 'Executed function: {}, {} != {}'.format(function.__name__, result, case['expected'])
4 changes: 2 additions & 2 deletions sorts/timsort.py → sorts/tim_sort.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ def merge(left, right):
return [right[0]] + merge(left, right[1:])


def timsort(lst):
def tim_sort(lst):
runs, sorted_runs = [], []
length = len(lst)
new_run = [lst[0]]
Expand Down Expand Up @@ -75,7 +75,7 @@ def timsort(lst):
def main():

lst = [5,9,10,3,-4,5,178,92,46,-18,0,7]
sorted_lst = timsort(lst)
sorted_lst = tim_sort(lst)
print(sorted_lst)

if __name__ == '__main__':
Expand Down
6 changes: 3 additions & 3 deletions sorts/topological_sort.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,6 @@ def topological_sort(start, visited, sort):
# return sort
return sort


sort = topological_sort('a', [], [])
print(sort)
if __name__ == '__main__':
sort = topological_sort('a', [], [])
print(sort)
5 changes: 3 additions & 2 deletions sorts/tree_sort.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ def inorder(root, res):
res.append(root.val)
inorder(root.right,res)

def treesort(arr):
def tree_sort(arr):
# Build BST
if len(arr) == 0:
return arr
Expand All @@ -42,4 +42,5 @@ def treesort(arr):
inorder(root,res)
return res

print(treesort([10,1,3,2,9,14,13]))
if __name__ == '__main__':
print(tree_sort([10,1,3,2,9,14,13]))
18 changes: 8 additions & 10 deletions sorts/wiggle_sort.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,11 @@ def wiggle_sort(nums):
if (i % 2 == 1) == (nums[i-1] > nums[i]):
nums[i-1], nums[i] = nums[i], nums[i-1]


print("Enter the array elements:\n")
array=list(map(int,input().split()))
print("The unsorted array is:\n")
print(array)
wiggle_sort(array)
print("Array after Wiggle sort:\n")
print(array)


if __name__ == '__main__':
print("Enter the array elements:\n")
array=list(map(int,input().split()))
print("The unsorted array is:\n")
print(array)
wiggle_sort(array)
print("Array after Wiggle sort:\n")
print(array)

0 comments on commit 02c0daf

Please sign in to comment.