organization in the src structure, modification of README

This commit is contained in:
Mari Wahl 2015-01-06 18:30:04 -05:00
parent c2ca11f247
commit 6afe96fa4d
165 changed files with 64 additions and 184 deletions

View file

@ -0,0 +1,33 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
from collections import Counter
def Counter_example():
''' show some examples for Counter '''
''' it is a dictionary that maps the items to the number of occurences '''
seq1 = [1, 2, 3, 5, 1, 2, 5, 5, 2, 5, 1, 4]
seq_counts = Counter(seq1)
print(seq_counts)
''' we can increment manually or use the update() method '''
seq2 = [1, 2, 3]
seq_counts.update(seq2)
print(seq_counts)
seq3 = [1, 4, 3]
for key in seq3:
seq_counts[key] += 1
print(seq_counts)
''' also, we can use set operations such as a-b or a+b '''
seq_counts_2 = Counter(seq3)
print(seq_counts_2)
print(seq_counts + seq_counts_2)
print(seq_counts - seq_counts_2)
if __name__ == '__main__':
Counter_example()

View file

@ -0,0 +1,31 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
from collections import OrderedDict
def OrderedDict_example():
''' show some examples for OrderedDict '''
''' keep the order of insertion.
maintains a doubly linked list, so size is more than twice than normal dict'''
pairs = [('a', 1), ('b',2), ('c',3)]
d1 = {}
for key, value in pairs:
if key not in d1:
d1[key] = []
d1[key].append(value)
for key in d1:
print(key, d1[key])
d2 = OrderedDict(pairs)
for key in d2:
print(key, d2[key])
if __name__ == '__main__':
OrderedDict_example()

View file

View file

@ -0,0 +1,21 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
import collections
import string
import sys
def count_unique_word():
words = collections.defaultdict(int)
strip = string.whitespace + string.punctuation + string.digits + "\"'"
for filename in sys.argv[1:]:
with open(filename) as file:
for line in file:
for word in line.lower().split():
word = word.strip(strip)
if len(word) > 2:
words[word] = +1
for word in sorted(words):
print("'{0}' occurs {1} times.".format(word, words[word]))

View file

@ -0,0 +1,27 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
from collections import defaultdict
def defaultdict_example():
''' show some examples for defaultdicts '''
pairs = {('a', 1), ('b',2), ('c',3)}
d1 = {}
for key, value in pairs:
if key not in d1:
d1[key] = []
d1[key].append(value)
print(d1)
d2 = defaultdict(list)
for key, value in pairs:
d2[key].append(value)
print(d2)
if __name__ == '__main__':
defaultdict_example()

View file

@ -0,0 +1,32 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
import string
def delete_unique_word(str1):
''' find and delete all the duplicate characters in a string '''
# create ordered dict
table_c = { key : 0 for key in string.ascii_lowercase}
# fill the table with the chars in the string
for i in str1:
table_c[i] += 1
# scan the table to find times chars > 1
for key, value in table_c.items():
if value > 1:
str1 = str1.replace(key, "")
return str1
def test_delete_unique_word():
str1 = "google"
assert(delete_unique_word(str1) == 'le')
print('Tests passed!')
if __name__ == '__main__':
test_delete_unique_word()

View file

@ -0,0 +1,34 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
def hash_func(astring, tablesize):
sum = 0
for pos in range(len(astring)):
sum = sum + ord(astring[pos])
return sum%tablesize
def find_anagram_hash_function(word1, word2):
''' verify if words are anagrams by comparying hash functions'''
tablesize = 11
return hash_func(word1, tablesize) == hash_func(word2, tablesize)
def test_find_anagram_hash_function(module_name='this module'):
word1 = 'buffy'
word2 = 'bffyu'
word3 = 'bffya'
assert(find_anagram_hash_function(word1, word2) == True)
assert(find_anagram_hash_function(word1, word3) == False)
s = 'Tests in {name} have {con}!'
print(s.format(name=module_name, con='passed'))
if __name__ == '__main__':
test_find_anagram_hash_function()

View file

@ -0,0 +1,33 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
from collections import Counter, defaultdict
def find_dice_probabilities(S, n_faces=6):
''' given 2 dice, determine number of ways to sum S if all dice are rolled '''
if S > 2*n_faces or S < 2: return None
cdict = Counter()
ddict = defaultdict(list)
for dice1 in range(1, n_faces+1):
for dice2 in range(1, n_faces+1):
t = [dice1, dice2]
cdict[dice1+dice2] += 1
ddict[dice1+dice2].append( t)
return [cdict[S], ddict[S]]
def test_find_dice_probabilities(module_name='this module'):
n_faces = 6
S = 5
results = find_dice_probabilities(S, n_faces)
print(results)
assert(results[0] == len(results[1]))
if __name__ == '__main__':
test_find_dice_probabilities()

View file

@ -0,0 +1,31 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
from collections import Counter
def find_top_N_recurring_words(seq, N):
''' find the top N recurring words in a file:
1) use a hash table to find counts
2) sort the list on base of the maximum counts
3) return the last N words '''
dcounter = Counter()
for word in seq.split():
dcounter[word] += 1
return dcounter.most_common(N)
def test_find_top_N_recurring_words(module_name='this module'):
seq = 'buffy angel monster xander a willow gg buffy the monster super buffy angel'
N = 3
assert(find_top_N_recurring_words(seq, N) == [('buffy', 3), ('monster', 2), ('angel', 2)])
s = 'Tests in {name} have {con}!'
print(s.format(name=module_name, con='passed'))
if __name__ == '__main__':
test_find_top_N_recurring_words()

View file

@ -0,0 +1,51 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
'''To use timeit you create a Timer object whose parameters are two Python statements. The first parameter is a Python statement that you want to time; the second parameter is a statement that will run once to set up the test. The timeit module will then time how long it takes to execute the statement some number of times. By default timeit will try to run the statement one million times. When its done it returns the time as a floating point value representing the total number of seconds. However, since it executes the statement a million times you can read the result as the number of microseconds to execute the test one time. You can also pass timeit a named parameter called number that allows you to specify how many times the test statement is executed. The following session shows how long it takes to run each of our test functions 1000 times. '''
import timeit
import random
for i in range(10000,1000001,20000):
''' this experiment confirm that the contains operator for lists is O(n) and for dict is O(1) '''
t = timeit.Timer("random.randrange(%d) in x"%i, "from __main__ import random,x")
x = list(range(i))
lst_time = t.timeit(number=1000)
x = {j:None for j in range(i)}
d_time = t.timeit(number=1000)
print("%d,%10.3f,%10.3f" % (i, lst_time, d_time))
""" There rersults are:
10000, 0.192, 0.002
30000, 0.600, 0.002
50000, 1.000, 0.002
70000, 1.348, 0.002
90000, 1.755, 0.002
110000, 2.194, 0.002
130000, 2.635, 0.002
150000, 2.951, 0.002
170000, 3.405, 0.002
190000, 3.743, 0.002
210000, 4.142, 0.002
230000, 4.577, 0.002
250000, 4.797, 0.002
270000, 5.371, 0.002
290000, 5.690, 0.002
310000, 5.977, 0.002
so we can see the linear tile for lists, and constant for dict!
Big-O Efficiency of Python Dictionary Operations
Operation Big-O Efficiency
copy O(n)
get item O(1)
set item O(1)
delete item O(1)
contains (in) O(1)
iteration O(n)
"""

View file

@ -0,0 +1,38 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
def usual_dict(dict_data):
newdata = {}
for k, v in dict_data:
if k in newdata:
newdata[k].append(v)
else:
newdata[k] = [v]
return newdata
def setdefault_dict(dict_data):
newdata = {}
for k, v in dict_data:
newdata.setdefault(k, []).append(v)
return newdata
def test_setdef(module_name='this module'):
dict_data = (('key1', 'value1'),
('key1', 'value2'),
('key2', 'value3'),
('key2', 'value4'),
('key2', 'value5'),)
print(usual_dict(dict_data))
print(setdefault_dict(dict_data))
s = 'Tests in {name} have {con}!'
print(s.format(name=module_name, con='passed'))
if __name__ == '__main__':
test_setdef()

View file

@ -0,0 +1,45 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
import string
def verify_two_strings_are_anagrams(str1, str2):
""" find whether two words are anagrams. Since sets do not count occurency, and sorting is O(nlogn)
we will use hash tables. We scan the first string and add all the character occurences. Then we
scan the second tring and decrease all the caracther occurences. If all the counts are zero, it is
an anagram"""
# create the hash table
ana_table = {key:0 for key in string.ascii_lowercase}
# scan first string
for i in str1:
ana_table[i] += 1
# scan second string
for i in str2:
ana_table[i] -= 1
# verify whether all the entries are 0
if len(set(ana_table.values())) < 2: return True
else: return False
def test_verify_two_strings_are_anagrams():
str1 = 'marina'
str2 = 'aniram'
assert(verify_two_strings_are_anagrams(str1, str2) == True)
str1 = 'google'
str2 = 'gouglo'
assert(verify_two_strings_are_anagrams(str1, str2) == False)
print('Tests passed!')
if __name__ == '__main__':
test_verify_two_strings_are_anagrams()

View file

@ -0,0 +1,29 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
''' give all the combinations of a str or list:
>>> l1 = (1, 2, 3)
>>> comb_str(l1)
[[1], [1, [2]], [1, [2, 3]], [1, [3]], [2], [2, 3], [3]]
>>> comb_str([])
[]
'''
def comb_str(l1):
if len(l1) < 2: return l1
result = []
for i in range(len(l1)):
result.append([l1[i]])
for comb in comb_str(l1[i+1:]):
result.append([l1[i], comb])
return result
if __name__ == '__main__':
import doctest
doctest.testmod()

View file

@ -0,0 +1,68 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
''' two routines to convert str to int and int to str:
- bc: negative str, zero, exp numbers (ex. 1e5), other bases, NAN
>>> conv_str2int('367')
367
>>> conv_str2int('0')
0
>>> conv_str2int('-10')
-10
>>> conv_str2int('1e5')
100000
>>> conv_int2str(0)
'0'
>>> conv_int2str(1e5)
'100000'
>>> conv_int2str(367)
'367'
>>> conv_int2str(-10)
'-10'
'''
def conv_int2str(int1):
aux_dict = {key:value for key in range(10) for value in '0123456789'[key]}
if int1 == 0: return '0' # REMEMBER TO HANDLE 0
if int1 < 0: # REMEMBER TO HANDLE NEGATIVE
sign = '-'
int1 = int1*(-1)
else:
sign = ''
aux_ls = []
while int1 > 0:
c = int1%10
int1 = int1//10
cadd = aux_dict[c]
aux_ls.append(cadd)
aux_ls.reverse() # REMEMBER TO REVERSE
return sign + ''.join(aux_ls)
def conv_str2int(str1):
if not str1: return None
aux_dict = {key:value for value in range(10) for key in '0123456789'[value]}
if str1[0] == '-':
sign = -1
str1 = str1[1:] # REMEMBER TO CUT THE SIGN FROM THE STR
else:
sign = 1
dec, result = 1, 0
for i in range(len(str1)-1, -1, -1): # REMEMBER TO FINISH IN -1, NOT 0, AND
aux = str1[i] # AND DO THE STEPS -1
if aux == 'e':
exp_num = conv_str2int(str1[i+1:])
number = conv_str2int(str1[:i])
result = number*10**exp_num
break
result += aux_dict[aux]*dec
dec *= 10
return result*sign
if __name__ == '__main__':
import doctest
doctest.testmod()

View file

@ -0,0 +1,24 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
import string
import sys
def count_unique_word():
''' list every word and number of times in alphabetical order for input files '''
words = {} # create an empty dictionary
strip = string.whitespace + string.punctuation + string.digits + "\"'"
for filename in sys.argv[1:]:
with open(filename) as file:
for line in file:
for word in line.lower().split():
word = word.strip(strip)
if len(word) > 2:
words[word] = words.get(word,0) +1
for word in sorted(words):
print("'{0}' occurs {1} times.".format(word, words[word]))
count_unique_word()

View file

@ -0,0 +1,33 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
def find_0_MxN(m):
''' find 0s in a matrix and replace the col and row to 0s:
>>> m1 = [[1,2,3,4], [5,6,7,8], [9,10,11,12], [13,14,15,16]]
>>> find_0_MxN(m1)
[[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]]
>>> m2 = [[1, 2, 3, 4], [0, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]]
>>> find_0_MxN(m2)
[[0, 2, 3, 4], [0, 0, 0, 0], [0, 10, 11, 12], [0, 14, 15, 16]]
'''
index = []
for row in range(len(m)):
for col in range(len(m[0])):
if m[row][col] == 0:
index.append((row, col))
for i in index:
row = i[0]
col = i[1]
for i in range(len(m)):
m[row][i] = 0
for i in range(len(m[0])):
m[i][col] = 0
return m
if __name__ == '__main__':
import doctest
doctest.testmod()

View file

@ -0,0 +1,47 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
def find_all_permutations_string(str1):
''' print all the permutations of a given string, recursive so runtime is O(n*(n-1)) '''
res = []
if len(str1) == 1:
res = [str1]
else:
for i, c in enumerate(str1):
for perm in find_all_permutations_string(str1[:i] + str1[i+1:]):
res += [c + perm]
return res
def find_all_permutations_string_crazy(str1):
''' crazy simple way of find all the permutations of a string, also using recursion'''
return [str1] if len(str1) == 1 else [c + perm for i, c in enumerate(str1) for perm in find_all_permutations_string_crazy(str1[:i]+str1[i+1:])]
def find_all_permutations_string_stdlib(str1):
''' find all the permutations of a string just using the available packages '''
from itertools import permutations
perms = [''.join(p) for p in permutations(str1)]
return perms
def test_find_all_permutations_string():
str1 = "abc"
perm_set = {'abc', 'bac', 'cab', 'acb', 'cba', 'bca'}
assert(set(find_all_permutations_string(str1)) == perm_set)
assert(set(find_all_permutations_string_crazy(str1)) == perm_set)
assert(set(find_all_permutations_string_stdlib(str1)) == perm_set)
print('Tests passed!')
if __name__ == '__main__':
test_find_all_permutations_string()

View file

@ -0,0 +1,47 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
def find_closest_num_seq_unsorted(seq):
''' Find the Closest two Numbers in a Sequence. If we do this without sorting
first, the runtime will be O(n^2) '''
dd = float("inf")
for x in seq:
for y in seq:
if x == y: continue
d = abs(x - y)
if d < dd:
xx, yy, dd = x, y, d
return xx, yy
def find_closest_num_seq_sorted(seq):
''' However, if we sort first, we can achieve it with runtime O(n log n): '''
seq.sort()
print(seq)
dd = float("inf")
for i in range(len(seq) - 1):
x, y = seq[i], seq[i+1]
if x == y: continue
d = abs(x-y)
if d < dd:
xx, yy, dd = x, y, d
return xx, yy
def test_find_closest_num_seq(module_name='this module'):
import random
seq = [random.randrange(100) for i in range(20)]
print(seq)
print(find_closest_num_seq_sorted(seq))
print(find_closest_num_seq_unsorted(seq))
s = 'Tests in {name} have {con}!'
print(s.format(name=module_name, con='passed'))
if __name__ == '__main__':
test_find_closest_num_seq()

View file

@ -0,0 +1,44 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
def find_duplicate_num_array(l1):
""" an array contains n numbers ranging from 0 to n-1. there are some numbers duplicated, but it is
not clear how many. this code find a duplicate number in the array. """
""" A naive solution is to sort the input array, costing O(nlogn). Another solution is the utilization of a hash set. When the number is scanned, it is either in or not. It costs O(n) auxiliary memory to accomodate a hash set. A third solution, that only costs O(1) is consider that indexes in an array with length n are in the range n-1. If there were no duplication in the n numbers from 0 to n-1, we could rearange them sorted, so that each i has its ith number. Since there are duplicates, some locations are occupied by multiple numbers, other are vacant. So every number is scanned one by one, if it the number is not in the right i, it is compared to that from i, and the duplicate can be found, or we swap. Continue until a duplicate is found."""
for i in range(len(l1)):
if l1[i] == i: continue
elif l1[i] < 0 or l1[i] > len(l1)-1:
return None
elif l1[i] == l1[l1[i]]:
return True
else:
aux = l1[l1[i]]
l1[l1[i]] = l1[i]
l1[i] = aux
else:
return False
def test_find_duplicate_num_array():
a = [1,3,5,2,4,0]
b = [1,3,5,2,1,0,4]
c = [0,0]
assert(find_duplicate_num_array(b) == True)
assert(find_duplicate_num_array(a) == False)
assert(find_duplicate_num_array(c) == True)
print('Tests passed!')
if __name__ == '__main__':
test_find_duplicate_num_array()

View file

@ -0,0 +1,34 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
def find_edit_distance(str1, str2):
''' computes the edit distance between two strings '''
m = len(str1)
n = len(str2)
diff = lambda c1, c2: 0 if c1 == c2 else 1
E = [[0] * (n + 1) for i in range(m + 1)]
for i in range(m + 1):
E[i][0] = i
for j in range(1, n + 1):
E[0][j] = j
for i in range(1, m + 1):
for j in range(1, n + 1):
E[i][j] = min(E[i-1][j] + 1, E[i][j-1] + 1, E[i-1][j-1] + diff(str1[i-1], str2[j-1]))
return E[m][n]
def test_find_edit_distance():
s = 'sunday'
t = 'saturday'
assert(find_edit_distance(s, t) == 3)
print('Tests passed!')
if __name__ == '__main__':
test_find_edit_distance()

View file

@ -0,0 +1,30 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
''' find the first non-repetead char in a str.
---> we use a dict to count occurences
>>> find_non_rep_char("cut")
'c'
>>> s1 = 'google'
>>> find_non_rep_char(s1)
'l'
>>> find_non_rep_char('ccc')
>>> find_non_rep_char('')
'''
from collections import Counter
def find_non_rep_char(s1):
aux_dict = Counter()
for i in s1:
aux_dict[i] += 1
for i in s1:
if aux_dict[i] < 2: return i # remember it's <2
# not handling anything else: return None
if __name__ == '__main__':
import doctest
doctest.testmod()

View file

@ -0,0 +1,38 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
''' Find if a s2 is a substring of a s1
>>> s1 = 'buffy is a vampire slayer'
>>> s2 = 'vampire'
>>> s3 = 'angel'
>>> isSubstr(s1, s2)
True
>>> isSubstr(s1, s3)
False
>>> s4 = 'pirevam'
>>> find_substr(s2, s4)
True
>>> find_substr(s1, s4)
False
'''
def isSubstr(s1, s2):
if s1 in s2 or s2 in s1: return True
return False
def find_substr(s1, s2):
if s1 == '' or s2 == '': return True #empty str is always substr
for i, c in enumerate(s1):
if c == s2[0]:
test_s1 = s1[i:]+s1[:i]
return isSubstr(s2, test_s1)
return False
if __name__ == '__main__':
import doctest
doctest.testmod()

View file

@ -0,0 +1,41 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
def unique_char(s):
if len(s) > 256: return False
set_chars = set()
for i in s:
if i in set_chars:
return False
else:
set_chars.add(i)
return True
def unique_char_no_add(s):
if len(s) < 2: return True
for i, c in enumerate(s):
for j in s[i+1:]:
if j == c:
return False
return True
def main():
s1 = 'abcdefg'
s2 = 'buffy'
s3 = ''
print(unique_char(s1))
print(unique_char(s2))
print(unique_char(s3))
print(unique_char_no_add(s1) )
print(unique_char_no_add(s2))
print(unique_char_no_add(s3))
if __name__ == '__main__':
main()

View file

@ -0,0 +1,30 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
def find_long_con_inc(seq):
''' find the longest continuous increasing subsequence'''
one_seq = []
result = []
for i in range(0, len(seq)-1):
pivot = seq[i]
if pivot <= seq[i+1]:
one_seq.append(pivot)
else:
one_seq.append(pivot)
if len(one_seq) > len(result):
result = one_seq
one_seq = []
return result
def test_find_long_con_inc(module_name='this module'):
seq = [1, -2, 3, 5, 1, -1, 4, -1, 6]
long_con_inc = [-2,3,5]
assert(find_long_con_inc(seq) == long_con_inc )
if __name__ == '__main__':
test_find_long_con_inc()

View file

@ -0,0 +1,58 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
def find_majority_in_seq(seq):
''' find value which occurrence is greater than the total occurrence of all other elements '''
times = 1
result = seq[0]
for i in range(len(seq)):
if times == 0:
result = seq[i]
times = 1
elif seq[i] == result:
times +=1
else:
times -=1
if times == 0: return None
else:
count = 0
for i, c in enumerate(seq):
if c == result:
count += 1
return result, count
def test_find_majority_in_seq():
seq = [1, 1, 2, 3, 3, 3, 4, 4, 4, 4, 5, 6]
seq2 = [1, 2, 3]
assert(find_majority_in_seq(seq) == (4, 4))
assert(find_majority_in_seq(seq2) == None)
print('Tests passed!')
if __name__ == '__main__':
test_find_majority_in_seq()
"""
>>> A = [1, 2, 3, 2, 2, 4, 2, 5, 2]
>>> find_majority(A)
(2, 5)
>>> A = [1]
>>> find_majority(A)
(1, 1)
>>> A = [1, 2, 3, 2, 5, 6, 7]
>>> find_majority(A)
No Majority Element.
"""

View file

@ -0,0 +1,44 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
def find_max_profit_On(seq):
''' find the most profit from a seq with O(n) '''
max_profit = 0
min_value = seq[0]
for i in range(1, len(seq)):
profit_here = seq[i]- min_value
if profit_here > max_profit:
max_profit = profit_here
else:
if min_value > seq[i]:
min_value = seq[i]
return max_profit
def find_max_profit_On2(seq):
''' find the most profit from a seq with O(n2) '''
max_profit = 0
for i in range(len(seq)-1):
for j in range (i, len(seq)-1):
if seq[j] - seq[i] > max_profit:
max_profit = seq[j] - seq[i]
return max_profit
def test_find_max_profit():
seq = [9,11,5,7,16,1]
assert(find_max_profit_On(seq) == 11)
assert(find_max_profit_On2(seq) == 11)
seq = [1,15,2,3,4,3]
assert(find_max_profit_On(seq) == 14)
assert(find_max_profit_On2(seq) == 14)
print('Tests passed!')
if __name__ == '__main__':
test_find_max_profit()

View file

@ -0,0 +1,44 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
def find_max_subarray1(l1):
''' calculate the greatest sum of subarrays from an array.
An array with n elements has n(n+1)/2 subarrays so force brute cost O(n^2).
What we can do is to check when a sum becomes a negative number or zero, and then discard, since
this will not "add" anything to the new event... When the sum decreases, it gets the previous sum. '''
sum_new, result = 0, 0
for c in l1:
result = max(result, sum_new)
sum_new += c
if sum_new <= 0: sum_new = 0
return result
def find_max_subarray2(l1):
''' find the contiguous subarray which has the largest sum (Kadane's algorithm in O(n))
with extra O(n) space '''
sum_old = [l1[0]]
for c in l1:
sum_old.append(max(c, sum_old [-1] + c))
return max(sum_old)
def test_find_max_subarray():
l1 = [-2, 1, -3, 4, -1, 2, 1, -5, 4]
l2 = [-1, 3, -5, 4, 6, -1, 2, -7, 13, -3]
assert(find_max_subarray1(l1)) == 6)
assert(find_max_subarray1(l2)) == 17)
assert(find_max_subarray2(l1) == 6)
assert(find_max_subarray2(l2) == 17)
print('Tests passed!')
if __name__ == '__main__':
test_find_max_subarray()

View file

@ -0,0 +1,29 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
def find_palindrome_rec(s):
''' recursive way of checking whether a str is a palindrome '''
if len(s) > 1:
if s[0] != s[-1]: return False
else: find_palindrome_rec(s[1:-1])
return True
def test_find_palindrome_rec(module_name='this module'):
str1 = 'radar'
str2 = ""
str3 = 'x'
str4 = 'hello'
assert(find_palindrome_rec(str1) == True)
assert(find_palindrome_rec(str2) == True)
assert(find_palindrome_rec(str3) == True)
assert(find_palindrome_rec(str4) == False)
s = 'Tests in {name} have {con}!'
print(s.format(name=module_name, con='passed'))
if __name__ == '__main__':
test_find_palindrome_rec()

View file

@ -0,0 +1,33 @@
def find_product_without_division(seq):
'''Given an array of numbers, replace each number with the product of all the numbers in the array except the number itself *without* using division '''
forw = []
bacw = []
for i in range(len(seq)):
prod_f = 1
prod_b = 1
for next in range(i+1, len(seq)):
prod_f *= seq[next]
for before in range(0, i):
prod_b *= seq[before]
forw.append(prod_f)
bacw.append(prod_b)
print(bacw)
print(forw)
for i in range(len(seq)):
seq[i] = forw[i]*bacw[i]
return seq
def test_find_product_without_division():
seq = [2,3,4]
result = [12, 8, 6]
print(find_product_without_division(seq))
if __name__ == '__main__':
test_find_product_without_division()

View file

@ -0,0 +1,41 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
def find_subst_in_str(str1, set1):
sub_str1 = ''
found = False
while set1:
for c in str1:
if c in set1:
set1.remove(c)
found = True
if found == True:
sub_str1 += c
if len(set1) == 0: found = False
return sub_str1
def test_find_subst_in_str(module_name='this module'):
str1 = 'ydxahbcscdk'
set1 = {'a','b','c','d'}
result = 'dxahbc'
assert( find_subst_in_str(str1, set1)==result)
set2 = {'a','b','c'}
result2 = 'ahbc'
assert( find_subst_in_str(str1, set2)==result2)
s = 'Tests in {name} have {con}!'
print(s.format(name=module_name, con='passed'))
if __name__ == '__main__':
test_find_subst_in_str()

View file

@ -0,0 +1,55 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
import math
def find_two_missing_numbers(l1):
""" Two numbers out of n numbers from 1 to n are missing. The remaining n-2 numbers are in the
array but not sorted. Find the missing numbers The sum1 is the sum of all the elements in n. The
sum2 is the sum of all the elements in n-2. sum1 - sum2 = num1 + num2 = s. The prod1 is the prod of
all the elements in n. The prod2 is the prod of all the elements in n-2. prod1/prod2 = num1*num2 =
p. Runtime is O(n), because it scan 3 times. Space is O(1)
- In case of finding one integer, Let the missing number be M. We know that the sum of first N
natural numbers is N*(N+1)/2. Traverse through the array once and calculate the sum. This is the
sum of first N natural numbers M or S=N*(N+1)/2 M. Therefore M = N*(N+1)/2 S.
"""
n_min_2 = len(l1)
n = n_min_2 + 2
sum1, sum2, prod1, prod2 = 0,0,1,1
sum2 = sum(l1[:])
sum1 = sum(range(1,n+1))
s = sum1 - sum2
for i in range(1, n-1):
prod1 = prod1*i
prod2 = prod2*l1[i-1]
prod1 = prod1*n*(n-1)
p = prod1/prod2
num1 = (s + math.sqrt(s*s - 4*p))/2
num2 = (s - math.sqrt(s*s - 4*p))/2
return num1, num2
def test_find_two_missing_numbers():
l1 = [1, 3, 5]
result = find_two_missing_numbers(l1)
assert(result[0] == 2.0 or result[0] == 4.0)
print('Tests passed!')
if __name__ == '__main__':
test_find_two_missing_numbers()

View file

@ -0,0 +1,27 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
def greatest_sum_sub_array(l1):
sum_new = 0
results = []
for i, c in enumerate(l1):
sum_old = sum_new
sum_new = sum_old + c
if sum_new <= 0 or sum_new < sum_old:
sum_new = 0
results.append(sum_old)
continue
results.append(sum_new)
results.sort()
return results.pop()
def test_greatest_sum_sub_array():
l1 = [1, -4, 20, -4, 5, 15, 3]
assert(greatest_sum_sub_array(l1) == 23)
print('Tests passed!')
if __name__ == '__main__':
test_greatest_sum_sub_array()

View file

@ -0,0 +1,32 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
def longest_common_substring(str1, str2):
''' find the largest commom substring from 2 strings '''
m = [[0 for i in range(len(str2) + 1)] for k in range(len(str1) + 1)]
lcs = None
max_len = 0
for y in range(1, len(str1) + 1):
for x in range(1, len(str2) + 1):
m[y][x] = m[y - 1][x - 1] + 1 if (str1[y - 1] == str2[x - 1]) else 0
if m[y][x] > max_len:
max_len = m[y][x]
lcs = str1[(y - max_len):y]
return max_len, lcs
def test_longest_common_substring():
str1 = 'buffy is a vampire slayer'
str2 = 'aaas bampires vslay'
assert(longest_common_substring(str1, str2) == (6, 'ampire'))
print('Tests passed!')
if __name__ == '__main__':
test_longest_common_substring()

View file

@ -0,0 +1,38 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
def merge_two_sorted_arrays(a1, a2):
""" merge two sorted arrays, keeping the final sorted """
if len(a1) >= len(a2):
biga = a1
smalla = a2
else:
biga = a2
smalla = a1
final = []
count = 0
for i in range(len(biga)):
if count < len(smalla) and smalla[count] < biga[i]:
final.append(smalla[count])
count+=1
final.append(biga[i])
return final
def test_merge_two_sorted_arrays():
a1 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
a2 = [3, 6, 7]
assert(merge_two_sorted_arrays(a1, a2) == [0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 7, 8, 9, 10])
print('Tests passed!')
if __name__ == '__main__':
test_merge_two_sorted_arrays()

View file

@ -0,0 +1,24 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
''' give all the permutation of a str:
>>> str1 = 'hat'
>>> perm_str(str1)
['hat', 'hta', 'aht', 'ath', 'tha', 'tah']
>>> perm_str('')
''
'''
def perm_str(str1):
if len(str1) < 2: return str1
result = []
for i in range(len(str1)):
for perm in perm_str(str1[:i] + str1[i+1:]):
result.append(str1[i] + perm)
return result
if __name__ == '__main__':
import doctest
doctest.testmod()

View file

@ -0,0 +1,39 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
def print_all_seq_with_cont_num(s):
''' print all sequences with cont. numbers (2 at least) whose sum is a given s '''
if s < 3: return s
small = 1
big = 2
sum_here = big + small
result = []
while small < (1+s)/2:
sum_here = sum(range(small, big))
if sum_here < s:
big += 1
elif sum_here > s:
small +=1
else:
result.append(list(range(small, big)))
big += 1
return result
def test_print_all_seq_with_cont_num():
s = 15
sum_set_for_s = [[1,2,3,4,5], [4,5,6], [7,8]]
assert(print_all_seq_with_cont_num(s) == sum_set_for_s)
s = 1
assert(print_all_seq_with_cont_num(s)== 1)
s = 0
assert(print_all_seq_with_cont_num(s) == 0)
print('Tests passed!')
if __name__ == '__main__':
test_print_all_seq_with_cont_num()

View file

@ -0,0 +1,29 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
''' remove the chars in a list from a string
---> handle whitespaces!!!!
>>> remove_char_str('I love google', 'oe')
'I lv ggl'
>>> remove_char_str('google', '')
'google'
>>> remove_char_str('google', 'google')
''
'''
def remove_char_str(s1, charlist):
set_aux = set(charlist)
lt_aux = [] # we use list intead of concat. strs because it's more efficient
for c in s1:
if c not in set_aux:
lt_aux.append(c)
return ''.join(lt_aux) # IF NON CHARS, RETURN '' not NONE!
if __name__ == '__main__':
import doctest
doctest.testmod()

View file

@ -0,0 +1,37 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
def removing_duplicates_seq(seq):
''' if the values are hashable, we can use set and generators to remove duplicates
in a sequence '''
seen = set()
for item in seq:
if item not in seen:
yield item
seen.add(item)
def removing_duplicates_seq_not_hash(seq, key= None):
''' if the item is not hashable, such as dictionaries '''
seen = set()
for item in seq:
val = item if key is None else key[item]
if item not in seen:
yield item
seen.add(val)
def test_removing_duplicates_seq():
seq = [1, 2, 2, 2, 3, 3, 4, 4, 4]
dict = {'a':1, 'b':2, 'a':2, 'a':1}
assert(list(removing_duplicates_seq(seq)) == [1,2,3,4])
assert(list(removing_duplicates_seq_not_hash(dict)) == ['a', 'b'])
print('Tests passed!'.center(20, '*'))
if __name__ == '__main__':
test_removing_duplicates_seq()

View file

@ -0,0 +1,59 @@
#!/usr/bin/env python
author = "Mari Wahl"
email = "marina.w4hl@gmail.com"
# timeit is used for benchmarking.
from timeit import timeit
def reverse_1(string):
"""
Slowest function. Use a list and str.join to reverse the string.
:param string: the string to be reversed.
:return: a reversed string.
"""
reversed_string = []
# Iterates from the last to the first character.
for i in range(len(string) - 1, -1, -1):
# Appends the character to the list.
reversed_string.append(string[i])
return ''.join(reversed_string)
def reverse_2(string):
"""
Same principle as reverse_1. One-liner cousin.
:param string: the string to be reversed.
:return: a reversed string.
"""
return ''.join([character for character in [string[i] for i in range(len(string) - 1, -1, -1)]])
def reverse_3(string):
"""
Another one-liner. We make a list from the characters of the string and reverse it.
:param string: the string to be reversed.
:return: a reversed string.
"""
return ''.join([character for character in string][::-1])
# Overkill of elegance. A bit too passionate but it defines this lambda function well.
# Simply returns the string backwards. As fast as concise.
reverse_lambda = lambda s: s[::-1]
# We define some short strings to test our functions.
strings = ('buffy', 'foo', 'bar')
# We announce what we are doing.
print(', '.join(strings), ' should appear reversed if the function is working.\n')
print('{:<30}:'.format('Function name'), 'benchmarking result (lower is better):')
# Iterate over a tuple of functions.
for function in (reverse_1, reverse_2, reverse_3, reverse_lambda):
name = function.__name__ if function.__name__ != "<lambda>" else 'reverse_lambda'
# We print the function's name and its benchmark result.
print("{:<30}:".format(name), timeit(name + "('string')", setup='from __main__ import ' + name))
# We print the output so that we can check if the function is working as expected.
print(', '.join(map(function, strings)), '\n')
# We wait until the user wants to quit.
input('Press Return to quit.')

View file

@ -0,0 +1,35 @@
#!/usr/bin/env python
author = "Mari Wahl"
email = "marina.w4hl@gmail.com"
def reverse_string_inplace_rec(s):
''' takes a string and returns its reverse'''
if s:
s = s[-1] + reverse_string_inplace_rec(s[:-1])
return s
def reverse_string_inplace(s):
s = s[::-1]
if s[0] == '\0':
s = s[1:]
s += '\0'
return s
def test_reverse_string_inplace_rec(module_name='this module'):
s = 'hello'
s2 = 'buffy\0'
assert(reverse_string_inplace(s) == 'olleh')
assert(reverse_string_inplace(s2) == 'yffub\0')
assert(reverse_string_inplace_rec(s) == 'olleh')
s = 'Tests in {name} have {con}!'
print(s.format(name=module_name, con='passed'))
if __name__ == '__main__':
test_reverse_string_inplace_rec()

View file

@ -0,0 +1,117 @@
#!/usr/bin/env python
author = "Mari Wahl"
email = "marina.w4hl@gmail.com"
""" Here we want to invert the words in a string, without reverting
the words.
Important things to remember:
1. python strings are immutable
2. The last word doesn't not end by a space, so we need to make
sure we get the last word too
The solution consists of two loops,
1) revert all the characters with 2 pointers
2) search for spaces and revert the words, two pointers too
3) You can represent space as ' ' or as u'\u0020'
4) Do we want to look to ! ; , . etc?
In the solutions bellow, we show how to do this logic, and how to use
python's methods to do in a few lines
"""
# EXAMPLE NUMBER 1
def reverser(string1, p1=0, p2=None):
if len(string1) < 2:
return string1
p2 = p2 or len(string1)-1
while p1 < p2:
aux = string1[p1]
string1[p1] = string1[p2]
string1[p2] = aux
p1 += 1
p2 -= 1
def reversing_words_setence_logic(string1):
reverser(string1)
p = 0
start = 0
while p < len(string1):
if string1[p] == u"\u0020":
reverser(string1,start,p-1)
start = p+1
p += 1
reverser(string1,start,p-1)
return "".join(string1)
# EXAMPLE NUMBER 2 AND 3 USING PYTHON AWESOMESAUCE
def reversing_words_setence_py(str1):
''' reverse the words in a sentence'''
words = str1.split()
rev_set = " ".join(reversed(words))
return rev_set
def reversing_words_setence_py2(str1):
"""
Reverse the order of the words in a sentence.
:param string: the string which words wilL be reversed.
:return: the reversed string.
"""
words = str1.split(' ')
words.reverse()
return ' '.join(words)
# EXAMPLE 4, VERY SILLY, USING BRUTE FORCE
#
def reverse_words_brute(string):
"""
Reverse the order of the words in a sentence.
:param string: the string which words wil lbe reversed.
:return: the reversed string.
"""
word, sentence = [], []
for character in string:
if character != ' ':
word.append(character)
else:
# So we do not keep multiple whitespaces. An empty list evaluates to False.
if word:
sentence.append(''.join(word))
word = []
# So we do not keep multiple whitespaces. An empty list evaluates to False.
if word != '':
sentence.append(''.join(word))
sentence.reverse()
return ' '.join(sentence)
# TESTS
def test_reversing_words_sentence():
str1 = "Buffy is a Vampire Slayer"
assert(reversing_words_setence_py(str1) == "Slayer Vampire a is Buffy")
assert(reversing_words_setence_py2(str1) == "Slayer Vampire a is Buffy")
assert(reverse_words_brute(str1) == "Slayer Vampire a is Buffy")
assert(reversing_words_setence_logic(list(str1)) == "Slayer Vampire a is Buffy")
print("Tests passed!")
if __name__ == '__main__':
test_reversing_words_sentence()

View file

@ -0,0 +1,31 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
def rotate_NxN(m):
n = len(m)
for layer in range(n//2):
first = layer
last = n - 1 - layer
for i in range(first, last):
offset = i - first
top = m[first][i]
m[first][i] = m[last-offset][first]
m[last-offset][first] = m[last][last-offset]
m[last][last-offset] = m[i][last]
m[i][last] = top
return m
def main():
m = [[1,2],[3,4]]
mr = [[3,1],[4,2]]
assert(rotate_NxN(m) == mr)
m2 = [[1,2,3],[4,5,6],[7,8,9]]
print(rotate_NxN(m2))
if __name__ == '__main__':
main()

View file

@ -0,0 +1,67 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
'''To use timeit you create a Timer object whose parameters are two Python statements. The first parameter is a Python statement that you want to time; the second parameter is a statement that will run once to set up the test. The timeit module will then time how long it takes to execute the statement some number of times. By default timeit will try to run the statement one million times. When its done it returns the time as a floating point value representing the total number of seconds. However, since it executes the statement a million times you can read the result as the number of microseconds to execute the test one time. You can also pass timeit a named parameter called number that allows you to specify how many times the test statement is executed. The following session shows how long it takes to run each of our test functions 1000 times. '''
def test1():
l = []
for i in range(1000):
l = l + [i]
def test2():
l = []
for i in range(1000):
l.append(i)
def test3():
l = [i for i in range(1000)]
def test4():
l = list(range(1000))
if __name__ == '__main__':
import timeit
t1 = timeit.Timer("test1()", "from __main__ import test1")
print("concat ",t1.timeit(number=1000), "milliseconds")
t2 = timeit.Timer("test2()", "from __main__ import test2")
print("append ",t2.timeit(number=1000), "milliseconds")
t3 = timeit.Timer("test3()", "from __main__ import test3")
print("comprehension ",t3.timeit(number=1000), "milliseconds")
t4 = timeit.Timer("test4()", "from __main__ import test4")
print("list range ",t4.timeit(number=1000), "milliseconds")
""" The results are:
('concat ', 2.366791009902954, 'milliseconds')
('append ', 0.16743111610412598, 'milliseconds')
('comprehension ', 0.06446194648742676, 'milliseconds')
('list range ', 0.021029949188232422, 'milliseconds')
So we see the following pattern for lists:
Operation Big-O Efficiency
index [] O(1)
index assignment O(1)
append O(1)
pop() O(1)
pop(i) O(n)
insert(i,item) O(n)
del operator O(n)
iteration O(n)
contains (in) O(n)
get slice [x:y] O(k)
del slice O(n)
set slice O(n+k)
reverse O(n)
concatenate O(k)
sort O(n log n)
multiply O(nk)
"""

View file

@ -0,0 +1,32 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
from collections import Counter
def str_comp(s):
''' basic str compression with counts of repeated char'''
count, last = 1, ''
list_aux = []
for i, c in enumerate(s):
if last == c:
count += 1
else:
if i != 0:
list_aux.append(str(count))
list_aux.append(c)
count = 1
last = c
list_aux.append(str(count))
return ''.join(list_aux)
def main():
s1 = 'aabcccccaaa'
s2 = ''
print(str_comp(s1)) # 'a2b1c5a3'
print(str_comp(s2))
if __name__ == '__main__':
main()

View file

@ -0,0 +1,36 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
def sum_two_numbers_sequence(seq, s):
""" given an increasing sorted array and an integer s, find if there is a pair of two numbers in the array whose sum is s. It takes O(n). """
l1 = seq[:]
l2 = seq[:]
l2.reverse()
n1 = l1.pop()
n2 = l2.pop()
while l2 and l1:
sum_here = n1 + n2
if sum_here > s:
n1 = l1.pop()
elif sum_here < s:
n2 = l2.pop()
else:
return True
return False
def test_sum_two_numbers_sequence():
l1 = [1,2,3,4,5,6,7,8]
s = 7
assert(sum_two_numbers_sequence(l1, s) == True)
print('Tests passed!')
if __name__ == '__main__':
test_sum_two_numbers_sequence()

View file

@ -0,0 +1,49 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
def ver_perm(s1, s2):
''' worst case O(nlogn + mlogm) = O(NlogN) '''
if len(s1) != len(s2): return False
s1 = sorted(s1)
s2 = sorted(s2)
return s1 == s2
from collections import Counter
def ver_perm_dict(s1, s2):
''' worst case O(n + n +2n) = O(n)'''
if len(s1) != len(s2): return False
dict_aux = Counter()
for c in s1:
dict_aux[c] += 1
for c in s2:
dict_aux[c] -= 1
for item in dict_aux:
if dict_aux[item]:
return False
return True
import time
def main():
s1 = 'ufyfbufyfb'
s2 = 'buffybuffy'
s3 = 'uuyfbuuyfb'
s4 = ''
start = time.time()
print(ver_perm(s1, s2))
print(ver_perm(s1, s3))
print(ver_perm(s1, s4))
final1 = time.time() - start
start = time.time()
print(ver_perm_dict(s1, s2))
print(ver_perm_dict(s1, s3))
print(ver_perm_dict(s1, s4))
final2 = time.time() - start
print(final2-final1)
if __name__ == '__main__':
main()

View file

@ -0,0 +1,27 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
def convert_dec_to_any_base_rec(number, base):
''' convert an integer to a string in any base'''
convertString = '012345679ABCDEF'
if number < base: return convertString[number]
else:
return convert_dec_to_any_base_rec(number//base, base) + convertString[number%base]
def test_convert_dec_to_any_base_rec(module_name='this module'):
number = 9
base = 2
assert(convert_dec_to_any_base_rec(number, base) == '1001')
s = 'Tests in {name} have {con}!'
print(s.format(name=module_name, con='passed'))
if __name__ == '__main__':
test_convert_dec_to_any_base_rec()

View file

@ -0,0 +1,24 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
def convert_from_decimal(number, base):
''' convert any decimal number to another base. '''
multiplier, result = 1, 0
while number > 0:
result += number%base*multiplier
multiplier *= 10
number = number//base
return result
def test_convert_from_decimal():
number, base = 9, 2
assert(convert_from_decimal(number, base) == 1001)
print('Tests passed!')
if __name__ == '__main__':
test_convert_from_decimal()

View file

@ -0,0 +1,24 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
def convert_from_decimal_larger_bases(number, base):
''' convert any decimal number to a number in a base up to 20'''
strings = "0123456789ABCDEFGHIJ"
result = ""
while number > 0:
digit = number%base
result = strings[digit] + result
number = number//base
return result
def test_convert_from_decimal_larger_bases():
number, base = 31, 16
assert(convert_from_decimal_larger_bases(number, base) == '1F')
print('Tests passed!')
if __name__ == '__main__':
test_convert_from_decimal_larger_bases()

View file

@ -0,0 +1,25 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
def convert_to_decimal(number, base):
''' convert any number in another base to the decimal base'''
multiplier, result = 1, 0
while number > 0:
result += number%10*multiplier
multiplier *= base
number = number//10
return result
def test_convert_to_decimal():
number, base = 1001, 2
assert(convert_to_decimal(number, base) == 9)
print('Tests passed!')
if __name__ == '__main__':
test_convert_to_decimal()

View file

@ -0,0 +1,44 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
import math
def find_fibonacci_seq_rec(n):
''' implements the nth fibonacci value in a recursive exponential runtime '''
if n < 2: return n
return find_fibonacci_seq_rec(n - 1) + find_fibonacci_seq_rec(n - 2)
def find_fibonacci_seq_iter(n):
''' return the nth fibonacci value in a iterative O(n^2) runtime '''
if n < 2: return n
a, b = 0, 1
for i in range(n):
a, b = b, a + b
return a
def find_fibonacci_seq_form(n):
''' return the nth fibonacci value implemented by the formula, nearly constant-time algorithm,
but, it has a poor precise (after 72 it starts to become wrong) '''
sq5 = math.sqrt(5)
phi = (1 + sq5) / 2
return int(math.floor(phi ** n / sq5))
def test_find_fib():
n = 10
assert(find_fibonacci_seq_rec(n) == 55)
assert(find_fibonacci_seq_iter(n) == 55)
assert(find_fibonacci_seq_form(n) == 55)
print('Tests passed!')
if __name__ == '__main__':
test_find_fib()

View file

@ -0,0 +1,28 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
def finding_gcd(a, b):
''' implements the greatest common divider algorithm '''
while(b != 0):
result = b
a, b = b, a % b
return result
def test_finding_gcd():
number1 = 21
number2 = 12
assert(finding_gcd(number1, number2) == 3)
print('Tests passed!')
if __name__ == '__main__':
test_finding_gcd()

View file

@ -0,0 +1,59 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
import math
import random
def finding_prime(number):
''' find whether a number is prime in a simple way'''
num = abs(number)
if num < 4 : return True
for x in range(2, num):
if num % x == 0:
return False
return True
def finding_prime_sqrt(number):
''' find whether a number is prime as soon as it rejects all candidates up to sqrt(n) '''
num = abs(number)
if num < 4 : return True
for x in range(2, int(math.sqrt(num)) + 1):
if number % x == 0:
return False
return True
def finding_prime_fermat(number):
''' find whether a number is prime with Fermat's theorem, using probabilistic tests '''
if number <= 102:
for a in range(2, number):
if pow(a, number- 1, number) != 1:
return False
return True
else:
for i in range(100):
a = random.randint(2, number - 1)
if pow(a, number - 1, number) != 1:
return False
return True
def test_finding_prime():
number1 = 17
number2 = 20
assert(finding_prime(number1) == True)
assert(finding_prime(number2) == False)
assert(finding_prime_sqrt(number1) == True)
assert(finding_prime_sqrt(number2) == False)
assert(finding_prime_fermat(number1) == True)
assert(finding_prime_fermat(number2) == False)
print('Tests passed!')
if __name__ == '__main__':
test_finding_prime()

View file

@ -0,0 +1,35 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
import math
import random
import sys
from finding_prime import finding_prime_sqrt
def generate_prime(number=3):
''' return a n-bit prime '''
while 1:
p = random.randint(pow(2, number-2), pow(2, number-1)-1)
p = 2 * p + 1
if finding_prime_sqrt(p):
return p
if __name__ == '__main__':
if len(sys.argv) < 2:
print ("Usage: generate_prime.py number")
sys.exit()
else:
number = int(sys.argv[1])
print(generate_prime(number))

View file

@ -0,0 +1,40 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
def find_elem_matrix_bool(m1, value):
''' Search an Entry in a Matrix where the Rows and columns are Sorted
In this 2D matrix, every row is increasingly sorted from left to right,
and every column is increasingly sorted from top to bottom.
The runtime is O(m+n). '''
found = False
row = 0
col = len(m1[0]) - 1
while row < len(m1) and col >= 0:
if m1[row][col] == value:
found = True
break
elif m1[row][col] > value:
col-=1
else:
row+=1
return found
def test_find_elem_matrix_bool(module_name='this module'):
m1 = [[1,2,8,9], [2,4,9,12], [4,7,10,13], [6,8,11,15]]
assert(find_elem_matrix_bool(m1,8) == True)
assert(find_elem_matrix_bool(m1,3) == False)
m2 = [[0]]
assert(find_elem_matrix_bool(m2,0) == True)
s = 'Tests in {name} have {con}!'
print(s.format(name=module_name, con='passed'))
if __name__ == '__main__':
test_find_elem_matrix_bool()

View file

@ -0,0 +1,45 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
from fractions import Fraction
def rounding_floats(number1, places):
''' some operations with float()'''
return round(number1, places)
def float_to_fractions(number):
return Fraction(*number.as_integer_ratio())
def get_denominator(number1, number2):
a = Fraction(number1, number2)
return a.denominator
def get_numerator(number1, number2):
a = Fraction(number1, number2)
return a.numerator
def test_testing_floats(module_name='this module'):
number1 = 1.25
number2 = 1
number3 = -1
number4 = 5/4
number6 = 6
assert(rounding_floats(number1, number2) == 1.2)
assert(rounding_floats(number1*10, number3) == 10)
assert(float_to_fractions(number1) == number4)
assert(get_denominator(number2, number6) == number6)
assert(get_numerator(number2, number6) == number2)
s = 'Tests in {name} have {con}!'
print(s.format(name=module_name, con='passed'))
if __name__ == '__main__':
test_testing_floats()

View file

@ -0,0 +1,32 @@
#!/usr/bin/python
# mari von steinkirch @2013
# steinkirch at gmail
import numpy as np
def testing_numpy():
''' tests many features of numpy '''
ax = np.array([1,2,3])
ay = np.array([3,4,5])
print(ax)
print(ax*2)
print(ax+10)
print(np.sqrt(ax))
print(np.cos(ax))
print(ax-ay)
print(np.where(ax<2, ax, 10))
m = np.matrix([ax, ay, ax])
print(m)
print(m.T)
grid1 = np.zeros(shape=(10,10), dtype=float)
grid2 = np.ones(shape=(10,10), dtype=float)
print(grid1)
print(grid2)
print(grid1[1]+10)
print(grid2[:,2]*2)
if __name__ == '__main__':
testing_numpy()

View file

@ -0,0 +1,32 @@
#!/usr/bin/python
# mari von steinkirch @2013
# steinkirch at gmail
import numpy
import time
def trad_version():
t1 = time.time()
X = range(10000000)
Y = range(10000000)
Z = []
for i in range(len(X)):
Z.append(X[i] + Y[i])
return time.time() - t1
def numpy_version():
t1 = time.time()
X = numpy.arange(10000000)
Y = numpy.arange(10000000)
Z = X + Y
return time.time() - t1
if __name__ == '__main__':
print(trad_version())
print(numpy_version())
'''
3.23564291
0.0714290142059
'''

View file

@ -0,0 +1,27 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
import random
def testing_random():
''' testing the module random'''
values = [1, 2, 3, 4]
print(random.choice(values))
print(random.choice(values))
print(random.choice(values))
print(random.sample(values, 2))
print(random.sample(values, 3))
''' shuffle in place '''
random.shuffle(values)
print(values)
''' create random integers '''
print(random.randint(0,10))
print(random.randint(0,10))
if __name__ == '__main__':
testing_random()

View file

View file

@ -0,0 +1,32 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
''' Example of how to use a bit array in python as a "counter" dict:
>>> l1 = [0, 1, 2, 3, 4, 2, 6, 7, 8, 9]
>>> print_dupl_ba(l1)
2
'''
def print_dupl_ba(l1):
bs = bytearray(10)
for i in range(len(l1)):
if i == l1[i]:
bs[i] = 1
for index, bit in enumerate(bs):
if bit == 0:
return l1[index]
return None
if __name__ == '__main__':
import doctest
doctest.testmod()

View file

@ -0,0 +1,40 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
''' Clear a bit in a binary number. It is almost like the reverse of set bit:
1) first create a number filled of 1s, with 0 at i (can create 0001000 and ~)
2) AND the number so it clears the ith bit
>>> num = int('10010000', 2)
>>> clear_bit(num, 4)
'0b10000000'
>>> num = int('10010011', 2)
>>> clear_all_bits_from_i_to_0(num, 2)
'0b10010000'
>>> num = int('1110011', 2)
>>> clear_all_bits_from_most_sig_to_1(num, 2)
'0b11'
'''
def clear_bit(num, i):
mask = ~ (1 << i) # -0b10001
return bin(num & mask)
def clear_all_bits_from_i_to_0(num, i):
mask = ~ ( (1 << (i+1)) - 1)
return bin(num & mask)
def clear_all_bits_from_most_sig_to_1(num, i):
mask = ( 1 << i) -1
return bin(num & mask)
if __name__ == '__main__':
import doctest
doctest.testmod()

View file

@ -0,0 +1,28 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
''' Find how many bits a int has:
1) Start with a mask of 1
2) Mask with AND
3) if result (if true): count += 1
(obs: to find the int of a bin do int('1001', 2)) and to show in bin do bin(int))
>>> for i in range(17): print(find_bit_len(i))
'''
def find_bit_len(int_num):
lenght = 0
while int_num:
int_num >>= 1
lenght += 1
return lenght
if __name__ == '__main__':
import doctest
doctest.testmod()

View file

@ -0,0 +1,34 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
''' Find how many 1s in the binary:
1) Start with a mask of 1
2) Mask with AND
3) if result (if true): count += 1
(obs: to find the int of a bin do int('1001', 2)) and to show in bin do bin(int))
>>> find_how_many_1_in_a_binary(9)
2
'''
def find_how_many_1_in_a_binary(n):
counter = 0
while n:
if n & 1:
counter += 1
n >>= 1
return counter
if __name__ == '__main__':
import doctest
doctest.testmod()

View file

@ -0,0 +1,41 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
''' Get a bit in a binary number:
1) Shifts 1 over by i bits
2) make an AND with the number
3) all the other than the bit at i are clean, now compare to 0
4) if the new value is not 0, bit i is 1
>>> num = int('0100100', 2)
>>> get_bit(num, 0)
0
>>> get_bit(num, 1)
0
>>> get_bit(num, 2)
1
>>> get_bit(num, 3)
0
>>> get_bit(num, 4)
0
>>> get_bit(num, 5)
1
>>> get_bit(num, 6)
0
'''
def get_bit(num, i):
mask = 1 << i
return num & mask != 0
if __name__ == '__main__':
import doctest
doctest.testmod()

View file

@ -0,0 +1,35 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
''' Given a real number between 0 and 1 (eg: 0.72), this method print the binary
representation. If the Number cannot be represented accurately in binary, with at
most 32 chars, print error:
>>> get_float_rep(0.72)
('Error 2', '.1011100001010001111010111000010')
>>> get_float_rep(0.1)
('Error 2', '.0001100110011001100110011001100')
>>> get_float_rep(0.5)
'.1'
'''
def get_float_rep(num):
if num >= 1 or num <= 0: return 'Error 1'
result = '.'
while num:
if len(result) >= 32: return 'Error 2', result
r = num*2
if r >= 1:
result += '1'
num = r - 1
else:
result += '0'
num = r
return result
if __name__ == '__main__':
import doctest
doctest.testmod()

View file

@ -0,0 +1,35 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
''' Given two 32-bit numbers, N and M, and two bit positions, i and j, this
method insert M into N such that M starts at bit j and ends at bit i:
1) clear the bits j thru i in N'
2) shift M so that it lines up with bits j thru i
3) merge M and N
>>> N = 0b10000000000
>>> M = 0b10011
>>> j = 6
>>> i = 2
>>> insert_small_bin_into_big_bin(M, N, i, j)
'0b10001001100'
'''
def insert_small_bin_into_big_bin(M, N, i, j):
allOnes = ~0
left = allOnes << (j+1) # 1110000
right = ( (1 << i) - 1) # 0000111
mask = left | right # 1110111
N_cleared = N & mask
M_shifted = M << i
return bin( N_cleared | M_shifted)
if __name__ == '__main__':
import doctest
doctest.testmod()

View file

@ -0,0 +1,64 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
''' Give a positive int, print the next smallest and next largest ints with
same number of 1 bits.
The brute force is:
1) find number of 1 bits
2) loop above and down until find same, checking for each
>>> num = 0b1001
>>> next = '0b1010'
>>> prev = '0b110'
>>> print_prev_same_1s(num) == prev
True
>>> print_next_same_1s(num) == next
True
'''
def print_prev_same_1s(num):
n1s = find_num_1s(num)
# find prev
i = num-1
while True:
n1s_here = find_num_1s(i)
if n1s_here == n1s:
return bin(i)
i -= 1
if i < 0:
return None
def print_next_same_1s(num):
n1s = find_num_1s(num)
# find next
i = num+1
while True:
n1s_here = find_num_1s(i)
if n1s_here == n1s:
return bin(i)
i += 1
if i < 0:
return None
def find_num_1s(num):
counter = 0
while num:
if num & 1:
counter += 1
num >>= 1
return counter
if __name__ == '__main__':
import doctest
doctest.testmod()

View file

@ -0,0 +1,45 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
''' This method returns the number of bits that are necessary to change to convert two
numbers A and B:
1) XOR
2) count 1s
>>> a = int('10010000', 2)
>>> b = int('01011010', 2)
>>> count_bits_swap(a, b)
4
>>> count_bits_swap2(a, b)
4
'''
def count_bits_swap2(a, b):
count = 0
m = a^b
while m:
count +=1
m = m & (m-1)
return count
def count_bits_swap(a, b):
m = a^b
return count_1s(m)
def count_1s(m):
count = 0
while m:
if m& 1 :
count +=1
m >>= 1
return count
if __name__ == '__main__':
import doctest
doctest.testmod()

View file

@ -0,0 +1,38 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
''' Set a bit in a binary number:
1) Shifts 1 over by i bits
2) make an OR with the number, only the value at bit i will change and all the others bit
of the mask are zero so will not affect the num
>>> num = int('0100100', 2)
>>> set_bit(num, 0)
'0b100101'
>>> set_bit(num, 1)
'0b100110'
>>> set_bit(num, 2) # nothing change
'0b100100'
>>> set_bit(num, 3)
'0b101100'
>>> set_bit(num, 4)
'0b110100'
>>> set_bit(num, 5) # nothing change
'0b100100'
'''
def set_bit(num, i):
mask = 1 << i
return bin( num | mask )
if __name__ == '__main__':
import doctest
doctest.testmod()

View file

@ -0,0 +1,38 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
''' Swap odd and even bits in a smart way in a binary:
1) first for odds, take n and move the odd:
(a) Mask all odd bits with 10101010 (0xAA)
(b) shift by right by 1
2) do the same to ints with 01010101
3) merge
>>> num = 0b11011101
>>> result = '0b1101110'
>>> swap_odd_even(num) == result
True
'''
def swap_odd_even(num):
mask_odd = 0xAA # 0b10101010
mask_even = 0x55 # 0b1010101
odd = num & mask_odd
odd >>= 1
even = num & mask_even
even >>= 1
return bin(odd | even)
if __name__ == '__main__':
import doctest
doctest.testmod()

View file

@ -0,0 +1,26 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
''' This method merges set bit and clean bit:
1) first clear the bit at i using a mask such as 1110111
2) then shift the intended value v by i bits
3) this will create a number with bit i to v and all other to 0
4) finally update the ith bit with or
>>> num = int('10010000', 2)
>>> update_bit(num, 2, 1)
'0b10010100'
'''
def update_bit(num, i, v):
mask = ~ (1 << i)
return bin( (num & mask) | (v << i) )
if __name__ == '__main__':
import doctest
doctest.testmod()

View file

@ -0,0 +1,37 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
def removing_duplicates_seq(seq):
''' if the values are hashable, we can use set and generators to remove duplicates
in a sequence '''
seen = set()
for item in seq:
if item not in seen:
yield item
seen.add(item)
def removing_duplicates_seq_not_hash(seq, key= None):
''' if the item is not hashable, such as dictionaries '''
seen = set()
for item in seq:
val = item if key is None else key[item]
if item not in seen:
yield item
seen.add(val)
def test_removing_duplicates_seq():
seq = [1, 2, 2, 2, 3, 3, 4, 4, 4]
dict = {'a':1, 'b':2, 'a':2, 'a':1}
assert(list(removing_duplicates_seq(seq)) == [1,2,3,4])
assert(list(removing_duplicates_seq_not_hash(dict)) == ['a', 'b'])
print('Tests passed!'.center(20, '*'))
if __name__ == '__main__':
test_removing_duplicates_seq()

View file

@ -0,0 +1,39 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
from collections import OrderedDict
def set_operations_with_dict():
''' find common in 2 dictionaries '''
''' values() do not support set operations!'''
pairs = [('a', 1), ('b',2), ('c',3)]
d1 = OrderedDict(pairs)
print(d1) # ('a', 1), ('b', 2), ('c', 3)
d2 = {'a':1, 'c':2, 'd':3, 'e':4}
print(d2) # {'a': 1, 'c': 2, 'e': 4, 'd': 3}
union = d1.keys() & d2.keys()
print(union) # {'a', 'c'}
union_items = d1.items() & d2.items()
print(union_items) # {('a', 1)}
subtraction1 = d1.keys() - d2.keys()
print(subtraction1) # {'b'}
subtraction2 = d2.keys() - d1.keys()
print(subtraction2) # {'d', 'e'}
subtraction_items = d1.items() - d2.items()
print(subtraction_items) # {('b', 2), ('c', 3)}
''' we can remove keys from a dict doing: '''
d3 = {key:d2[key] for key in d2.keys() - {'c', 'd'}}
print(d3) {'a': 1, 'e': 4}
if __name__ == '__main__':
set_operations_with_dict()

View file

@ -0,0 +1,39 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
from collections import OrderedDict
def set_operations_with_dict():
''' find common in 2 dictionaries '''
''' values() do not support set operations!'''
pairs = [('a', 1), ('b',2), ('c',3)]
d1 = OrderedDict(pairs)
print(d1) # ('a', 1), ('b', 2), ('c', 3)
d2 = {'a':1, 'c':2, 'd':3, 'e':4}
print(d2) # {'a': 1, 'c': 2, 'e': 4, 'd': 3}
union = d1.keys() & d2.keys()
print(union) # {'a', 'c'}
union_items = d1.items() & d2.items()
print(union_items) # {('a', 1)}
subtraction1 = d1.keys() - d2.keys()
print(subtraction1) # {'b'}
subtraction2 = d2.keys() - d1.keys()
print(subtraction2) # {'d', 'e'}
subtraction_items = d1.items() - d2.items()
print(subtraction_items) # {('b', 2), ('c', 3)}
''' we can remove keys from a dict doing: '''
d3 = {key:d2[key] for key in d2.keys() - {'c', 'd'}}
print(d3) {'a': 1, 'e': 4}
if __name__ == '__main__':
set_operations_with_dict()

View file

@ -0,0 +1,37 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
def difference(l1):
""" return the list with duplicate elements removed """
return list(set(l1))
def intersection(l1, l2):
""" return the intersection of two lists """
return list(set(l1) & set(l2))
def union(l1, l2):
""" return the union of two lists """
return list(set(l1) | set(l2))
def test_sets_operations_with_lists():
l1 = [1,2,3,4,5,9,11,15]
l2 = [4,5,6,7,8]
l3 = []
assert(difference(l1) == [1, 2, 3, 4, 5, 9, 11, 15])
assert(difference(l2) == [8, 4, 5, 6, 7])
assert(intersection(l1, l2) == [4,5])
assert(union(l1, l2) == [1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 15])
assert(difference(l3) == [])
assert(intersection(l3, l2) == l3)
assert(sorted(union(l3, l2)) == sorted(l2))
print('Tests passed!')
if __name__ == '__main__':
test_sets_operations_with_lists()

View file

@ -0,0 +1,17 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
from collections import namedtuple
def namedtuple_example():
''' show some examples for namedtuple '''
sunnydale = namedtuple('name', ['job', 'age'])
buffy = sunnydale('slayer', '17')
print(buffy.job)
if __name__ == '__main__':
namedtuple_example()