Merge pull request #8 from SergeyTsaplin/full-refactoring

Sortings and searching algorithms refactoring
This commit is contained in:
Chetan Kaushik 2016-08-01 13:52:23 +05:30 committed by GitHub
commit d847747109
13 changed files with 441 additions and 251 deletions

90
.gitignore vendored Normal file
View File

@ -0,0 +1,90 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
env/
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
*.egg-info/
.installed.cfg
*.egg
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*,cover
.hypothesis/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# IPython Notebook
.ipynb_checkpoints
# pyenv
.python-version
# celery beat schedule file
celerybeat-schedule
# dotenv
.env
# virtualenv
venv/
ENV/
# Spyder project settings
.spyderproject
# Rope project settings
.ropeproject
.idea

View File

@ -1,39 +0,0 @@
import sys
def simple_bubble_sort(int_list):
count = len(int_list)
swapped = True
while (swapped):
swapped = False
for j in range(count - 1):
if (int_list[j] > int_list[j + 1]):
int_list[j], int_list[j + 1] = int_list[j + 1], int_list[j]
swapped = True
return int_list
def main():
# Python 2's `raw_input` has been renamed to `input` in Python 3
if sys.version_info.major < 3:
input_function = raw_input
else:
input_function = input
try:
print("Enter numbers separated by spaces:")
s = input_function()
inputs = list(map(int, s.split(' ')))
if len(inputs) < 2:
print('No Enough values to sort!')
raise Exception
except Exception as e:
print(e)
else:
sorted_input = simple_bubble_sort(inputs)
print('\nSorted list (min to max): {}'.format(sorted_input))
if __name__ == '__main__':
print('==== Bubble Sort ====\n')
main()

View File

@ -1,40 +0,0 @@
import sys
def simple_insertion_sort(int_list):
count = len(int_list)
for i in range(1, count):
temp = int_list[i]
j = i - 1
while(j >= 0 and temp < int_list[j]):
int_list[j + 1] = int_list[j]
j -= 1
int_list[j + 1] = temp
return int_list
def main():
# Python 2's `raw_input` has been renamed to `input` in Python 3
if sys.version_info.major < 3:
input_function = raw_input
else:
input_function = input
try:
print("Enter numbers separated by spaces:")
s = input_function()
inputs = list(map(int, s.split(' ')))
if len(inputs) < 2:
print('No Enough values to sort!')
raise Exception
except Exception as e:
print(e)
else:
sorted_input = simple_insertion_sort(inputs)
print('\nSorted list (min to max): {}'.format(sorted_input))
if __name__ == '__main__':
print('==== Insertion Sort ====\n')
main()

View File

@ -1,32 +0,0 @@
import sys
def sequential_search(alist, target):
for index, item in enumerate(alist):
if item == target:
print("Found target {} at index {}".format(target, index))
break
else:
print("Not found")
def main():
# Python 2's `raw_input` has been renamed to `input` in Python 3
if sys.version_info.major < 3:
input_function = raw_input
else:
input_function = input
try:
print("Enter numbers separated by spaces")
s = input_function()
inputs = list(map(int, s.split(' ')))
target = int(input_function('\nEnter a number to be found in list: '))
except Exception as e:
print(e)
else:
sequential_search(inputs, target)
if __name__ == '__main__':
print('==== Linear Search ====\n')
main()

View File

@ -1,59 +0,0 @@
import sys
def merge_sort(alist):
print("Splitting ", alist)
if len(alist) > 1:
mid = len(alist) // 2
left_half = alist[:mid]
right_half = alist[mid:]
merge_sort(left_half)
merge_sort(right_half)
i = j = k = 0
while i < len(left_half) and j < len(right_half):
if left_half[i] < right_half[j]:
alist[k] = left_half[i]
i += 1
else:
alist[k] = right_half[j]
j += 1
k += 1
while i < len(left_half):
alist[k] = left_half[i]
i += 1
k += 1
while j < len(right_half):
alist[k] = right_half[j]
j += 1
k += 1
print("Merging ", alist)
return alist
def main():
# Python 2's `raw_input` has been renamed to `input` in Python 3
if sys.version_info.major < 3:
input_function = raw_input
else:
input_function = input
try:
print("Enter numbers separated by spaces:")
s = input_function()
inputs = list(map(int, s.split(' ')))
if len(inputs) < 2:
print('No Enough values to sort!')
raise Exception
except Exception as e:
print(e)
else:
sorted_input = merge_sort(inputs)
print('\nSorted list (min to max): {}'.format(sorted_input))
if __name__ == '__main__':
print('==== Merge Sort ====\n')
main()

View File

@ -1,41 +0,0 @@
import sys
def quick_sort(A, p, r):
if p < r:
q = partition(A, p, r)
quick_sort(A, p, q - 1)
quick_sort(A, q + 1, r)
return A
def partition(A, p, r):
i = p - 1
for j in range(p, r):
if A[j] <= A[r]:
i += 1
A[i], A[j] = A[j], A[i]
A[i + 1], A[r] = A[r], A[i + 1]
return i + 1
def main():
# Python 2's `raw_input` has been renamed to `input` in Python 3
if sys.version_info.major < 3:
input_function = raw_input
else:
input_function = input
try:
print("Enter numbers separated by spaces")
s = input_function()
inputs = list(map(int, s.split(' ')))
except Exception as e:
print(e)
else:
sorted_input = quick_sort(inputs, 0, len(inputs) - 1)
print('\nSorted list (min to max): {}'.format(sorted_input))
if __name__ == '__main__':
print('==== Quick Sort ====\n')
main()

View File

@ -2,9 +2,9 @@
This is pure python implementation of binary search algorithm This is pure python implementation of binary search algorithm
For doctests run following command: For doctests run following command:
python -m doctest -v selection_sort.py python -m doctest -v binary_search.py
or or
python3 -m doctest -v selection_sort.py python3 -m doctest -v binary_search.py
For manual testing run: For manual testing run:
python binary_search.py python binary_search.py
@ -13,30 +13,12 @@ from __future__ import print_function
import bisect import bisect
def assert_sorted(collection):
"""Check if collection is sorted. If not raises :py:class:`ValueError`
:param collection: collection
:return: True if collection is sorted
:raise: :py:class:`ValueError` if collection is not sorted
Examples:
>>> assert_sorted([0, 1, 2, 4])
True
>>> assert_sorted([10, -1, 5])
Traceback (most recent call last):
...
ValueError: Collection must be sorted
"""
if collection != sorted(collection):
raise ValueError('Collection must be sorted')
return True
def binary_search(sorted_collection, item): def binary_search(sorted_collection, item):
"""Pure implementation of binary search algorithm in Python """Pure implementation of binary search algorithm in Python
Be careful collection must be sorted, otherwise result will be
unpredictable
:param sorted_collection: some sorted collection with comparable items :param sorted_collection: some sorted collection with comparable items
:param item: item value to search :param item: item value to search
:return: index of found item or None if item is not found :return: index of found item or None if item is not found
@ -53,12 +35,7 @@ def binary_search(sorted_collection, item):
>>> binary_search([0, 5, 7, 10, 15], 6) >>> binary_search([0, 5, 7, 10, 15], 6)
>>> binary_search([5, 2, 1, 5], 2)
Traceback (most recent call last):
...
ValueError: Collection must be sorted
""" """
assert_sorted(sorted_collection)
left = 0 left = 0
right = len(sorted_collection) - 1 right = len(sorted_collection) - 1
@ -78,6 +55,9 @@ def binary_search(sorted_collection, item):
def binary_search_std_lib(sorted_collection, item): def binary_search_std_lib(sorted_collection, item):
"""Pure implementation of binary search algorithm in Python using stdlib """Pure implementation of binary search algorithm in Python using stdlib
Be careful collection must be sorted, otherwise result will be
unpredictable
:param sorted_collection: some sorted collection with comparable items :param sorted_collection: some sorted collection with comparable items
:param item: item value to search :param item: item value to search
:return: index of found item or None if item is not found :return: index of found item or None if item is not found
@ -94,18 +74,34 @@ def binary_search_std_lib(sorted_collection, item):
>>> binary_search_std_lib([0, 5, 7, 10, 15], 6) >>> binary_search_std_lib([0, 5, 7, 10, 15], 6)
>>> binary_search_std_lib([5, 2, 1, 5], 2)
Traceback (most recent call last):
...
ValueError: Collection must be sorted
""" """
assert_sorted(sorted_collection)
index = bisect.bisect_left(sorted_collection, item) index = bisect.bisect_left(sorted_collection, item)
if index != len(sorted_collection) and sorted_collection[index] == item: if index != len(sorted_collection) and sorted_collection[index] == item:
return index return index
return None return None
def __assert_sorted(collection):
"""Check if collection is sorted, if not - raises :py:class:`ValueError`
:param collection: collection
:return: True if collection is sorted
:raise: :py:class:`ValueError` if collection is not sorted
Examples:
>>> __assert_sorted([0, 1, 2, 4])
True
>>> __assert_sorted([10, -1, 5])
Traceback (most recent call last):
...
ValueError: Collection must be sorted
"""
if collection != sorted(collection):
raise ValueError('Collection must be sorted')
return True
if __name__ == '__main__': if __name__ == '__main__':
import sys import sys
# For python 2.x and 3.x compatibility: 3.x has not raw_input builtin # For python 2.x and 3.x compatibility: 3.x has not raw_input builtin
@ -117,6 +113,10 @@ if __name__ == '__main__':
user_input = input_function('Enter numbers separated by coma:\n') user_input = input_function('Enter numbers separated by coma:\n')
collection = [int(item) for item in user_input.split(',')] collection = [int(item) for item in user_input.split(',')]
try:
__assert_sorted(collection)
except ValueError:
sys.exit('Sequence must be sorted to apply binary search')
target_input = input_function( target_input = input_function(
'Enter a single number to be found in the list:\n' 'Enter a single number to be found in the list:\n'

52
bubble_sort.py Normal file
View File

@ -0,0 +1,52 @@
"""
This is pure python implementation of bubble sort algorithm
For doctests run following command:
python -m doctest -v bubble_sort.py
or
python3 -m doctest -v bubble_sort.py
For manual testing run:
python bubble_sort.py
"""
from __future__ import print_function
def bubble_sort(collection):
"""Pure implementation of bubble sort algorithm in Python
:param collection: some mutable ordered collection with heterogeneous
comparable items inside
:return: the same collection ordered by ascending
Examples:
>>> bubble_sort([0, 5, 3, 2, 2])
[0, 2, 2, 3, 5]
>>> bubble_sort([])
[]
>>> bubble_sort([-2, -5, -45])
[-45, -5, -2]
"""
length = len(collection)
for i in range(length):
for j in range(length-1):
if collection[j] > collection[j+1]:
collection[j], collection[j+1] = collection[j+1], collection[j]
return collection
if __name__ == '__main__':
import sys
# For python 2.x and 3.x compatibility: 3.x has not raw_input builtin
# otherwise 2.x's input builtin function is too "smart"
if sys.version_info.major < 3:
input_function = raw_input
else:
input_function = input
user_input = input_function('Enter numbers separated by coma:\n')
unsorted = [int(item) for item in user_input.split(',')]
print(bubble_sort(unsorted))

56
insertion_sort.py Normal file
View File

@ -0,0 +1,56 @@
"""
This is pure python implementation of insertion sort algorithm
For doctests run following command:
python -m doctest -v insertion_sort.py
or
python3 -m doctest -v insertion_sort.py
For manual testing run:
python insertion_sort.py
"""
from __future__ import print_function
def insertion_sort(collection):
"""Pure implementation of insertion sort algorithm in Python
:param collection: some mutable ordered collection with heterogeneous
comparable items inside
:return: the same collection ordered by ascending
Examples:
>>> insertion_sort([0, 5, 3, 2, 2])
[0, 2, 2, 3, 5]
>>> insertion_sort([])
[]
>>> insertion_sort([-2, -5, -45])
[-45, -5, -2]
"""
length = len(collection)
for i in range(length):
current_item = collection[i]
j = i - 1
while j >= 0 and current_item < collection[j]:
collection[j+1] = collection[j]
j -= 1
collection[j+1] = current_item
return collection
if __name__ == '__main__':
import sys
# For python 2.x and 3.x compatibility: 3.x has not raw_input builtin
# otherwise 2.x's input builtin function is too "smart"
if sys.version_info.major < 3:
input_function = raw_input
else:
input_function = input
user_input = input_function('Enter numbers separated by coma:\n')
unsorted = [int(item) for item in user_input.split(',')]
print(insertion_sort(unsorted))

62
linear_search.py Normal file
View File

@ -0,0 +1,62 @@
"""
This is pure python implementation of linear search algorithm
For doctests run following command:
python -m doctest -v linear_search.py
or
python3 -m doctest -v linear_search.py
For manual testing run:
python linear_search.py
"""
from __future__ import print_function
def linear_search(sequence, target):
"""Pure implementation of binary search algorithm in Python
:param sequence: some sorted collection with comparable items
:param target: item value to search
:return: index of found item or None if item is not found
Examples:
>>> linear_search([0, 5, 7, 10, 15], 0)
0
>>> linear_search([0, 5, 7, 10, 15], 15)
4
>>> linear_search([0, 5, 7, 10, 15], 5)
1
>>> linear_search([0, 5, 7, 10, 15], 6)
"""
for index, item in enumerate(sequence):
if item == target:
return index
return None
if __name__ == '__main__':
import sys
# For python 2.x and 3.x compatibility: 3.x has not raw_input builtin
# otherwise 2.x's input builtin function is too "smart"
if sys.version_info.major < 3:
input_function = raw_input
else:
input_function = input
user_input = input_function('Enter numbers separated by coma:\n')
sequence = [int(item) for item in user_input.split(',')]
target_input = input_function(
'Enter a single number to be found in the list:\n'
)
target = int(target_input)
result = linear_search(sequence, target)
if result is not None:
print('{} found at positions: {}'.format(target, result))
else:
print('Not found')

76
merge_sort.py Normal file
View File

@ -0,0 +1,76 @@
"""
This is pure python implementation of merge sort algorithm
For doctests run following command:
python -m doctest -v merge_sort.py
or
python3 -m doctest -v merge_sort.py
For manual testing run:
python merge_sort.py
"""
from __future__ import print_function
def merge_sort(collection):
"""Pure implementation of merge sort algorithm in Python
:param collection: some mutable ordered collection with heterogeneous
comparable items inside
:return: the same collection ordered by ascending
Examples:
>>> merge_sort([0, 5, 3, 2, 2])
[0, 2, 2, 3, 5]
>>> merge_sort([])
[]
>>> merge_sort([-2, -5, -45])
[-45, -5, -2]
"""
length = len(collection)
if length > 1:
midpoint = length // 2
left_half = merge_sort(collection[:midpoint])
right_half = merge_sort(collection[midpoint:])
i = 0
j = 0
k = 0
left_length = len(left_half)
right_length = len(right_half)
while i < left_length and j < right_length:
if left_half[i] < right_half[j]:
collection[k] = left_half[i]
i += 1
else:
collection[k] = right_half[j]
j += 1
k += 1
while i < left_length:
collection[k] = left_half[i]
i += 1
k += 1
while j < right_length:
collection[k] = right_half[j]
j += 1
k += 1
return collection
if __name__ == '__main__':
import sys
# For python 2.x and 3.x compatibility: 3.x has not raw_input builtin
# otherwise 2.x's input builtin function is too "smart"
if sys.version_info.major < 3:
input_function = raw_input
else:
input_function = input
user_input = input_function('Enter numbers separated by coma:\n')
unsorted = [int(item) for item in user_input.split(',')]
print(merge_sort(unsorted))

61
quick_sort.py Normal file
View File

@ -0,0 +1,61 @@
"""
This is pure python implementation of quick sort algorithm
For doctests run following command:
python -m doctest -v quick_sort.py
or
python3 -m doctest -v quick_sort.py
For manual testing run:
python quick_sort.py
"""
from __future__ import print_function
def quick_sort(collection):
"""Pure implementation of quick sort algorithm in Python
:param collection: some mutable ordered collection with heterogeneous
comparable items inside
:return: the same collection ordered by ascending
Examples:
>>> quick_sort([0, 5, 3, 2, 2])
[0, 2, 2, 3, 5]
>>> quick_sort([])
[]
>>> quick_sort([-2, -5, -45])
[-45, -5, -2]
"""
less = []
equal = []
greater = []
if len(collection) > 1:
pivot = collection[0]
for x in collection:
if x < pivot:
less.append(x)
if x == pivot:
equal.append(x)
if x > pivot:
greater.append(x)
return quick_sort(less) + equal + quick_sort(greater)
else:
return collection
if __name__ == '__main__':
import sys
# For python 2.x and 3.x compatibility: 3.x has not raw_input builtin
# otherwise 2.x's input builtin function is too "smart"
if sys.version_info.major < 3:
input_function = raw_input
else:
input_function = input
user_input = input_function('Enter numbers separated by coma:\n')
unsorted = [int(item) for item in user_input.split(',')]
print(quick_sort(unsorted))

View File

@ -5,10 +5,14 @@ For doctests run following command:
python -m doctest -v selection_sort.py python -m doctest -v selection_sort.py
or or
python3 -m doctest -v selection_sort.py python3 -m doctest -v selection_sort.py
For manual testing run:
python selection_sort.py
""" """
from __future__ import print_function from __future__ import print_function
def selection_sort(sortable):
def selection_sort(collection):
"""Pure implementation of selection sort algorithm in Python """Pure implementation of selection sort algorithm in Python
Examples: Examples:
@ -21,20 +25,20 @@ def selection_sort(sortable):
>>> selection_sort([-2, -5, -45]) >>> selection_sort([-2, -5, -45])
[-45, -5, -2] [-45, -5, -2]
:param sortable: some mutable ordered collection with heterogeneous :param collection: some mutable ordered collection with heterogeneous
comparable items inside comparable items inside
:return: the same collection ordered by ascending :return: the same collection ordered by ascending
""" """
length = len(sortable) length = len(collection)
for i in range(length): for i in range(length):
least = i least = i
for k in range(i + 1, length): for k in range(i + 1, length):
if sortable[k] < sortable[least]: if collection[k] < collection[least]:
least = k least = k
sortable[least], sortable[i] = ( collection[least], collection[i] = (
sortable[i], sortable[least] collection[i], collection[least]
) )
return sortable return collection
if __name__ == '__main__': if __name__ == '__main__':