Skip to content

Commit

Permalink
sorting algos
Browse files Browse the repository at this point in the history
  • Loading branch information
DavidLeoni committed Dec 3, 2018
1 parent 1bd30ae commit ece47d9
Show file tree
Hide file tree
Showing 14 changed files with 1,045 additions and 9 deletions.
Binary file added exercises/sorting/img/insertion-sort-example.gif
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added exercises/sorting/img/insertion-sort.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added exercises/sorting/img/quicksort-pivot.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added exercises/sorting/img/quicksort-pivot1.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added exercises/sorting/img/quicksort.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 12 additions & 0 deletions exercises/sorting/insertion_sort_solution.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@

def insertion_sort(A):
""" Sorts in-place list A with insertion sort. """
#jupman-raise
for i in range(1, len(A)):
temp = A[i]
j = i
while j > 0 and A[j-1] > temp:
A[j] = A[j-1]
j -= 1
A[j] = temp
#/jupman-raise
36 changes: 36 additions & 0 deletions exercises/sorting/insertion_sort_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
from insertion_sort_solution import *
import unittest


class InsertionSortTest(unittest.TestCase):

def test_01_zero_elements(self):
v = []
insertion_sort(v)
self.assertEqual(v,[])

def test_02_return_none(self):
self.assertEqual(None, insertion_sort([2]))

def test_03_one_element(self):
v = ["a"]
insertion_sort(v)
self.assertEqual(v,["a"])


def test_04_two_elements(self):
v = [2,1]
insertion_sort(v)
self.assertEqual(v,[1,2])

def test_05_three_elements(self):
v = [2,1,3]
insertion_sort(v)
self.assertEqual(v,[1,2,3])

def test_06_piccinno_list(self):
v = [23, 34, 55, 32, 7777, 98, 3, 2, 1]
insertion_sort(v)
vcopy = v[:]
vcopy.sort()
self.assertEqual(v, vcopy)
68 changes: 68 additions & 0 deletions exercises/sorting/merge_sort_solution.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@

import itertools

def merge1(a,b):
""" Takes a and b as two ordered lists (from smallest to greatest) of (possibly negative) integers.
Lists are of size n and m respectively
RETURN a NEW list composed of the items in A and B ordered
from smallest to greatest
- MUST RUN IN O(m+n)
- use .pop() on input lists to reduce their size and put _maximal_ elements in tmp
"""
#jupman-raise

ret = []

while len(a) > 0 or len(b) > 0:

if len(a) > 0 and len(b) > 0:
if a[-1] > b[-1]:
ret.append(a.pop())
else:
ret.append(b.pop())
elif len(a) > 0:
ret.append(a.pop())
else:
ret.append(b.pop())

ret.reverse()
return ret
#/jupman-raise

def merge2(A,B):
""" Takes A and B as two ordered lists (from smallest to greatest) of (possibly negative) integers.
Lists are of size n and m respectively
RETURN a NEW list composed of the items in A and B ordered
from smallest to greatest
- MUST RUN IN O(m+n)
- in this version, do NOT use .pop() on input lists to reduce their size.
Instead, use indeces to track at which point you are, starting at zero and
putting _minimal_ elements in tmp
"""
#jupman-raise
i = 0
j = 0
res = []
while i + j < len(A) + len(B):
if i < len(A) and j < len(B):
if A[i] < B[j]:
res.append(A[i])
i += 1
else:
res.append(B[j])
j += 1
elif i < len(A):
res.extend(itertools.islice(A,i, None))
return res
else:
res.extend(itertools.islice(B,j, None))
return res
return res
#/jupman-raise

90 changes: 90 additions & 0 deletions exercises/sorting/merge_sort_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
from merge_sort_solution import *
import unittest


class Merge1Test(unittest.TestCase):

def test_01_empty__empty(self):
v = []
w = []
self.assertEqual(merge1(v, w),[])

def test_02_7__empty(self):
v = [7]
w = []
self.assertEqual(merge1(v, w),[7])
self.assertEqual(v, []) # should empty inputs
self.assertEqual(w, [])


def test_03_empty__7(self):
v = []
w = [7]
self.assertEqual(merge1(v, w),[7])
self.assertEqual(v, []) # should empty inputs
self.assertEqual(w, [])



def test_04_7_9__6(self):
v = [7,9]
w = [6]
self.assertEqual(merge1(v,w),[6,7,9])

def test_05_6__7_9(self):
v = [6]
w = [7,9]
self.assertEqual(merge1(v,w),[6,7,9])

def test_06_5_5_8__7_9(self):
v = [5,5,8]
w = [7,9]
self.assertEqual(merge1(v,w),[5,5,7,8,9])

def test_07_7_9__5_5_8(self):
v = [7,9]
w = [5,5,8]
self.assertEqual(merge1(v,w),[5,5,7,8,9])

class Merge2Test(unittest.TestCase):

def test_01_empty__empty(self):
v = []
w = []
self.assertEqual(merge2(v, w),[])


def test_02_7__empty(self):
v = [7]
w = []
self.assertEqual(merge2(v, w),[7])
self.assertEqual(v, [7]) # merge2 should *not* empty inputs
self.assertEqual(w, [])


def test_03_empty__7(self):
v = []
w = [7]
self.assertEqual(merge2(v, w),[7])
self.assertEqual(v, []) # merge2 should *not* empty inputs
self.assertEqual(w, [7])

def test_04_7_9__6(self):
v = [7,9]
w = [6]
self.assertEqual(merge2(v,w),[6,7,9])

def test_05_6__7_9(self):
v = [6]
w = [7,9]
self.assertEqual(merge2(v,w),[6,7,9])

def test_06_5_5_8__7_9(self):
v = [5,5,8]
w = [7,9]
self.assertEqual(merge2(v,w),[5,5,7,8,9])

def test_07_7_9__5_5_8(self):
v = [7,9]
w = [5,5,8]
self.assertEqual(merge2(v,w),[5,5,7,8,9])
48 changes: 48 additions & 0 deletions exercises/sorting/quick_sort_solution.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import unittest


def swap(A, x, y):
"""
In the array A, swaps the elements at indeces x and y.
"""
tmp = A[x]
A[x] = A[y]
A[y] = tmp

def pivot(A, first, last):
""" MODIFIES in-place the slice of the array A with indeces between first included
and last included. RETURN the new pivot index.
"""
#jupman-raise
p = A[first]
j = first
for i in range(first + 1, last + 1):
if A[i] < p:
j += 1
swap(A, i, j)
A[first] = A[j]
A[j] = p
return j
#/jupman-raise

def quicksort(A, first, last):
"""
Sorts in-place the slice of the array A with indeces between first included
and last included.
"""
#jupman-raise
if first < last:
j = pivot(A, first, last)
quicksort(A, first, j - 1)
quicksort(A, j + 1, last)
#/jupman-raise

def qs(A):
"""
Sorts in-place the array A by calling quicksort function on the full array.
"""
#jupman-raise
if len(A) > 0:
quicksort(A, 0, len(A) - 1)
#/jupman-raise
96 changes: 96 additions & 0 deletions exercises/sorting/quick_sort_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
from quick_sort_solution import *
import unittest

class SwapTest(unittest.TestCase):

def test_one_element(self):
v = ['a'];
swap(v,0,0)
self.assertEqual(v, ['a'])

def test_two_elements(self):
v = ['a','b'];
swap(v,0,1)
self.assertEqual(v, ['b','a'])

def test_return_none(self):
v = ['a','b', 'c', 'd'];
self.assertEquals(None, swap(v,1,3))

def test_long_list(self):
v = ['a','b', 'c', 'd'];
swap(v,1,3)
self.assertEqual(v, ['a', 'd','c', 'b'])


def test_swap_property(self):
v = ['a','b','c','d'];
w = ['a','b','c','d'];
swap(v,1,3)
swap(w,3,1)
self.assertEqual(v, w)

def test_double_swap(self):
v = ['a','b','c','d'];
swap(v,1,3)
swap(v,1,3)
self.assertEqual(v, ['a','b','c','d'])

class PivotTest(unittest.TestCase):
""" Test cases only for pivot function
"""


def test_pivot_zero(self):
with self.assertRaises(Exception):
pivot([],0,0)

def test_pivot_one(self):
self.assertEqual(0, pivot([3],0,0))

def test_pivot_two_already_ordered(self):
self.assertEqual(0, pivot([6, 7],0,1))

def test_pivot_two_not_ordered(self):
self.assertEqual(1, pivot([7, 6],0,1))

def test_pivot_three_not_ordered(self):
self.assertEqual(1, pivot([7, 6,8],0,1))


class QuicksortTest(unittest.TestCase):
""" Test cases for qs function
"""

def test_zero_elements(self):
v = []
qs(v)
self.assertEqual(v,[])

def test_return_none(self):
self.assertEquals(None, qs([2]))

def test_one_element(self):
v = ["a"]
qs(v)
self.assertEqual(v,["a"])


def test_two_elements(self):
v = [2,1]
qs(v)
self.assertEqual(v,[1,2])

def test_three_elements(self):
v = [2,1,3]
qs(v)
self.assertEqual(v,[1,2,3])

def test_piccinno_list(self):
v = [23, 34, 55, 32, 7777, 98, 3, 2, 1]
qs(v)
vcopy = v[:]
vcopy.sort()
self.assertEqual(v, vcopy)

0 comments on commit ece47d9

Please sign in to comment.