Adding unit tests for sorting functions, and improving readability on some sorting algorithms (#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
This commit is contained in:
Mehdi ALAOUI 2019-05-25 15:41:24 +02:00 committed by John Law
parent 9f982a83c8
commit 02c0daf9e5
14 changed files with 119 additions and 47 deletions

View File

@ -10,8 +10,4 @@ try:
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]))

View File

@ -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]
"""
@ -46,4 +46,4 @@ if __name__ == '__main__':
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))

View File

@ -50,11 +50,11 @@ if __name__ == '__main__':
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)
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=' ')
print("After sort : ")
for i in range(0, n):
print(unsorted[i], end=' ')

View File

@ -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

View File

@ -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

View File

@ -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
@ -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]))

View File

@ -1,4 +1,4 @@
def radixsort(lst):
def radix_sort(lst):
RADIX = 10
placement = 1

74
sorts/tests.py Normal file
View File

@ -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'])

View File

@ -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]]
@ -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__':

View File

@ -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)

View File

@ -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
@ -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]))

View File

@ -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)