organized

This commit is contained in:
Mari Wahl 2014-08-20 17:34:32 -04:00
parent 77731415d1
commit 5ed530430c
60 changed files with 439 additions and 563 deletions

View File

@ -1,24 +1,24 @@
#!/usr/bin/python3 #!/usr/bin/python
# mari von steinkirch @2013
# steinkirch at gmail __author__ = "Mari Wahl"
__email__ = "marina.w4hl@gmail.com"
def binary_search(seq, key): def binary_search(seq, key):
''' binary search iterative algorithm ''' ''' binary search iterative algorithm '''
''' observe that the index is returned ''' ''' observe that the index is returned '''
hi = len(seq) hi = len(seq)
lo = 0 lo = 0
while lo < hi: while lo < hi:
mid = (hi+lo) // 2 mid = (hi+lo) // 2
if seq[mid] == key: if seq[mid] == key:
return mid return mid
elif key < seq[mid]: elif key < seq[mid]:
hi = mid hi = mid
else: else:
lo = mid + 1 lo = mid + 1
return None
def binary_search_rec(seq, key, lo=0, hi=None): def binary_search_rec(seq, key, lo=0, hi=None):
''' binary search recursive algorithm ''' ''' binary search recursive algorithm '''

View File

@ -1,9 +1,11 @@
#!/usr/bin/python3 #!/usr/bin/python
# mari von steinkirch @2013
# steinkirch at gmail __author__ = "Mari Wahl"
__email__ = "marina.w4hl@gmail.com"
''' Searches an element in a matrix where in every row, the values are increasing from left to right, but the last number in a row is smaller than the first number in the next row. ''' Searches an element in a matrix where in every row, the values are increasing from left to right, but the last number in a row is smaller than the first number in the next row.
(1) The naive brute force solution (sequential search) scan all numbers and cost O(nm). However, since the numbers are already sorted, the matrix can be viewed as a 1D sorted array. The binary search algorithm is suitable. The efficiency is O(logmn). (1) The naive brute force solution (sequential search) scan all numbers and cost O(nm). However, since the numbers are already sorted, the matrix can be viewed as a 1D sorted array. The binary search algorithm is suitable. The efficiency is O(logmn).
>>> m = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] >>> m = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
@ -12,20 +14,20 @@
>>> binary_search_matrix_rec(m, 12) >>> binary_search_matrix_rec(m, 12)
>>> binary_search_matrix_iter(m, 6) >>> binary_search_matrix_iter(m, 6)
(1, 2) (1, 2)
>>> binary_search_matrix_iter(m, 12) >>> binary_search_matrix_iter(m, 12)
>>> binary_search_matrix_iter(m, 1) >>> binary_search_matrix_iter(m, 1)
(0, 0) (0, 0)
(2) Another solution is "discarding" arrays in the way. The efficiency is O(logm). (2) Another solution is "discarding" arrays in the way. The efficiency is O(logm).
>>> m = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] >>> m = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> searching_matrix(m, 6) >>> searching_matrix(m, 6)
(1, 2) (1, 2)
>>> searching_matrix(m, 12) >>> searching_matrix(m, 12)
'''
def binary_search_matrix_rec(m, key, lo=0, hi=None): '''
def binary_search_matrix_rec(m, key, lo=0, hi=None):
if not m: return None if not m: return None
rows = len(m) rows = len(m)
cols = len(m[0]) cols = len(m[0])
@ -47,7 +49,7 @@ def binary_search_matrix_iter(m, key):
rows = len(m) rows = len(m)
cols = len(m[0]) cols = len(m[0])
lo, hi = 0, rows*cols lo, hi = 0, rows*cols
while lo < hi: while lo < hi:
mid = (hi + lo)//2 mid = (hi + lo)//2
row = mid//rows row = mid//rows
col = mid%rows col = mid%rows
@ -62,14 +64,14 @@ def searching_matrix(m, key):
if not m: return None if not m: return None
rows = len(m) rows = len(m)
cols = len(m[0]) cols = len(m[0])
i, j = 0, cols -1 i, j = 0, cols -1
while i < rows and j > 0: while i < rows and j > 0:
item = m[i][j] item = m[i][j]
if key == item: return (i, j) if key == item: return (i, j)
elif key < item: j -= 1 elif key < item: j -= 1
else: i += 1 else: i += 1
return None return None
if __name__ == '__main__': if __name__ == '__main__':
import doctest import doctest

View File

@ -1,33 +1,19 @@
#!/usr/bin/python3 #!/usr/bin/python
# mari von steinkirch @2013
# steinkirch at gmail __author__ = "Mari Wahl"
__email__ = "marina.w4hl@gmail.com"
''' Given a sorted array that was rotated, find an item with binary search: ''' Given a sorted array that was rotated, find an item with binary search:
>>> l1 = [3, 4, 5, 6, 7, 1, 2]
>>> find_element_rot_array(l1, 7)
4
>>> find_element_rot_array(l1, 3)
0
>>> find_element_rot_array(l1, 4)
1
>>> find_element_rot_array(l1, 5)
2
>>> find_element_rot_array(l1, 6)
3
>>> find_element_rot_array(l1, 1)
5
>>> find_element_rot_array(l1, 2)
6
>>> find_element_rot_array(l1, 8)
''' '''
def find_element_rot_array(seq, key, lo=0, hi=None): def find_element_rot_array(seq, key, lo=0, hi=None):
hi = hi or len(seq) hi = hi or len(seq)
if hi <= lo: return None # base case: <= for odd and even numbers! if hi <= lo: return None # base case: <= for odd and even numbers!
mid = (hi + lo) // 2 mid = (hi + lo) // 2
if key == seq[mid]: return mid if key == seq[mid]: return mid
# if left is ordered --> we work here # if left is ordered --> we work here
if seq[lo] <= seq[mid]: if seq[lo] <= seq[mid]:
# now, is the key there? # now, is the key there?
@ -36,7 +22,7 @@ def find_element_rot_array(seq, key, lo=0, hi=None):
else: else:
# all the other cases # all the other cases
return find_element_rot_array(seq, key, mid+1, hi) return find_element_rot_array(seq, key, mid+1, hi)
# right is ordered --> we work here # right is ordered --> we work here
else: else:
# now, is the key there? # now, is the key there?
@ -46,11 +32,13 @@ def find_element_rot_array(seq, key, lo=0, hi=None):
# all the other cases # all the other cases
return find_element_rot_array(seq, key, lo, mid) return find_element_rot_array(seq, key, lo, mid)
def test_find_element_rot_array():
l1 = [3, 4, 5, 6, 7, 1, 2]
assert(find_element_rot_array(l1, 7) == 4 )
print("Tests passed!")
if __name__ == '__main__': if __name__ == '__main__':
import doctest test_find_element_rot_array()
doctest.testmod()

View File

@ -1,6 +1,8 @@
#!/usr/bin/python3 #!/usr/bin/python
# mari von steinkirch @2013
# steinkirch at gmail __author__ = "Mari Wahl"
__email__ = "marina.w4hl@gmail.com"
def find_max_unimodal_array(A): def find_max_unimodal_array(A):
@ -19,7 +21,7 @@ def find_max_unimodal_array(A):
def test_find_max_unimodal_array(): def test_find_max_unimodal_array():
seq = [1, 2, 5, 6, 7, 10, 12, 9, 8, 7, 6] seq = [1, 2, 5, 6, 7, 10, 12, 9, 8, 7, 6]
assert(find_max_unimodal_array(seq) == 12) assert(find_max_unimodal_array(seq) == 12)
print('Tests passed!') print('Tests passed!')
@ -28,5 +30,5 @@ if __name__ == '__main__':
test_find_max_unimodal_array() test_find_max_unimodal_array()

View File

@ -1,6 +1,9 @@
#!/usr/bin/python3 #!/usr/bin/python
# mari von steinkirch @2013
# steinkirch at gmail __author__ = "Mari Wahl"
__email__ = "marina.w4hl@gmail.com"

View File

@ -1,21 +1,13 @@
#!/usr/bin/python3 #!/usr/bin/python
# mari von steinkirch @2013
# steinkirch at gmail __author__ = "Mari Wahl"
__email__ = "marina.w4hl@gmail.com"
''' Given a sorted an array with empty strings, we use binary search to find some string (since ''' Given a sorted an array with empty strings, we use binary search to find some string (since
the list is sorted): the list is sorted):
--> we deal with the empty strings with strip and then run to left and right, or move --> we deal with the empty strings with strip and then run to left and right, or move
mid to the closed non-empty str (remember that the index must be conserved): mid to the closed non-empty str (remember that the index must be conserved):
>>> l1 = ['acre', 'ball', '', 'coach', '', 'cut', '']
>>> find_str_array_with_empty_str(l1, l1[0])
0
>>> find_str_array_with_empty_str(l1, l1[1])
1
>>> find_str_array_with_empty_str(l1, l1[3])
3
>>> find_str_array_with_empty_str(l1, l1[5])
5
>>> find_str_array_with_empty_str(l1, 'bla')
''' '''
@ -25,28 +17,33 @@ def find_str_array_with_empty_str(seq, s1):
lo = 0 lo = 0
while hi > lo: while hi > lo:
mid = (hi+lo)//2 mid = (hi+lo)//2
if seq[mid] == '': if seq[mid] == '':
while True: while True:
left = mid-1 left = mid-1
right = mid+1 right = mid+1
if left < lo or right > hi: return None if left < lo or right > hi: return None
elif right < hi and seq[right]: elif right < hi and seq[right]:
mid = right mid = right
break break
elif left > lo and seq[left]: elif left > lo and seq[left]:
mid = left mid = left
break break
right += 1 right += 1
left -= 1 left -= 1
if s1 == seq[mid] == s1: return mid if s1 == seq[mid] == s1: return mid
elif s1 < seq[mid]: hi = mid elif s1 < seq[mid]: hi = mid
else: lo = mid + 1 else: lo = mid + 1
def test_find_str_array_with_empty_str():
seq = ['acre', 'ball', '', 'coach', '', 'cut', '']
key = seq[1]
assert(find_str_array_with_empty_str(seq, key) == 1)
print('Tests passed!')
if __name__ == '__main__': if __name__ == '__main__':
import doctest test_find_str_array_with_empty_str()
doctest.testmod()

View File

@ -1,6 +1,7 @@
#!/usr/bin/python3 #!/usr/bin/python
# mari von steinkirch @2013
# steinkirch at gmail __author__ = "Mari Wahl"
__email__ = "marina.w4hl@gmail.com"
def binary_serch_counting(lst1, k, lo=0, hi=None): def binary_serch_counting(lst1, k, lo=0, hi=None):
@ -15,26 +16,26 @@ def binary_serch_counting(lst1, k, lo=0, hi=None):
else: else:
return mid return mid
return -1 return -1
def find_time_occurrence_list(seq, k): def find_time_occurrence_list(seq, k):
""" find how many times a k element appears in a sorted list. One way of doing this is using """ find how many times a k element appears in a sorted list. One way of doing this is using
collections.OrderedDict to no mess with the sorting, and add entries for every count. This collections.OrderedDict to no mess with the sorting, and add entries for every count. This
should be O(n). It has a O(1) space complexity since the size of the dict is fixed. should be O(n). It has a O(1) space complexity since the size of the dict is fixed.
Another way, since the array is sorted, it to use binary search, since this is only O(logn). Another way, since the array is sorted, it to use binary search, since this is only O(logn).
""" """
index_some_k = binary_serch_counting(seq, k) index_some_k = binary_serch_counting(seq, k)
count = 1 count = 1
sizet = len(seq) sizet = len(seq)
for i in range(index_some_k+1, sizet): # go up for i in range(index_some_k+1, sizet): # go up
if seq[i] == k: count +=1 if seq[i] == k: count +=1
else: break else: break
for i in range(index_some_k-1, -1, -1): # go down for i in range(index_some_k-1, -1, -1): # go down
if seq[i] == k: count +=1 if seq[i] == k: count +=1
else: break else: break
return count return count

View File

@ -1,6 +1,9 @@
#!/usr/bin/python3 #!/usr/bin/python
# mari von steinkirch @2013
# steinkirch at gmail __author__ = "Mari Wahl"
__email__ = "marina.w4hl@gmail.com"
''' using sets ''' ''' using sets '''
@ -9,9 +12,9 @@ def intersection_two_arrays_sets(seq1, seq2):
set1 = set(seq1) set1 = set(seq1)
set2 = set(seq2) set2 = set(seq2)
return set1.intersection(set2) #same as list(set1 & set2 return set1.intersection(set2) #same as list(set1 & set2
''' using merge sort ''' ''' using merge sort '''
def intersection_two_arrays_ms(seq1, seq2): def intersection_two_arrays_ms(seq1, seq2):
@ -23,19 +26,19 @@ def intersection_two_arrays_ms(seq1, seq2):
seq2.pop() seq2.pop()
elif seq1[-1] > seq2[-1]: elif seq1[-1] > seq2[-1]:
seq1.pop() seq1.pop()
else: else:
seq2.pop() seq2.pop()
res.reverse() res.reverse()
return res return res
''' using binary search ''' ''' using binary search '''
def binary_search(seq, key, lo=0, hi=None): def binary_search(seq, key, lo=0, hi=None):
''' binary search iterative algorithm ''' ''' binary search iterative algorithm '''
hi = hi or len(seq) hi = hi or len(seq)
while lo < hi: while lo < hi:
mid = (hi+lo) // 2 mid = (hi+lo) // 2
if seq[mid] == key: if seq[mid] == key:
@ -43,31 +46,31 @@ def binary_search(seq, key, lo=0, hi=None):
elif key > seq[mid]: elif key > seq[mid]:
lo = mid + 1 lo = mid + 1
else: else:
hi = mid hi = mid
return None return None
def intersection_two_arrays_bs(seq1, seq2): def intersection_two_arrays_bs(seq1, seq2):
''' if A small and B is too large, we can do a binary search on each entry in B ''' ''' if A small and B is too large, we can do a binary search on each entry in B '''
''' only works if sorted and the small sequence has not larger nmbers!!!''' ''' only works if sorted and the small sequence has not larger nmbers!!!'''
if len(seq1) > len(seq2): seq, key = seq1, seq2 if len(seq1) > len(seq2): seq, key = seq1, seq2
else: seq, key = seq2, seq1 else: seq, key = seq2, seq1
intersec = [] intersec = []
for item in key: for item in key:
if binary_search(seq, item): if binary_search(seq, item):
intersec.append(item) intersec.append(item)
return intersec return intersec
def test_intersection_two_arrays(module_name='this module'): def test_intersection_two_arrays(module_name='this module'):
seq1 = [1,2,3,5,7,8] seq1 = [1,2,3,5,7,8]
seq2 = [3,5,6] seq2 = [3,5,6]
assert(set(intersection_two_arrays_sets(seq1,seq2)) == set([3,5])) assert(set(intersection_two_arrays_sets(seq1,seq2)) == set([3,5]))
assert(intersection_two_arrays_bs(seq1,seq2) == [3,5]) assert(intersection_two_arrays_bs(seq1,seq2) == [3,5])
assert(intersection_two_arrays_ms(seq1,seq2) == [3,5]) assert(intersection_two_arrays_ms(seq1,seq2) == [3,5])
s = 'Tests in {name} have {con}!' s = 'Tests in {name} have {con}!'
print(s.format(name=module_name, con='passed')) print(s.format(name=module_name, con='passed'))

View File

@ -1,6 +1,9 @@
#!/usr/bin/python3 #!/usr/bin/python
# mari von steinkirch @2013
# steinkirch at gmail __author__ = "Mari Wahl"
__email__ = "marina.w4hl@gmail.com"
def ordered_sequential_search(seq, n): def ordered_sequential_search(seq, n):
@ -19,7 +22,7 @@ def test_ordered_sequential_search(module_name='this module'):
n2 = 7 n2 = 7
assert(ordered_sequential_search(seq, n1) == True) assert(ordered_sequential_search(seq, n1) == True)
assert(ordered_sequential_search(seq, n2) == False) assert(ordered_sequential_search(seq, n2) == False)
s = 'Tests in {name} have {con}!' s = 'Tests in {name} have {con}!'
print(s.format(name=module_name, con='passed')) print(s.format(name=module_name, con='passed'))

View File

@ -1,16 +1,19 @@
#!/usr/bin/python3 #!/usr/bin/python
# mari von steinkirch @2013
# steinkirch at gmail __author__ = "Mari Wahl"
__email__ = "marina.w4hl@gmail.com"
import numpy import numpy
def searching_in_a_matrix(m1, value): def searching_in_a_matrix(m1, value):
""" searches an element in a matrix where in every row, the values are increasing from left to """ searches an element in a matrix where in every row, the values are increasing from left to
right, but the last number in a row is smaller than the first number in the next row. right, but the last number in a row is smaller than the first number in the next row.
The naive brute force solution scan all numbers and cost O(nm). However, since the numbers are The naive brute force solution scan all numbers and cost O(nm). However, since the numbers are
already sorted, the matrix can be viewed as a 1D sorted array. The binary search algorithm is already sorted, the matrix can be viewed as a 1D sorted array. The binary search algorithm is
suitable. The efficience is O(logmn).""" suitable. The efficience is O(logmn)."""
rows = len(m1) rows = len(m1)
cols = len(m1[0]) cols = len(m1[0])
lo = 0 lo = 0
@ -24,7 +27,7 @@ def searching_in_a_matrix(m1, value):
elif v > value: hi = mid elif v > value: hi = mid
else: lo = mid+1 else: lo = mid+1
return False return False
def test_searching_in_a_matrix(): def test_searching_in_a_matrix():

View File

@ -1,6 +1,8 @@
#!/usr/bin/python3 #!/usr/bin/python
# mari von steinkirch @2013
# steinkirch at gmail __author__ = "Mari Wahl"
__email__ = "marina.w4hl@gmail.com"
def sequential_search(seq, n): def sequential_search(seq, n):
@ -16,7 +18,7 @@ def test_sequential_search(module_name='this module'):
n2 = 7 n2 = 7
assert(sequential_search(seq, n1) == True) assert(sequential_search(seq, n1) == True)
assert(sequential_search(seq, n2) == False) assert(sequential_search(seq, n2) == False)
s = 'Tests in {name} have {con}!' s = 'Tests in {name} have {con}!'
print(s.format(name=module_name, con='passed')) print(s.format(name=module_name, con='passed'))
@ -29,4 +31,4 @@ if __name__ == '__main__':
Case Best Case Worst Case Average Case Case Best Case Worst Case Average Case
item is present 1 n n2 item is present 1 n n2
item is not present n n n item is not present n n n
"""" """

View File

@ -1,112 +0,0 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
''' A recursive and an iterative example of binary search in Python.
Remember: sequence must be sorted! You can return True/False or the index:
>>> l1 = [1, 2, 3, 4, 5, 6, 7]
>>> binary_search_rec(l1, 1)
0
>>> binary_search_rec(l1, 2)
1
>>> binary_search_rec(l1, 3)
2
>>> binary_search_rec(l1, 4)
3
>>> binary_search_rec(l1, 5)
4
>>> binary_search_rec(l1, 6)
5
>>> binary_search_rec(l1, 7)
6
>>> binary_search_rec(l1, 8)
>>> l1 = [1, 2, 3, 4, 5, 6]
>>> binary_search_rec(l1, 1)
0
>>> binary_search_rec(l1, 2)
1
>>> binary_search_rec(l1, 3)
2
>>> binary_search_rec(l1, 4)
3
>>> binary_search_rec(l1, 5)
4
>>> binary_search_rec(l1, 6)
5
>>> binary_search_rec(l1, 7)
>>> l1 = [1, 2, 3, 4, 5, 6, 7]
>>> binary_search_iter(l1, 1)
0
>>> binary_search_iter(l1, 2)
1
>>> binary_search_iter(l1, 3)
2
>>> binary_search_iter(l1, 4)
3
>>> binary_search_iter(l1, 5)
4
>>> binary_search_iter(l1, 6)
5
>>> binary_search_iter(l1, 7)
6
>>> binary_search_iter(l1, 8)
>>> l1 = [1, 2, 3, 4, 5, 6]
>>> binary_search_iter(l1, 1)
0
>>> binary_search_iter(l1, 2)
1
>>> binary_search_iter(l1, 3)
2
>>> binary_search_iter(l1, 4)
3
>>> binary_search_iter(l1, 5)
4
>>> binary_search_iter(l1, 6)
5
>>> binary_search_iter(l1, 7)
'''
def binary_search_iter(seq, key):
hi, lo = len(seq), 0
while lo < hi: # here is <!
mid = (hi+lo)//2
if key == seq[mid]: return mid
elif key < seq[mid]: hi = mid
else: lo = mid + 1
return None
def bool_binary_search_iter(seq, key):
hi, lo = len(seq), 0
while lo < hi:
mid = (hi+lo)//2
if key == seq[mid]: return True
elif key < seq[mid]: hi = mid
else: lo = mid + 1
return False
def binary_search_rec(seq, key, lo=0, hi=None):
hi = hi or len(seq)
if hi <= lo: return None # base case: <= for odd and even numbers!
mid = (hi + lo) // 2
if key == seq[mid]: return mid
elif key < seq[mid] : return binary_search_rec(seq, key, lo, mid) # include until mid-1
else: return binary_search_rec(seq, key, mid+1, hi)
def bool_binary_search_rec(seq, key, lo=0, hi=None):
hi = hi or len(seq)
if hi <= lo: return False # base case: <= for odd and even numbers!
mid = (hi + lo) // 2
if key == seq[mid]: return True
elif key < seq[mid] : return bool_binary_search_rec(seq, key, lo, mid)
else: return bool_binary_search_rec(seq, key, mid+1, hi)
if __name__ == '__main__':
import doctest
doctest.testmod()

View File

@ -1,16 +1,14 @@
#!/usr/bin/python3 #!/usr/bin/python
# Mari von Steinkirch @ 2013 __author__ = "Mari Wahl"
# mari.wahl9@gmail.com __email__ = "marina.w4hl@gmail.com"
# Bernardo Sulzbach (mafagafo) @ 2014
# 1449441@gmail.com
def bubble_sort(seq): def bubble_sort(seq):
""" """
Implementation of bubble sort. Implementation of bubble sort.
O(n²) and thus highly ineffective. O(n2) and thus highly ineffective.
:param seq: the sequence to be sorted. :param seq: the sequence to be sorted.
:return: the sorted sequence. :return: the sorted sequence.
""" """
@ -27,7 +25,7 @@ def bubble_sort(seq):
def test_bubble_sort(module_name='this module'): def test_bubble_sort(module_name='this module'):
seq = [4, 5, 2, 1, 6, 2, 7, 10, 13, 8] seq = [4, 5, 2, 1, 6, 2, 7, 10, 13, 8]
assert(bubble_sort(seq) == sorted(seq)) assert(bubble_sort(seq) == sorted(seq))
s = 'Tests in {name} have {con}!' s = 'Tests in {name} have {con}!'
print(s.format(name=module_name, con='passed')) print(s.format(name=module_name, con='passed'))

View File

@ -1,6 +1,8 @@
#!/usr/bin/python3 #!/usr/bin/python
# mari von steinkirch @2013
# steinkirch at gmail __author__ = "Mari Wahl"
__email__ = "marina.w4hl@gmail.com"
from collections import defaultdict from collections import defaultdict
@ -13,7 +15,7 @@ def count_sort_dict(a):
for k in range(min(c), max(c) + 1): for k in range(min(c), max(c) + 1):
b.extend(c[k]) b.extend(c[k])
return b return b
def test_count_sort(): def test_count_sort():
seq = [3, 5, 2, 6, 8, 1, 0, 3, 5, 6, 2, 5, 4, 1, 5, 3] seq = [3, 5, 2, 6, 8, 1, 0, 3, 5, 6, 2, 5, 4, 1, 5, 3]

View File

@ -1,6 +1,7 @@
#!/usr/bin/python3 #!/usr/bin/python
# mari von steinkirch @2013
# steinkirch at gmail __author__ = "Mari Wahl"
__email__ = "marina.w4hl@gmail.com"
import random import random
@ -24,7 +25,7 @@ def qselect(A, k, left=None, right=None):
swap(A, i, swapIndex) swap(A, i, swapIndex)
swapIndex += 1 swapIndex += 1
i += 1 i += 1
# Move pivot to final position # Move pivot to final position
swap(A, right, swapIndex) swap(A, right, swapIndex)
@ -36,7 +37,7 @@ def qselect(A, k, left=None, right=None):
return qselect(A, k, left=swapIndex+1, right=right) return qselect(A, k, left=swapIndex+1, right=right)
else: else:
return qselect(A, k, left=left, right=swapIndex-1) return qselect(A, k, left=left, right=swapIndex-1)
def find_k_largest_seq_quickselect(seq, k): def find_k_largest_seq_quickselect(seq, k):
@ -54,7 +55,8 @@ def test_find_k_largest_seq_quickselect():
seq = [3, 10, 4, 5, 1, 8, 9, 11, 5] seq = [3, 10, 4, 5, 1, 8, 9, 11, 5]
k = 2 k = 2
assert(find_k_largest_seq_quickselect(seq,k) == [10, 11]) assert(find_k_largest_seq_quickselect(seq,k) == [10, 11])
print("Tests passed!")
if __name__ == '__main__': if __name__ == '__main__':
test_find_k_largest_seq_quickselect() test_find_k_largest_seq_quickselect()

View File

@ -1,11 +1,10 @@
#!/usr/bin/python3 #!/usr/bin/python
# mari von steinkirch @2013
# steinkirch at gmail __author__ = "Mari Wahl"
__email__ = "marina.w4hl@gmail.com"
from do_benchmark import benchmark
@benchmark
def gnome_sort(seq): def gnome_sort(seq):
''' sort a sequence using the gnome sort alg ''' ''' sort a sequence using the gnome sort alg '''
i = 0 i = 0
@ -29,7 +28,7 @@ if __name__ == '__main__':

View File

@ -1,6 +1,8 @@
#!/usr/bin/python3 #!/usr/bin/python
# mari von steinkirch @2013
# steinkirch at gmail __author__ = "Mari Wahl"
__email__ = "marina.w4hl@gmail.com"
class Heap(object): class Heap(object):
def __init__(self, data): def __init__(self, data):
@ -19,13 +21,13 @@ class Heap(object):
def right_child(self, i): def right_child(self, i):
return (i << 1) + 2 # +2 instead of +1 because it's 0-indexed. return (i << 1) + 2 # +2 instead of +1 because it's 0-indexed.
def __max_heapify__(self, i): def __max_heapify__(self, i):
largest = i largest = i
left = self.left_child(i) left = self.left_child(i)
right = self.right_child(i) right = self.right_child(i)
n = len(self.data) n = len(self.data)
largest = (left < n and self.data[left] > self.data[i]) and left or i largest = (left < n and self.data[left] > self.data[i]) and left or i
largest = (right < n and self.data[right] > self.data[largest]) and right or largest largest = (right < n and self.data[right] > self.data[largest]) and right or largest
if i != largest: if i != largest:

View File

@ -0,0 +1,85 @@
#!/usr/bin/python
__author__ = "Mari Wahl"
__email__ = "marina.w4hl@gmail.com"
''' Heapsort using Pythons libraries'''
import heapq
def heap_sort1(seq):
''' heap sort with Python's heapq '''
h = []
for value in seq:
heapq.heappush(h, value)
return [heapq.heappop(h) for i in range(len(h))]
def test_heap_sort1():
seq = [3, 5, 2, 6, 8, 1, 0, 3, 5, 6, 2]
assert(heap_sort1(seq) == sorted(seq))
print('Tests passed!')
''' Heapsort using my Heap class '''
from heap import Heap
def heap_sort2(seq):
heap = Heap(seq)
res = []
for i in range(len(seq)):
res.insert(0, heap.extract_max())
return res
def test_heap_sort2():
seq = [3, 5, 2, 6, 8, 1, 0, 3, 5, 6, 2]
print heap_sort2(seq)
print('Tests passed!')
''' A third way of doing heap sort '''
def heap_sort3(seq):
for start in range((len(seq)-2)//2, -1, -1):
siftdown(seq, start, len(seq)-1)
for end in range(len(seq)-1, 0, -1):
seq[end], seq[0] = seq[0], seq[end]
siftdown(seq, 0, end - 1)
return seq
def siftdown(seq, start, end):
root = start
while True:
child = root * 2 + 1
if child > end: break
if child + 1 <= end and seq[child] < seq[child + 1]:
child += 1
if seq[root] < seq[child]:
seq[root], seq[child] = seq[child], seq[root]
root = child
else:
break
def test_heap_sort3():
seq = [3, 5, 2, 6, 8, 1, 0, 3, 5, 6, 2]
assert(heap_sort3(seq) == sorted(seq))
print('Tests passed!')
if __name__ == '__main__':
test_heap_sort1()
test_heap_sort2()
test_heap_sort3()

View File

@ -1,23 +0,0 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
import heapq
def heap_sort1(seq):
''' heap sort with Python's heapq '''
h = []
for value in seq:
heapq.heappush(h, value)
return [heapq.heappop(h) for i in range(len(h))]
def test_heap_sort1():
seq = [3, 5, 2, 6, 8, 1, 0, 3, 5, 6, 2]
assert(heap_sort1(seq) == sorted(seq))
print('Tests passed!')
if __name__ == '__main__':
test_heap_sort1()

View File

@ -1,24 +0,0 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
from heap import Heap
def heap_sort2(seq):
heap = Heap(seq)
res = []
for i in range(len(seq)):
res.insert(0, heap.extract_max())
return res
def test_heap_sort2():
seq = [3, 5, 2, 6, 8, 1, 0, 3, 5, 6, 2]
assert(heap_sort2(seq) == sorted(seq))
print('Tests passed!')
if __name__ == '__main__':
test_heap_sort2()

View File

@ -1,36 +0,0 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
def heap_sort3(seq):
for start in range((len(seq)-2)//2, -1, -1):
siftdown(seq, start, len(seq)-1)
for end in range(len(seq)-1, 0, -1):
seq[end], seq[0] = seq[0], seq[end]
siftdown(seq, 0, end - 1)
return seq
def siftdown(seq, start, end):
root = start
while True:
child = root * 2 + 1
if child > end: break
if child + 1 <= end and seq[child] < seq[child + 1]:
child += 1
if seq[root] < seq[child]:
seq[root], seq[child] = seq[child], seq[root]
root = child
else:
break
def test_heap_sort():
seq = [3, 5, 2, 6, 8, 1, 0, 3, 5, 6, 2]
assert(heap_sort3(seq) == sorted(seq))
print('Tests passed!')
if __name__ == '__main__':
test_heap_sort3()

View File

@ -1,6 +1,8 @@
#!/usr/bin/python3 #!/usr/bin/python
# mari von steinkirch @2013
# steinkirch at gmail __author__ = "Mari Wahl"
__email__ = "marina.w4hl@gmail.com"
@ -38,7 +40,7 @@ if __name__ == '__main__':

View File

@ -1,25 +1,40 @@
#!/usr/bin/python3 #!/usr/bin/python
# mari von steinkirch @2013
# steinkirch at gmail __author__ = "Mari Wahl"
__email__ = "marina.w4hl@gmail.com"
''' Some examples of how to implement Merge Sort in Python
--> RUNTIME: WORST/BEST/AVERAGE Is O(nlogn)
--> space complexity is O(n) for arrays
--> not in place, good for large arrays
>>> seq = [3, 5, 2, 6, 8, 1, 0, 3, 5, 6, 2]
>>> merge_sort(seq) == sorted(seq)
True
>>> seq2 = [3, 3, 3, 3, 3, 3, 3, 3]
>>> merge_sort(seq2) == sorted(seq2)
True
>>> seq3 = []
>>> merge_sort(seq3) == sorted(seq3)
True
'''
def merge_sort(seq): def merge_sort(seq):
if len(seq) <= 1: return seq if len(seq) <= 1: return seq
mid = len(seq)//2 mid = len(seq)//2
lft, rgt = seq[:mid], seq[mid:] lft, rgt = seq[:mid], seq[mid:]
if len(lft)>1: lft = merge_sort(lft) if len(lft)>1: lft = merge_sort(lft)
if len(rgt)>1: rgt = merge_sort(rgt) if len(rgt)>1: rgt = merge_sort(rgt)
res = [] res = []
while lft and rgt: while lft and rgt:
if lft [-1]>= rgt[-1]: if lft [-1]>= rgt[-1]:
res.append(lft.pop()) res.append(lft.pop())
else: else:
res.append(rgt.pop()) res.append(rgt.pop())
res.reverse() res.reverse()
return(lft or rgt) + res return(lft or rgt) + res
@ -29,5 +44,57 @@ def test_merge_sort():
print('Tests passed!') print('Tests passed!')
'''
We could also divide this sort into two parts, separating
the merge part in another function
'''
def merge_sort_sep(seq):
if len(seq) < 2 : return seq # base case
mid = len(seq)//2
left, right = None, None # we could have declared the arrays here,
# but this would allocate unecessary extra space
if seq[:mid]: left = merge_sort(seq[:mid])
if seq[mid:]: right = merge_sort(seq[mid:]) # notice that mid is included!
return merge(left, right) # merge iteratively
def merge(left, right):
if not left or not right: return left or right # nothing to be merged
result = []
i, j = 0, 0
while i < len(left) and j < len(right):
if left[i] <= right[j]:
result.append(left[i])
i += 1
else:
result.append(right[j])
j += 1
if left[i:] : result.extend(left[i:]) # REMEMBER TO TO ENXTEND NOT APPEND
if right[j:] : result.extend(right[j:])
return result
''' The two following merge functions are O(2n)=O(n) and O(n) respectively. They
illustrate many features in Python that '''
def merge_2n(left, right):
if not left or not right: return left or right # nothing to be merged
result = []
while left and right:
if left[-1] >= right[-1]:
result.append(left.pop())
else:
result.append(right.pop())
result.reverse()
return (left or right) + result
if __name__ == '__main__': if __name__ == '__main__':
test_merge_sort() test_merge_sort()

View File

@ -1,6 +1,7 @@
#!/usr/bin/python3 #!/usr/bin/python
# mari von steinkirch @2013
# steinkirch at gmail __author__ = "Mari Wahl"
__email__ = "marina.w4hl@gmail.com"
''' --> In the case of two arrays: we can merge two arrays using the merge function from the merge sort ''' --> In the case of two arrays: we can merge two arrays using the merge function from the merge sort
--> we can do this for files too, merging each two --> we can do this for files too, merging each two
@ -16,27 +17,27 @@
result.append(right.pop()) result.append(right.pop())
result.reverse() result.reverse()
return (left or right) + result return (left or right) + result
2) If we can't modify or we want to in place, we need two pointers: 2) If we can't modify or we want to in place, we need two pointers:
>>> l1 = [1, 2, 3, 4, 5, 6, 7] >>> l1 = [1, 2, 3, 4, 5, 6, 7]
>>> l2 = [2, 4, 5, 8] >>> l2 = [2, 4, 5, 8]
>>> merge(l1, l2) >>> merge(l1, l2)
[1, 2, 2, 3, 4, 4, 5, 5, 6, 7, 8] [1, 2, 2, 3, 4, 4, 5, 5, 6, 7, 8]
3) For example, in the case we have a big array filled 0s in the end, and another array with the size of the number of 0s: 3) For example, in the case we have a big array filled 0s in the end, and another array with the size of the number of 0s:
>>> l1 = [1, 2, 3, 4, 5, 6, 7, 0, 0, 0, 0] >>> l1 = [1, 2, 3, 4, 5, 6, 7, 0, 0, 0, 0]
>>> l2 = [2, 4, 5, 8] >>> l2 = [2, 4, 5, 8]
>>> merge_two_arrays_inplace(l1, l2) >>> merge_two_arrays_inplace(l1, l2)
[1, 2, 2, 3, 4, 4, 5, 5, 6, 7, 8] [1, 2, 2, 3, 4, 4, 5, 5, 6, 7, 8]
4) If we want to merge sorted files (and we have plenty of RAM to load all files): 4) If we want to merge sorted files (and we have plenty of RAM to load all files):
>>> list_files = ['1.dat', '2.dat', '3.dat'] >>> list_files = ['1.dat', '2.dat', '3.dat']
>>> merge_files(list_files) >>> merge_files(list_files)
[1, 1, 2, 3, 3, 3, 4, 5, 5, 5, 6, 7, 8] [1, 1, 2, 3, 3, 3, 4, 5, 5, 5, 6, 7, 8]
''' '''
def merge(left, right): def merge(left, right):
if not left or not right: return left or right # nothing to be merged if not left or not right: return left or right # nothing to be merged
@ -54,15 +55,15 @@ def merge(left, right):
return result return result
def merge_two_arrays_inplace(l1, l2): def merge_two_arrays_inplace(l1, l2):
if not l1 or not l2: return l1 or l2 # nothing to be merged if not l1 or not l2: return l1 or l2 # nothing to be merged
p2 = len(l2) - 1 p2 = len(l2) - 1
p1 = len(l1) - len(l2) - 1 p1 = len(l1) - len(l2) - 1
p12 = len(l1) - 1 p12 = len(l1) - 1
while p2 >= 0 and p1 >= 0: while p2 >= 0 and p1 >= 0:
item_to_be_merged = l2[p2] item_to_be_merged = l2[p2]
item_bigger_array = l1[p1] item_bigger_array = l1[p1]
if item_to_be_merged < item_bigger_array: if item_to_be_merged < item_bigger_array:
l1[p12] = item_bigger_array l1[p12] = item_bigger_array
p1 -= 1 p1 -= 1
@ -81,11 +82,11 @@ def merge_files(list_files):
with open(filename, 'r') as file: with open(filename, 'r') as file:
for line in file: for line in file:
aux.append(int(line)) aux.append(int(line))
result.append(aux) result.append(aux)
final.extend(result.pop()) final.extend(result.pop())
for l in result: for l in result:
final = merge(l, final) final = merge(l, final)
return final return final
if __name__ == '__main__': if __name__ == '__main__':

View File

@ -1,6 +1,27 @@
#!/usr/bin/python3 #!/usr/bin/python
# mari von steinkirch @2013
# steinkirch at gmail __author__ = "Mari Wahl"
__email__ = "marina.w4hl@gmail.com"
''' Some examples of how to implement Quick Sort in Python
--> RUNTIME: BEST/AVERAGE Is O(nlogn), WORST is O(n2)
--> the first example is not in place, the second is in place
--> test with two element arrays, identical values
Quick sort in place:
1) select pivot as the index = 0
2) start pointer1 at index = 1 and pointer2 in the last element
3) while pointer1 < pointer2:
if value in pointer1 <= pivot
swap value in pointer1 with value in pointer2 and advanced pointer2
else
advance pointer1
4) now the array is like this:
[pivot, larger than pivot, smaller than pivot]
5) swap the pivot where pointer 1 stop
6) do recursively for [smaller] + [pivot] + [larger]
'''
@ -11,22 +32,52 @@ def quick_sort(seq):
left = quick_sort([x for x in seq[1:] if x < pivot]) left = quick_sort([x for x in seq[1:] if x < pivot])
right = quick_sort([x for x in seq[1:] if x >= pivot]) right = quick_sort([x for x in seq[1:] if x >= pivot])
return left + [pivot] + right return left + [pivot] + right
''' slightly different in the way we get the pivot'''
def quick_sort(seq):
if len(seq) < 2 : return seq
mid = len(seq)//2
pi = seq[mid]
seq = seq[:mid] + seq[mid+1:]
left = quick_sort([x for x in seq if x <= pi]) # REMEMBER TO INCLUDE X (OR IN RIGHT)
right = quick_sort([x for x in seq if x > pi])
return left + [pi] + right
""" we can also divide them into two functions """ """ we can also divide them into two functions """
def partition(seq): def partition(seq):
pi,seq = seq[0],seq[1:] pi,seq = seq[0],seq[1:]
lo = [x for x in seq if x <= pi] lo = [x for x in seq if x <= pi]
hi = [x for x in seq if x > pi] hi = [x for x in seq if x > pi]
return lo, pi, hi return lo, pi, hi
def quick_sort_divided(seq): def quick_sort_divided(seq):
if len(seq) < 2: return seq if len(seq) < 2: return seq
lo, pi, hi = partition(seq) lo, pi, hi = partition(seq)
return quick_sort_divided(lo) + [pi] + quick_sort_divided(hi) return quick_sort_divided(lo) + [pi] + quick_sort_divided(hi)
''' quick_sort in place '''
def quick_sort_in(seq):
if len(seq) < 2 : return seq
if len(seq) == 2 and seq[0] > seq[1]:
seq[0], seq[1] = seq[1], seq[0] # problems when only 2 elements because of swap
pivot = seq[0] # start at the ends because we don't know how many elements
p1, p2 = 1, len(seq) -1 # set pointers at both ends
while p1 < p2: # must be < or out of range
if seq[p1] <= pivot: # must be <= because of pivot swap
seq[p1], seq[p2] = seq[p2], seq[p1]
p2 -= 1
else:
p1 += 1
seq[0], seq[p1] = seq[p1], pivot
return quick_sort_in(seq[p1+1:]) + [seq[p1]] + quick_sort_in(seq[:p1])
def test_quick_sort(): def test_quick_sort():
seq = [3, 5, 2, 6, 8, 1, 0, 3, 5, 6, 2] seq = [3, 5, 2, 6, 8, 1, 0, 3, 5, 6, 2]

View File

@ -1,6 +1,7 @@
#!/usr/bin/python3 #!/usr/bin/python
# mari von steinkirch @2013
# steinkirch at gmail __author__ = "Mari Wahl"
__email__ = "marina.w4hl@gmail.com"
def selection_sort(seq): def selection_sort(seq):
@ -25,7 +26,7 @@ if __name__ == '__main__':

View File

@ -1,6 +1,7 @@
#!/usr/bin/python3 #!/usr/bin/python
# mari von steinkirch @2013
# steinkirch at gmail __author__ = "Mari Wahl"
__email__ = "marina.w4hl@gmail.com"
''' A method to sort an array so that all the anagrams are together. Since we only ''' A method to sort an array so that all the anagrams are together. Since we only
want the anagrams to be grouped, we can use a dictionary for this task. This want the anagrams to be grouped, we can use a dictionary for this task. This
@ -13,21 +14,21 @@
from collections import defaultdict from collections import defaultdict
def sort_anagrams_together(l1): def sort_anagrams_together(l1):
result = [] result = []
# step 1 save the anagrams together # step 1 save the anagrams together
dict_aux = defaultdict(list) # rememebr to indicate the type dict_aux = defaultdict(list) # rememebr to indicate the type
for word in l1: for word in l1:
key = ''.join(sorted(word)) # need to sort the strings and join it key = ''.join(sorted(word)) # need to sort the strings and join it
dict_aux[key].append(word) # because only sorted give a list of each char dict_aux[key].append(word) # because only sorted give a list of each char
# step 2 print the anagrams. Note that if you want everything # step 2 print the anagrams. Note that if you want everything
# sorted you would have to sort the keys and insert the angrams after that # sorted you would have to sort the keys and insert the angrams after that
for key in dict_aux: for key in dict_aux:
result.extend(dict_aux[key]) result.extend(dict_aux[key])
return result return result
if __name__ == '__main__': if __name__ == '__main__':
import doctest import doctest

View File

@ -1,70 +0,0 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
''' Some examples of how to implement Merge Sort in Python
--> RUNTIME: WORST/BEST/AVERAGE Is O(nlogn)
--> space complexity is O(n) for arrays
--> not in place, good for large arrays
>>> seq = [3, 5, 2, 6, 8, 1, 0, 3, 5, 6, 2]
>>> merge_sort(seq) == sorted(seq)
True
>>> seq2 = [3, 3, 3, 3, 3, 3, 3, 3]
>>> merge_sort(seq2) == sorted(seq2)
True
>>> seq3 = []
>>> merge_sort(seq3) == sorted(seq3)
True
'''
''' This is the main function that keep dividing the seq '''
def merge_sort(seq):
if len(seq) < 2 : return seq # base case
mid = len(seq)//2
left, right = None, None # we could have declared the arrays here,
# but this would allocate unecessary extra space
if seq[:mid]: left = merge_sort(seq[:mid])
if seq[mid:]: right = merge_sort(seq[mid:]) # notice that mid is included!
return merge(left, right) # merge iteratively
''' The two following merge functions are O(2n)=O(n) and O(n) respectively. They
illustrate many features in Python that '''
def merge_2n(left, right):
if not left or not right: return left or right # nothing to be merged
result = []
while left and right:
if left[-1] >= right[-1]:
result.append(left.pop())
else:
result.append(right.pop())
result.reverse()
return (left or right) + result
def merge(left, right):
if not left or not right: return left or right # nothing to be merged
result = []
i, j = 0, 0
while i < len(left) and j < len(right):
if left[i] <= right[j]:
result.append(left[i])
i += 1
else:
result.append(right[j])
j += 1
if left[i:] : result.extend(left[i:]) # REMEMBER TO TO ENXTEND NOT APPEND
if right[j:] : result.extend(right[j:])
return result
if __name__ == '__main__':
import doctest
doctest.testmod()

View File

@ -1,74 +0,0 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
''' Some examples of how to implement Quick Sort in Python
--> RUNTIME: BEST/AVERAGE Is O(nlogn), WORST is O(n2)
--> the first example is not in place, the second is in place
--> test with two element arrays, identical values
Quick sort in place:
1) select pivot as the index = 0
2) start pointer1 at index = 1 and pointer2 in the last element
3) while pointer1 < pointer2:
if value in pointer1 <= pivot
swap value in pointer1 with value in pointer2 and advanced pointer2
else
advance pointer1
4) now the array is like this:
[pivot, larger than pivot, smaller than pivot]
5) swap the pivot where pointer 1 stop
6) do recursively for [smaller] + [pivot] + [larger]
>>> seq = [3, 5, 2, 6, 8, 1, 0, 3, 5, 6, 2]
>>> quick_sort(seq) == sorted(seq)
True
>>> quick_sort([3, 3, 3, 3, 3, 3]) == [3, 3, 3, 3, 3, 3]
True
>>> quick_sort([]) == []
True
>>> quick_sort([2,1]) == [1, 2]
True
>>> quick_sort_in(seq) == sorted(seq)
True
>>> quick_sort_in([3, 3, 3, 3, 3, 3]) == [3, 3, 3, 3, 3, 3]
True
>>> quick_sort_in([]) == []
True
>>> quick_sort_in([2,1]) == [1, 2]
True
'''
def quick_sort(seq):
if len(seq) < 2 : return seq
mid = len(seq)//2
pi = seq[mid]
seq = seq[:mid] + seq[mid+1:]
left = quick_sort([x for x in seq if x <= pi]) # REMEMBER TO INCLUDE X (OR IN RIGHT)
right = quick_sort([x for x in seq if x > pi])
return left + [pi] + right
def quick_sort_in(seq):
if len(seq) < 2 : return seq
if len(seq) == 2 and seq[0] > seq[1]:
seq[0], seq[1] = seq[1], seq[0] # problems when only 2 elements because of swap
pivot = seq[0] # start at the ends because we don't know how many elements
p1, p2 = 1, len(seq) -1 # set pointers at both ends
while p1 < p2: # must be < or out of range
if seq[p1] <= pivot: # must be <= because of pivot swap
seq[p1], seq[p2] = seq[p2], seq[p1]
p2 -= 1
else:
p1 += 1
seq[0], seq[p1] = seq[p1], pivot
return quick_sort_in(seq[p1+1:]) + [seq[p1]] + quick_sort_in(seq[:p1])
if __name__ == '__main__':
import doctest
doctest.testmod()