mirror of
https://github.com/autistic-symposium/master-algorithms-py.git
synced 2025-12-14 07:48:58 -05:00
initial and final commit
This commit is contained in:
parent
4061fa6df1
commit
227a0efc0e
272 changed files with 11976 additions and 4 deletions
|
|
@ -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()
|
||||
|
||||
|
|
@ -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()
|
||||
|
||||
|
|
@ -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()
|
||||
|
||||
|
|
@ -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()
|
||||
|
||||
|
|
@ -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()
|
||||
|
||||
|
|
@ -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()
|
||||
|
||||
|
|
@ -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()
|
||||
|
||||
|
|
@ -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()
|
||||
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
#!/usr/bin/python3
|
||||
# mari von steinkirch @2013
|
||||
# steinkirch at gmail
|
||||
|
||||
|
||||
def reverse_str(s):
|
||||
''' in place '''
|
||||
sr_ls = []
|
||||
for i in range(len(s)-1, -1, -1):
|
||||
sr_ls.append(s[i])
|
||||
return ''.join(sr_ls)
|
||||
|
||||
|
||||
|
||||
|
||||
def main():
|
||||
s1 = 'abcdefg'
|
||||
s2 = 'buffy'
|
||||
s3 = ''
|
||||
print(reverse_str(s1))
|
||||
print(reverse_str(s2))
|
||||
print(reverse_str(s3))
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
#!/usr/bin/python3
|
||||
# mari von steinkirch @2013
|
||||
# steinkirch at gmail
|
||||
|
||||
''' reverse words in a setence, keeping the words right
|
||||
>>> str1 = 'I love Google and Python!'
|
||||
>>> reverse_words(str1)
|
||||
'Python! and Google love I'
|
||||
>>> reverse_words('bla')
|
||||
'bla'
|
||||
>>> reverse_words('')
|
||||
''
|
||||
>>> reverse_words_brute(str1)
|
||||
'Python! and Google love I'
|
||||
>>> reverse_words_brute('bla')
|
||||
'bla'
|
||||
>>> reverse_words_brute('')
|
||||
''
|
||||
'''
|
||||
|
||||
def reverse_words(str1):
|
||||
l1 = str1.split(' ')
|
||||
l1.reverse()
|
||||
return ' '.join(l1)
|
||||
|
||||
def reverse_words_brute(str1):
|
||||
aux_lt = []
|
||||
aux_str = ''
|
||||
for i, c in enumerate(str1):
|
||||
if c != ' ':
|
||||
aux_str += c # WE COULD HAVE USED LT HERE, MORE EFFICIENT
|
||||
elif c == ' ':
|
||||
aux_lt.append(aux_str) # WE COULD HAVE USED STR BUT NOT EFFICIENT!
|
||||
aux_str = ''
|
||||
aux_lt.append(aux_str) # REMEMBER THAT THE LAST ONE DOEN'T HAVE SPACE!
|
||||
aux_lt.reverse()
|
||||
return ' '.join(aux_lt)
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import doctest
|
||||
doctest.testmod()
|
||||
|
||||
|
|
@ -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()
|
||||
|
||||
|
|
@ -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()
|
||||
|
||||
|
|
@ -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()
|
||||
|
||||
|
|
@ -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()
|
||||
|
||||
|
|
@ -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()
|
||||
|
||||
|
|
@ -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()
|
||||
|
||||
|
|
@ -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()
|
||||
|
||||
|
|
@ -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()
|
||||
|
||||
|
|
@ -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()
|
||||
|
||||
|
|
@ -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()
|
||||
|
||||
|
|
@ -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()
|
||||
|
||||
|
|
@ -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()
|
||||
|
||||
|
|
@ -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()
|
||||
|
||||
|
|
@ -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()
|
||||
|
||||
|
|
@ -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()
|
||||
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
#!/usr/bin/python3
|
||||
# mari von steinkirch @2013
|
||||
# steinkirch at gmail
|
||||
|
||||
''' Given a linked list, check if the nodes form a palindrome '''
|
||||
|
||||
from linked_list_fifo import LinkList, Node
|
||||
|
||||
def isPal(l1):
|
||||
if len(l1) < 2: return True
|
||||
if l1[0] != l1[-1]: return False
|
||||
return isPal(l1[1:-1])
|
||||
|
||||
|
||||
|
||||
def checkllPal(ll):
|
||||
node = ll.head
|
||||
l1 = []
|
||||
while node:
|
||||
l1.append(node.value)
|
||||
node = node.next
|
||||
return isPal(l1)
|
||||
|
||||
|
||||
|
||||
def main():
|
||||
ll = LinkList()
|
||||
l1 = [1, 2, 3, 2, 1]
|
||||
for i in l1:
|
||||
ll.addNode(i)
|
||||
print(checkllPal(ll))
|
||||
|
||||
ll.addNode(2)
|
||||
ll.addNode(3)
|
||||
print(checkllPal(ll))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
#!/usr/bin/python3
|
||||
# mari von steinkirch @2013
|
||||
# steinkirch at gmail
|
||||
|
||||
|
||||
''' Build a class for a circular linked list and implement a function to see whether
|
||||
a linked list is circular'''
|
||||
|
||||
from linked_list_fifo import Node, LinkList
|
||||
|
||||
class Node(object):
|
||||
def __init__(self, value = None, next = None):
|
||||
self.value = value
|
||||
self.next = next
|
||||
|
||||
|
||||
class CircLinkList(object):
|
||||
def __init__(self):
|
||||
self.head = None
|
||||
self.tail = None
|
||||
self.lenght = 0
|
||||
|
||||
def addNode(self, value):
|
||||
node = Node(value, self.head)
|
||||
if not self.head:
|
||||
self.head = node
|
||||
if self.tail:
|
||||
self.tail.next = node
|
||||
self.tail = node
|
||||
self.lenght += 1
|
||||
|
||||
def printList(self):
|
||||
size = self.lenght
|
||||
node = self.head
|
||||
i = 0
|
||||
while i < size:
|
||||
print(node.value)
|
||||
node = node.next
|
||||
i += 1
|
||||
|
||||
|
||||
|
||||
def isCircularll(ll):
|
||||
p1 = ll.head
|
||||
p2 = ll.head
|
||||
|
||||
while p2 and p2.next:
|
||||
p1 = p1.next
|
||||
p2 = p2.next.next
|
||||
|
||||
if p1 == p2:
|
||||
return True
|
||||
return False
|
||||
|
||||
def main():
|
||||
ll = CircLinkList()
|
||||
for i in range(10):
|
||||
ll.addNode(i)
|
||||
ll.printList()
|
||||
|
||||
print(isCircularll(ll))
|
||||
|
||||
ll2 = LinkList()
|
||||
for i in range(10):
|
||||
ll2.addNode(i)
|
||||
ll2.printList()
|
||||
|
||||
print(isCircularll(ll2))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
#!/usr/bin/python3
|
||||
# mari von steinkirch @2013
|
||||
# steinkirch at gmail
|
||||
|
||||
''' Implement a double-linked list, which is very simple, we just need inherets from a Linked List Class and add an attribute for prev.'''
|
||||
|
||||
from linked_list_fifo import LinkList
|
||||
|
||||
class dNode(object):
|
||||
def __init__(self, value = None, next = None):
|
||||
self.value = value
|
||||
self.next = next
|
||||
self.prev = None # THIS IS THE EXTRA ATTRIBUTE FOR DOUBLE L
|
||||
self.children = None # THIS IS NOT USED HERE, IS EXAMPLES WITH MANY LL INSIDE LLs
|
||||
|
||||
class dLinkList(LinkList):
|
||||
|
||||
def addNode(self, value):
|
||||
node = dNode(value)
|
||||
if not self.head:
|
||||
self.head = node
|
||||
if self.tail:
|
||||
node.prev = self.tail # ADD THIS WHEN DOUBLE L
|
||||
self.tail.next = node
|
||||
self.tail = node
|
||||
self.length += 1
|
||||
|
||||
|
||||
def printListInverse(self): # THIS IS THE EXTRA METHOD FOR DOUBLE L
|
||||
node = self.tail
|
||||
while node:
|
||||
print(node.value)
|
||||
node = node.prev
|
||||
|
||||
|
||||
|
||||
|
||||
from collections import Counter
|
||||
|
||||
def main():
|
||||
|
||||
ll = dLinkList()
|
||||
for i in range(1, 10):
|
||||
ll.addNode(i)
|
||||
print('Printing the list...')
|
||||
ll.printList()
|
||||
print('Now, printing the list inversely...')
|
||||
ll.printListInverse()
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
@ -0,0 +1,105 @@
|
|||
#!/usr/bin/python3
|
||||
# mari von steinkirch @2013
|
||||
# steinkirch at gmail
|
||||
|
||||
''' Find the mth-to-last element of a linked list.
|
||||
One option is having two pointers, separated by m. P1 start at the roots (p1 = self.root) and p2 is m-behinf pointer, which is created when p1 is at m. When p1 reach the end, p2 is the node. '''
|
||||
|
||||
from linked_list_fifo import Node
|
||||
|
||||
class LinkList(object):
|
||||
def __init__(self):
|
||||
self.head = None
|
||||
self.tail = None
|
||||
self.lenght = 0
|
||||
|
||||
def addNode(self, value):
|
||||
node = Node(value)
|
||||
if not self.head:
|
||||
self.head = node
|
||||
if self.tail:
|
||||
self.tail.next = node
|
||||
self.tail = node
|
||||
self.lenght += 1
|
||||
|
||||
def removeNode(self, index):
|
||||
prev = None
|
||||
node = self.head
|
||||
i = 0
|
||||
while node and i < index:
|
||||
prev = node
|
||||
node = node.next
|
||||
i += 1
|
||||
if i == index:
|
||||
if not prev:
|
||||
self.head = node.next
|
||||
else:
|
||||
prev.next = node.next
|
||||
self.lenght -= 1
|
||||
else:
|
||||
print('Index not found')
|
||||
|
||||
def findkth_from_begin(self, k):
|
||||
node = self.head
|
||||
i = 0
|
||||
while node and i < k:
|
||||
node = node.next
|
||||
i += 1
|
||||
while node:
|
||||
print(node.value)
|
||||
node = node.next
|
||||
|
||||
def findkth_to_last(self, k):
|
||||
node = self.head
|
||||
key = self.lenght - k
|
||||
i = 0
|
||||
while node and i < key:
|
||||
node = node.next
|
||||
i += 1
|
||||
print(node.value)
|
||||
|
||||
def findkth_to_last_2pointers(self, k):
|
||||
node = self.head
|
||||
pointer = self.head
|
||||
i = 0
|
||||
while pointer and i < k:
|
||||
pointer = pointer.next
|
||||
i += 1
|
||||
while pointer:
|
||||
node = node.next
|
||||
pointer = pointer.next
|
||||
print(node.value)
|
||||
|
||||
def findkth_to_last_2pointers2(self, k):
|
||||
p1 = self.head
|
||||
p2 = self.head
|
||||
i = 0
|
||||
while p1:
|
||||
if i >= k: # ---> notice >= not >!
|
||||
p2 = p2.next
|
||||
p1 = p1.next
|
||||
i += 1
|
||||
print(p2.value)
|
||||
|
||||
|
||||
def main():
|
||||
ll = LinkList()
|
||||
for i in range(1, 11):
|
||||
ll.addNode(i)
|
||||
# list is 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
|
||||
# so 0th from last is 11, 1th to last is 10,
|
||||
# 2th from last is 9!
|
||||
|
||||
|
||||
print('Finding from begin...')
|
||||
ll.findkth_from_begin(2)
|
||||
print('Finding to last, case 1...')
|
||||
ll.findkth_to_last(2) #9
|
||||
print('Finding to last, case 2...')
|
||||
ll.findkth_to_last_2pointers(2)
|
||||
print('Finding to last, case 3...')
|
||||
ll.findkth_to_last_2pointers2(2)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
#!/usr/bin/python3
|
||||
# mari von steinkirch @2013
|
||||
# steinkirch at gmail
|
||||
|
||||
''' The first example design a Hash table using chaining to avoid collisions. The second
|
||||
uses two lists.'''
|
||||
|
||||
from linked_list_fifo import Node, LinkList
|
||||
|
||||
class HashTableLL(object):
|
||||
def __init__(self, size):
|
||||
self.size = size
|
||||
self.slots = []
|
||||
self._createHashTable()
|
||||
|
||||
def _createHashTable(self):
|
||||
for i in range(self.size) :
|
||||
self.slots.append(LinkList())
|
||||
|
||||
def findIndex(self, item):
|
||||
return item%self.size
|
||||
|
||||
def addItem(self, item):
|
||||
index = self.findIndex(item)
|
||||
self.slots[index].addNode(item)
|
||||
return self
|
||||
|
||||
|
||||
def delItem(self, item):
|
||||
index = self.findIndex(item)
|
||||
self.slots[index].deleteNode(item)
|
||||
return self
|
||||
|
||||
|
||||
def printHashTable(self):
|
||||
for i in range(self.size):
|
||||
print('\nSlot {}:'.format(i))
|
||||
print(self.slots[i].printList())
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def test_hash_tables():
|
||||
H1 = HashTableLL(3)
|
||||
for i in range (0, 20):
|
||||
H1.addItem(i)
|
||||
H1.printHashTable()
|
||||
print('\n\nNow deleting:')
|
||||
H1.delItem(0)
|
||||
H1.delItem(0)
|
||||
H1.delItem(0)
|
||||
H1.delItem(0)
|
||||
H1.printHashTable()
|
||||
'''
|
||||
H2 = HashTable2L(3)
|
||||
H2[54]="buffy"
|
||||
H2[26]="xander"
|
||||
H2[17]="giles"
|
||||
print(H.2slots)
|
||||
'''
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
test_hash_tables()
|
||||
|
|
@ -0,0 +1,183 @@
|
|||
#!/usr/bin/python3
|
||||
# mari von steinkirch @2013
|
||||
# steinkirch at gmail
|
||||
|
||||
''' A class for a linked list that has the nodes in a FIFO order (such as a queue)'''
|
||||
|
||||
|
||||
class Node(object):
|
||||
def __init__(self, value = None, next = None):
|
||||
self.value = value
|
||||
self.next = next
|
||||
|
||||
class LinkList(object):
|
||||
def __init__(self):
|
||||
self.head = None
|
||||
self.tail = None
|
||||
self.length = 0
|
||||
|
||||
def addNode(self, value):
|
||||
node = Node(value)
|
||||
if not self.head:
|
||||
self.head = node
|
||||
if self.tail:
|
||||
self.tail.next = node
|
||||
self.tail = node
|
||||
self.length += 1
|
||||
|
||||
def printList(self):
|
||||
node = self.head
|
||||
while node:
|
||||
print(node.value)
|
||||
node = node.next
|
||||
|
||||
def addInOrder(self, item):
|
||||
new_node = Node(item)
|
||||
node = self.head
|
||||
previous = None
|
||||
stop = False
|
||||
while node and not stop:
|
||||
if node.value > item:
|
||||
stop = True
|
||||
else:
|
||||
previous = node
|
||||
node = node.next
|
||||
|
||||
if not previous:
|
||||
new_node.next = self.head
|
||||
self.head = new_node
|
||||
else:
|
||||
new_node.next = node
|
||||
previous.next = new_node
|
||||
|
||||
|
||||
|
||||
def deleteNode(self, index):
|
||||
prev = None
|
||||
node = self.head
|
||||
i = 0
|
||||
while node and i < index:
|
||||
prev = node
|
||||
node = node.next
|
||||
i += 1
|
||||
if i == index:
|
||||
if not prev:
|
||||
self.head = node.next
|
||||
else:
|
||||
prev.next = node.next
|
||||
self.length -= 1
|
||||
else:
|
||||
print('Index not found!')
|
||||
|
||||
|
||||
def deleteNodeIfOrdered(self, item):
|
||||
node = self.head
|
||||
previous = None
|
||||
found = False
|
||||
while node and not found:
|
||||
if node.value == item:
|
||||
found = True
|
||||
else:
|
||||
previous = node
|
||||
node = node.next
|
||||
|
||||
if found:
|
||||
if not previous:
|
||||
self.head = node.next
|
||||
else:
|
||||
previous.next = node.next
|
||||
else:
|
||||
print('Node not found!')
|
||||
|
||||
|
||||
def removeDupl(self):
|
||||
prev = None
|
||||
node = self.head
|
||||
aux_dict = Counter()
|
||||
while node:
|
||||
value_here = node.value
|
||||
if aux_dict[value_here] == 0:
|
||||
aux_dict[value_here] = 1
|
||||
else:
|
||||
if prev == None:
|
||||
self.head = node.next
|
||||
else:
|
||||
prev.next = node.next
|
||||
self.length -= 1
|
||||
prev = node
|
||||
node = node.next
|
||||
|
||||
def removeDupl_no_buf(self):
|
||||
node = self.head
|
||||
while node:
|
||||
pivot = node.value
|
||||
pointer = node.next
|
||||
prev = node
|
||||
while pointer:
|
||||
value_here = pointer.value
|
||||
if value_here == pivot:
|
||||
prev.next = pointer.next
|
||||
self.length -= 1
|
||||
prev = pointer
|
||||
pointer = pointer.next
|
||||
node = node.next
|
||||
|
||||
def searchIfOrdered(self, item):
|
||||
node = self.head
|
||||
found = False
|
||||
stop = False
|
||||
while node and not found and not stop:
|
||||
if node.value == item:
|
||||
found = True
|
||||
else:
|
||||
if node.value > item:
|
||||
stop = True
|
||||
else:
|
||||
node = node.next
|
||||
return found
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
from collections import Counter
|
||||
|
||||
def main():
|
||||
|
||||
ll = LinkList()
|
||||
for i in range(1, 10):
|
||||
ll.addNode(i)
|
||||
ll.addNode(i+1)
|
||||
print('Linked List with duplicates:')
|
||||
ll.printList()
|
||||
print('Length before deleting duplicate is: ', ll.length)
|
||||
ll.removeDupl()
|
||||
ll.printList()
|
||||
print('Lenght after deleting duplicates is: ', ll.length)
|
||||
|
||||
ll = LinkList()
|
||||
for i in range(1, 10):
|
||||
ll.addNode(i)
|
||||
ll.addNode(i+1)
|
||||
print('Linked List with duplicates:')
|
||||
ll.printList()
|
||||
print('Length before deleting duplicate is: ', ll.length)
|
||||
ll.removeDupl_no_buf()
|
||||
ll.printList()
|
||||
print('Lenght after deleting duplicates is: ', ll.length)
|
||||
|
||||
|
||||
ll = LinkList()
|
||||
l1 = [4, 2, 5, 7, 1, 9]
|
||||
for i in l1:
|
||||
ll.addInOrder(i)
|
||||
ll.printList()
|
||||
print(ll.searchIfOrdered(7))
|
||||
print(ll.searchIfOrdered(3))
|
||||
ll.deleteNodeIfOrdered(7)
|
||||
ll.printList()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
#!/usr/bin/python3
|
||||
# mari von steinkirch @2013
|
||||
# steinkirch at gmail
|
||||
|
||||
|
||||
''' Implement a unordered linked list, i.e. a LIFO linked list (like a stack) '''
|
||||
|
||||
class Node(object):
|
||||
def __init__(self, value = None, next = None):
|
||||
self.value = value
|
||||
self.next = next
|
||||
|
||||
class LinkList(object):
|
||||
def __init__(self):
|
||||
self.head = None
|
||||
self.lenght = 0
|
||||
|
||||
def addNode(self, value):
|
||||
node = Node(value)
|
||||
node.next = self.head
|
||||
self.head = node
|
||||
self.lenght += 1
|
||||
|
||||
def printList(self):
|
||||
node = self.head
|
||||
while node:
|
||||
print(node.value)
|
||||
node = node.next
|
||||
|
||||
def deleteNode(self, index):
|
||||
prev = None
|
||||
node = self.head
|
||||
i = 0
|
||||
while node and i < index:
|
||||
prev = node
|
||||
node = node.next
|
||||
i += 1
|
||||
if index == i:
|
||||
self.lenght -= 1
|
||||
if prev == None:
|
||||
self.head = node.next
|
||||
else:
|
||||
prev.next = node.next
|
||||
else:
|
||||
print('Node with index {} not found'.format(index))
|
||||
|
||||
|
||||
def deleteNodeByValue(self, item):
|
||||
prev = None
|
||||
node = self.head
|
||||
found = False
|
||||
while node and not found:
|
||||
if node.value == item:
|
||||
found = True
|
||||
else:
|
||||
prev = node
|
||||
node = node.next
|
||||
if found:
|
||||
self.lenght -= 1
|
||||
if prev == None:
|
||||
self.head = node.next
|
||||
else:
|
||||
prev.next = node.next
|
||||
else:
|
||||
print('Node with value {} not found'.format(item))
|
||||
|
||||
|
||||
def main():
|
||||
ll = LinkList()
|
||||
for i in range(1, 11):
|
||||
ll.addNode(i)
|
||||
print('The list is:')
|
||||
ll.printList()
|
||||
print('The list after deleting node with index 2 (value 8):')
|
||||
ll.deleteNode(2)
|
||||
ll.printList()
|
||||
print('The list after deleting node with value 2 (index 7):')
|
||||
ll.deleteNodeByValue(2)
|
||||
ll.printList()
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
#!/usr/bin/python3
|
||||
# mari von steinkirch @2013
|
||||
# steinkirch at gmail
|
||||
|
||||
''' This function partionate a linked list in a value, where everything smaller than this value
|
||||
goes to the front, and everything large goes to the back:'''
|
||||
|
||||
from linked_list_fifo import LinkList, Node
|
||||
|
||||
def partList(ll, n):
|
||||
more = LinkList()
|
||||
less = LinkList()
|
||||
node_old = ll.head
|
||||
while node_old:
|
||||
item = node_old.value
|
||||
if item < n:
|
||||
less.addNode(item)
|
||||
elif item > n:
|
||||
more.addNode(item)
|
||||
node_old = node_old.next
|
||||
|
||||
less.addNode(n)
|
||||
nodemore = more.head
|
||||
while nodemore:
|
||||
less.addNode(nodemore.value)
|
||||
nodemore = nodemore.next
|
||||
return less
|
||||
|
||||
|
||||
|
||||
def main():
|
||||
ll = LinkList()
|
||||
l1 = [6, 7, 3, 4, 9, 5, 1, 2, 8]
|
||||
for i in l1:
|
||||
ll.addNode(i)
|
||||
print('Before Part')
|
||||
ll.printList()
|
||||
print('After Part')
|
||||
newll = partList(ll, 6)
|
||||
newll.printList()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
#!/usr/bin/python3
|
||||
# mari von steinkirch @2013
|
||||
# steinkirch at gmail
|
||||
|
||||
''' Supposing two linked lists represening numbers, such that in each of their
|
||||
nodes they carry one digit. This function sums the two numbers that these
|
||||
two linked lists represent, returning a third list representing the sum:'''
|
||||
|
||||
from linked_list_fifo import Node, LinkList
|
||||
|
||||
|
||||
def sumlls(l1, l2):
|
||||
lsum = LinkList()
|
||||
dig1 = l1.head
|
||||
dig2 = l2.head
|
||||
next = 0
|
||||
while dig1 and dig2:
|
||||
d1 = dig1.value
|
||||
d2 = dig2.value
|
||||
sum_d = d1 + d2 + next
|
||||
if sum_d > 9:
|
||||
next = sum_d//10
|
||||
lsum.addNode(sum_d%10)
|
||||
|
||||
else:
|
||||
lsum.addNode(sum_d)
|
||||
next = 0
|
||||
|
||||
dig1 = dig1.next
|
||||
dig2 = dig2.next
|
||||
|
||||
if dig1:
|
||||
sum_d = next + dig1.value
|
||||
if sum_d > 9:
|
||||
lsum.addNode(sum_d%10)
|
||||
else:
|
||||
lsum.addNode(sum_d)
|
||||
dig1 = dig1.next
|
||||
|
||||
if dig2:
|
||||
sum_d = next + dig2.value
|
||||
if sum_d > 9:
|
||||
lsum.addNode(sum_d%10)
|
||||
else:
|
||||
lsum.addNode(sum_d)
|
||||
dig2 = dig2.next
|
||||
|
||||
|
||||
return lsum
|
||||
|
||||
|
||||
|
||||
def main():
|
||||
l1 = LinkList() # 2671
|
||||
l1.addNode(1)
|
||||
l1.addNode(7)
|
||||
l1.addNode(6)
|
||||
l1.addNode(2)
|
||||
|
||||
l2 = LinkList() # 455
|
||||
l2.addNode(5)
|
||||
l2.addNode(5)
|
||||
l2.addNode(4)
|
||||
|
||||
lsum = sumlls(l1, l2)
|
||||
lsum.printList()# 3126
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
class Node(object):
|
||||
def __init__(self, name, which):
|
||||
self.name = name
|
||||
self.which = which
|
||||
self.next = next
|
||||
self.timestamp = 0
|
||||
|
||||
|
||||
|
||||
class AnimalShelter(object):
|
||||
def __init__(self):
|
||||
self.first_cat = None
|
||||
self.first_dog = None
|
||||
self.last_cat = None
|
||||
self.last_dog = None
|
||||
self.counter = 0
|
||||
|
||||
|
||||
def enqueue(self, name, which):
|
||||
self.counter += 1
|
||||
node = Node(name, which)
|
||||
node.timestamp = self.counter
|
||||
|
||||
if which == 'cat':
|
||||
if not self.first_cat:
|
||||
self.first_cat = node
|
||||
if self.last_cat:
|
||||
self.last_cat.next = node
|
||||
self.last_cat = node
|
||||
|
||||
if which == 'dog':
|
||||
if not self.first_dog:
|
||||
self.first_dog = node
|
||||
if self.last_dog:
|
||||
self.last_dog.next = node
|
||||
self.last_dog = node
|
||||
|
||||
|
||||
|
||||
def dequeueDog(self):
|
||||
if self.first_dog:
|
||||
node = self.first_dog
|
||||
self.first_dog = node.next
|
||||
return str(node.name)
|
||||
raise Exception('No Dogs!')
|
||||
|
||||
|
||||
|
||||
def dequeueCat(self):
|
||||
if self.first_cat:
|
||||
node = self.first_cat
|
||||
self.first_cat = node.next
|
||||
return str(node.name)
|
||||
raise Exception('No Cats!')
|
||||
|
||||
|
||||
|
||||
def dequeueAny(self):
|
||||
nodecat = self.first_cat
|
||||
nodedog = self.first_dog
|
||||
if nodecat and not nodedog:
|
||||
return self.dequeueCat()
|
||||
elif nodedog and not nodecat:
|
||||
return self.dequeueDog()
|
||||
elif nodedog and nodecat:
|
||||
if nodedog.timestamp < nodecat.timestamp:
|
||||
return self.dequeueDog()
|
||||
else:
|
||||
return self.dequeueCat()
|
||||
raise Exception('No Animals!')
|
||||
|
||||
|
||||
|
||||
|
||||
def main():
|
||||
qs = AnimalShelter()
|
||||
qs.enqueue('bob', 'cat')
|
||||
qs.enqueue('mia', 'cat')
|
||||
qs.enqueue('yoda', 'dog')
|
||||
qs.enqueue('wolf', 'dog')
|
||||
|
||||
assert(qs.dequeueDog() == 'yoda')
|
||||
assert(qs.dequeueCat() == 'bob')
|
||||
print(qs.dequeueAny() == 'mia')
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
class MyQueue(object):
|
||||
def __init__(self):
|
||||
self.enq = []
|
||||
self.deq = []
|
||||
|
||||
def enqueue(self, item):
|
||||
self.enq.append(item)
|
||||
|
||||
def _addStacks(self):
|
||||
aux = []
|
||||
if self.enq:
|
||||
while self.enq:
|
||||
aux.append(self.enq.pop())
|
||||
aux.extend(self.deq)
|
||||
self.deq = aux
|
||||
|
||||
def dequeue(self):
|
||||
self._addStacks()
|
||||
if self.deq:
|
||||
return self.deq.pop()
|
||||
raise Exception('Cannot "deque": Queue is empty')
|
||||
|
||||
def peek(self):
|
||||
if self.deq:
|
||||
return self.deq[-1]
|
||||
elif self.enq:
|
||||
return self.enq[0]
|
||||
raise Exception('Cannot "peek": Queue is empty')
|
||||
|
||||
def isEmpty(self):
|
||||
return not (bool(self.enq) or bool(self.deq))
|
||||
|
||||
def size(self):
|
||||
return len(self.enq) + len(self.deq)
|
||||
|
||||
def printQueue(self):
|
||||
self._addStacks()
|
||||
if self.deq:
|
||||
aux = str(self.deq).strip('[]')
|
||||
return 'Front --> ' + aux +' <-- Back'
|
||||
else:
|
||||
raise Exception('Cannot "printQueue": Queue is empty')
|
||||
|
||||
|
||||
def main():
|
||||
q = MyQueue()
|
||||
for i in range(1, 11):
|
||||
q.enqueue(i)
|
||||
print(q.printQueue())
|
||||
assert(q.peek() == 1)
|
||||
assert(q.isEmpty() == False)
|
||||
assert(q.size() == 10)
|
||||
|
||||
for i in range (1, 10):
|
||||
q.dequeue()
|
||||
print(q.printQueue())
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
@ -0,0 +1,165 @@
|
|||
from stack import Stack, Node
|
||||
|
||||
class SetOfStacks(object):
|
||||
def __init__(self, capacity):
|
||||
assert(capacity > 1)
|
||||
self.capacity = capacity
|
||||
self.stack_now = None
|
||||
self.stack_now_size = 0
|
||||
self.old_stacks = []
|
||||
|
||||
|
||||
def _checkIfFull(self):
|
||||
return self.stack_now_size == self.capacity
|
||||
|
||||
|
||||
def _addStack(self):
|
||||
self.stack_now = Stack()
|
||||
self.stack_now_size = 0
|
||||
|
||||
|
||||
def _archiveStack(self):
|
||||
self.old_stacks.append(self.stack_now)
|
||||
self.stack_now = None
|
||||
self.stack_now_size = 0
|
||||
|
||||
|
||||
def _popItem(self):
|
||||
if self.stack_now.top:
|
||||
value = self.stack_now.top.value
|
||||
if self.stack_now.top.next:
|
||||
node = self.stack_now.top
|
||||
self.stack_now.top = self.stack_now.top.next
|
||||
else:
|
||||
self.stack_now = []
|
||||
return value
|
||||
raise Exception('Stack is empty.')
|
||||
|
||||
|
||||
def numberOfStacksUsed(self):
|
||||
if self.stack_now:
|
||||
return len(self.old_stacks) + 1
|
||||
else:
|
||||
return len(self.old_stacks)
|
||||
|
||||
|
||||
def seeTop(self):
|
||||
if self.stack_now:
|
||||
return self.stack_now.top.value
|
||||
elif self.old_stacks:
|
||||
return self.old_stacks[-1].top.value
|
||||
raise Exception('Stack is Empty')
|
||||
|
||||
|
||||
def isEmpty(self):
|
||||
return not (bool(self.stack_now) or bool(self.old_stacks))
|
||||
|
||||
|
||||
def _sizeStackInUse(self):
|
||||
return self.stack_now_size
|
||||
|
||||
|
||||
def size(self):
|
||||
return self._sizeStackInUse() + self.capacity*len(self.old_stacks)
|
||||
|
||||
|
||||
def push(self, item):
|
||||
if not self.stack_now:
|
||||
self._addStack()
|
||||
|
||||
node = Node(item)
|
||||
node.next = self.stack_now.top
|
||||
self.stack_now.top = node
|
||||
|
||||
self.stack_now_size += 1
|
||||
|
||||
if self._checkIfFull():
|
||||
self._archiveStack()
|
||||
|
||||
|
||||
def pop(self):
|
||||
if not self.stack_now:
|
||||
if not self.old_stacks:
|
||||
raise Exception('Stack is empty')
|
||||
else:
|
||||
self.stack_now = self.old_stacks.pop()
|
||||
self.stack_now_size = self.capacity - 1
|
||||
self._popItem()
|
||||
else:
|
||||
self._popItem()
|
||||
if self.stack_now:
|
||||
self.stack_now_size -= 1
|
||||
else:
|
||||
self.stack_now_size = 0
|
||||
|
||||
|
||||
|
||||
def main():
|
||||
s1 = SetOfStacks(3)
|
||||
|
||||
print(s1.numberOfStacksUsed())
|
||||
print(s1.isEmpty())
|
||||
print(s1.size())
|
||||
|
||||
s1.push(1)
|
||||
print('Push item 1')
|
||||
print(s1.numberOfStacksUsed())
|
||||
print(s1.seeTop())
|
||||
print(s1.isEmpty())
|
||||
print(s1.size())
|
||||
|
||||
s1.push(2)
|
||||
s1.push(3)
|
||||
print('Push item 2 and 3')
|
||||
print(s1.numberOfStacksUsed())
|
||||
print(s1.seeTop())
|
||||
print(s1.isEmpty())
|
||||
print(s1.size())
|
||||
|
||||
s1.push(4)
|
||||
print('Push item 4')
|
||||
print(s1.numberOfStacksUsed())
|
||||
print(s1.seeTop())
|
||||
print(s1.isEmpty())
|
||||
print(s1.size())
|
||||
|
||||
s1.push(5)
|
||||
print('Push item 5')
|
||||
print(s1.numberOfStacksUsed())
|
||||
print(s1.seeTop())
|
||||
print(s1.isEmpty())
|
||||
print(s1.size())
|
||||
|
||||
s1.pop()
|
||||
print('Pop item 5')
|
||||
print(s1.numberOfStacksUsed())
|
||||
print(s1.seeTop())
|
||||
print(s1.isEmpty())
|
||||
print(s1.size())
|
||||
|
||||
s1.pop()
|
||||
print('Pop item 4')
|
||||
print(s1.numberOfStacksUsed())
|
||||
print(s1.seeTop())
|
||||
print(s1.isEmpty())
|
||||
print(s1.size())
|
||||
|
||||
s1.pop()
|
||||
s1.pop()
|
||||
print('Pop item 3 e 2')
|
||||
print(s1.numberOfStacksUsed())
|
||||
print(s1.seeTop())
|
||||
print(s1.isEmpty())
|
||||
print(s1.size())
|
||||
|
||||
s1.pop()
|
||||
print('Pop item 1')
|
||||
print(s1.numberOfStacksUsed())
|
||||
print(s1.isEmpty())
|
||||
print(s1.size())
|
||||
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
@ -0,0 +1,154 @@
|
|||
from stack import StackList
|
||||
|
||||
class SetOfStacksList(object):
|
||||
def __init__(self, capacity):
|
||||
assert(capacity > 1)
|
||||
self.capacity = capacity
|
||||
self.stack_now = []
|
||||
self.old_stacks = []
|
||||
|
||||
def _checkIfFull(self):
|
||||
return len(self.stack_now) == self.capacity
|
||||
|
||||
|
||||
def _archiveStack(self):
|
||||
self.old_stacks.append(self.stack_now)
|
||||
self.stack_now = []
|
||||
|
||||
|
||||
def _popItem(self):
|
||||
if self.stack_now:
|
||||
return self.stack_now.pop()
|
||||
raise Exception('Stack is empty.')
|
||||
|
||||
|
||||
def _sizeStackInUse(self):
|
||||
return len(self.stack_now)
|
||||
|
||||
|
||||
def numberOfStacksUsed(self):
|
||||
if self.stack_now:
|
||||
return len(self.old_stacks) + 1
|
||||
else:
|
||||
return len(self.old_stacks)
|
||||
|
||||
|
||||
def seeTop(self):
|
||||
if self.stack_now:
|
||||
return self.stack_now[-1]
|
||||
elif self.old_stacks:
|
||||
return self.old_stacks[-1][-1]
|
||||
raise Exception('Stack is Empty')
|
||||
|
||||
|
||||
def isEmpty(self):
|
||||
return not(bool(self.stack_now) or bool(self.old_stacks))
|
||||
|
||||
|
||||
def size(self):
|
||||
return len(self.stack_now) + self.capacity*len(self.old_stacks)
|
||||
|
||||
|
||||
def push(self, item):
|
||||
self.stack_now.append(item)
|
||||
if self._checkIfFull():
|
||||
self._archiveStack()
|
||||
|
||||
|
||||
def pop(self):
|
||||
if not self.stack_now:
|
||||
if not self.old_stacks:
|
||||
raise Exception('Stack is empty')
|
||||
else:
|
||||
self.stack_now = self.old_stacks.pop()
|
||||
return self.stack_now.pop()
|
||||
|
||||
def popAt(self, index):
|
||||
number_of_stacks = self.size()
|
||||
if index < number_of_stacks:
|
||||
if index == number_of_stacks - 1 and self.stack_now:
|
||||
return self.stack_now.pop()
|
||||
if index < number_of_stacks - 1:
|
||||
stack_here = self.old_stacks[index]
|
||||
return stack_here.pop()
|
||||
raise Exception('Stack at index {} is empty.'.format(index))
|
||||
raise Exception('Index larger than the number of stacks.')
|
||||
|
||||
def printStacks(self):
|
||||
return str(self.old_stacks), str(self.stack_now)
|
||||
|
||||
|
||||
def main():
|
||||
s1 = SetOfStacksList(3)
|
||||
|
||||
print(s1.numberOfStacksUsed())
|
||||
print(s1.isEmpty())
|
||||
print(s1.size())
|
||||
|
||||
s1.push(1)
|
||||
print('Push item 1')
|
||||
print(s1.numberOfStacksUsed())
|
||||
print(s1.seeTop())
|
||||
print(s1.isEmpty())
|
||||
print(s1.size())
|
||||
|
||||
s1.push(2)
|
||||
s1.push(3)
|
||||
print('Push item 2 and 3')
|
||||
print(s1.numberOfStacksUsed())
|
||||
print(s1.seeTop())
|
||||
print(s1.isEmpty())
|
||||
print(s1.size())
|
||||
|
||||
s1.push(4)
|
||||
print('Push item 4')
|
||||
print(s1.numberOfStacksUsed())
|
||||
print(s1.seeTop())
|
||||
print(s1.isEmpty())
|
||||
print(s1.size())
|
||||
|
||||
s1.push(5)
|
||||
print('Push item 5')
|
||||
print(s1.numberOfStacksUsed())
|
||||
print(s1.seeTop())
|
||||
print(s1.isEmpty())
|
||||
print(s1.size())
|
||||
|
||||
s1.pop()
|
||||
print('Pop item 5')
|
||||
print(s1.numberOfStacksUsed())
|
||||
print(s1.seeTop())
|
||||
print(s1.isEmpty())
|
||||
print(s1.size())
|
||||
|
||||
s1.pop()
|
||||
print('Pop item 4')
|
||||
print(s1.numberOfStacksUsed())
|
||||
print(s1.seeTop())
|
||||
print(s1.isEmpty())
|
||||
print(s1.size())
|
||||
|
||||
s1.pop()
|
||||
s1.pop()
|
||||
print('Pop item 3 e 2')
|
||||
print(s1.numberOfStacksUsed())
|
||||
print(s1.seeTop())
|
||||
print(s1.isEmpty())
|
||||
print(s1.size())
|
||||
|
||||
s1.pop()
|
||||
print('Pop item 1')
|
||||
print(s1.numberOfStacksUsed())
|
||||
print(s1.isEmpty())
|
||||
print(s1.size())
|
||||
|
||||
|
||||
s2 = SetOfStacksList(3)
|
||||
for i in range(1, 11):
|
||||
s2.push(i)
|
||||
print(s2.printStacks())
|
||||
print(s2.popAt(2))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
def sortStack(s):
|
||||
bufs = []
|
||||
while s:
|
||||
item = s.pop()
|
||||
count, i = 0, 0
|
||||
while bufs and bufs[-1] > item:
|
||||
s.append(bufs.pop())
|
||||
count += 1
|
||||
bufs.append(item)
|
||||
while i < count:
|
||||
bufs.append(s.pop())
|
||||
i += 1
|
||||
return bufs
|
||||
|
||||
def main():
|
||||
s = [3, 5, 1, 2, 6, 7, 8]
|
||||
print(sortStack(s))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
from stack import Stack, Node, StackList
|
||||
|
||||
|
||||
class StackMinElen(Stack):
|
||||
def __init__(self):
|
||||
self.top = None
|
||||
self.mins = []
|
||||
|
||||
def printMin(self):
|
||||
if self.mins:
|
||||
return self.mins[-1]
|
||||
raise Exception('Stack is empty.')
|
||||
|
||||
|
||||
def pop(self):
|
||||
if self.top:
|
||||
self.mins.pop()
|
||||
node = self.top
|
||||
self.top = node.next
|
||||
return node.value
|
||||
raise Exception('Stack is empty.')
|
||||
|
||||
|
||||
def push(self, item):
|
||||
if self.top:
|
||||
min_so_far = self.mins[-1]
|
||||
if min_so_far > item:
|
||||
self.mins.append(item)
|
||||
else:
|
||||
self.mins.append(min_so_far)
|
||||
else:
|
||||
self.mins.append(item)
|
||||
node = Node(item)
|
||||
node.next = self.top
|
||||
self.top = node
|
||||
|
||||
|
||||
|
||||
|
||||
class StackListMinElen(StackList):
|
||||
def __init__(self):
|
||||
self.items = []
|
||||
self.mins = []
|
||||
|
||||
def printMin(self):
|
||||
if self.mins:
|
||||
return self.mins[-1]
|
||||
raise Exception('Stack is Empty')
|
||||
|
||||
def push(self, item):
|
||||
self.items.append(item)
|
||||
if self.mins:
|
||||
if self.mins[-1] > item:
|
||||
self.mins.append(item)
|
||||
else:
|
||||
self.mins.append(self.mins[-1])
|
||||
else:
|
||||
self.mins.append(item)
|
||||
|
||||
def pop(self):
|
||||
if self.items:
|
||||
self.mins.pop()
|
||||
return self.items.pop()
|
||||
raise Exception('Stack is Empty')
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def main():
|
||||
s1 = StackListMinElen()
|
||||
l1 = [4, 2, 6, 3, 1, 5]
|
||||
for i in l1:
|
||||
s1.push(i)
|
||||
print('Min: ', s1.printMin())
|
||||
print('Pop: ', s1.pop())
|
||||
print('Min: ', s1.printMin())
|
||||
print('Pop: ', s1.pop())
|
||||
print('Min: ', s1.printMin())
|
||||
print('Pop: ', s1.pop())
|
||||
print('Min: ', s1.printMin())
|
||||
print('Pop: ', s1.pop())
|
||||
print('Min: ', s1.printMin())
|
||||
print('Pop: ', s1.pop())
|
||||
print('Min: ', s1.printMin())
|
||||
|
||||
|
||||
s2 = StackMinElen()
|
||||
l1 = [4, 2, 6, 3, 1, 5]
|
||||
for i in l1:
|
||||
s2.push(i)
|
||||
print('Min: ', s2.printMin())
|
||||
print('Pop: ', s2.pop())
|
||||
print('Min: ', s2.printMin())
|
||||
print('Pop: ', s2.pop())
|
||||
print('Min: ', s2.printMin())
|
||||
print('Pop: ', s2.pop())
|
||||
print('Min: ', s2.printMin())
|
||||
print('Pop: ', s2.pop())
|
||||
print('Min: ', s2.printMin())
|
||||
print('Pop: ', s2.pop())
|
||||
print('Min: ', s2.printMin())
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
@ -0,0 +1,94 @@
|
|||
#!/usr/bin/python3
|
||||
# steinkirch at gmail.com
|
||||
# astro.sunysb.edu/steinkirch
|
||||
|
||||
class Node(object):
|
||||
def __init__(self, value=None):
|
||||
self.value = value
|
||||
self.next = None
|
||||
|
||||
|
||||
class Stack(object):
|
||||
def __init__(self):
|
||||
self.top = None
|
||||
|
||||
def push(self, item):
|
||||
node = Node(item)
|
||||
node.next = self.top
|
||||
self.top = node
|
||||
|
||||
def pop(self):
|
||||
if self.top:
|
||||
node = self.top
|
||||
self.top = node.next
|
||||
return node.value
|
||||
raise Exception('Stack is empty.')
|
||||
|
||||
def isEmpty(self):
|
||||
return bool(self.top)
|
||||
|
||||
def seeTop(self):
|
||||
if self.top:
|
||||
return self.top.value
|
||||
raise Exception('Stack is empty.')
|
||||
|
||||
def size(self):
|
||||
node = self.top
|
||||
count = 0
|
||||
while node:
|
||||
count +=1
|
||||
node = node.next
|
||||
return count
|
||||
|
||||
|
||||
class StackList(list):
|
||||
def __init__(self):
|
||||
self.items = []
|
||||
|
||||
def push(self, item):
|
||||
self.items.append(item)
|
||||
|
||||
def pop(self):
|
||||
if self.items:
|
||||
return self.items.pop()
|
||||
raise Exception('Stack is empty.')
|
||||
|
||||
def seeTop(self):
|
||||
if self.items:
|
||||
return self.items[-1]
|
||||
raise Exception('Stack is empty.')
|
||||
|
||||
def size(self):
|
||||
return len(self.items)
|
||||
|
||||
def isEmpty(self):
|
||||
return bool(self.items)
|
||||
|
||||
|
||||
def main():
|
||||
s1 = StackList()
|
||||
print(s1.isEmpty())
|
||||
for i in range(1, 10):
|
||||
s1.push(i)
|
||||
print(s1.isEmpty())
|
||||
print(s1.size())
|
||||
print(s1.seeTop())
|
||||
s1.pop()
|
||||
print(s1.size())
|
||||
print(s1.seeTop())
|
||||
|
||||
|
||||
s2 = Stack()
|
||||
print(s2.isEmpty())
|
||||
for i in range(1, 10):
|
||||
s2.push(i)
|
||||
print(s2.isEmpty())
|
||||
print(s2.size())
|
||||
print(s2.seeTop())
|
||||
s2.pop()
|
||||
print(s2.size())
|
||||
print(s2.seeTop())
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
from stack import Stack, Node
|
||||
|
||||
|
||||
def moveTop(s1, s3):
|
||||
s3.append(s1.pop())
|
||||
|
||||
def moveDisks(n, s1, s3, s2):
|
||||
if n < 1: return
|
||||
moveDisks(n - 1, s1, s2, s3)
|
||||
moveTop(s1, s3)
|
||||
moveDisks(n -1, s2, s3, s1)
|
||||
|
||||
|
||||
def towersOfHanoi(n):
|
||||
s1 = [x+1 for x in range(n)]
|
||||
s2 = []
|
||||
s3 = []
|
||||
print('The first stick is {0} and the third stick has {1}'.format(s1, s3))
|
||||
|
||||
moveDisks(n, s1, s3, s2)
|
||||
|
||||
print('The first stick is {0} and the third stick has {1}'.format(s1, s3))
|
||||
return s3
|
||||
|
||||
if __name__ == '__main__':
|
||||
towersOfHanoi(6)
|
||||
|
|
@ -0,0 +1,112 @@
|
|||
#!/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()
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
#!/usr/bin/python3
|
||||
# mari von steinkirch @2013
|
||||
# steinkirch at gmail
|
||||
|
||||
''' 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).
|
||||
|
||||
>>> m = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
|
||||
>>> binary_search_matrix_rec(m, 6)
|
||||
(1, 2)
|
||||
>>> binary_search_matrix_rec(m, 12)
|
||||
>>> binary_search_matrix_iter(m, 6)
|
||||
(1, 2)
|
||||
>>> binary_search_matrix_iter(m, 12)
|
||||
>>> binary_search_matrix_iter(m, 1)
|
||||
(0, 0)
|
||||
|
||||
(2) Another solution is "discarding" arrays in the way. The efficiency is O(logm).
|
||||
>>> m = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
|
||||
>>> searching_matrix(m, 6)
|
||||
(1, 2)
|
||||
>>> searching_matrix(m, 12)
|
||||
|
||||
'''
|
||||
|
||||
|
||||
def binary_search_matrix_rec(m, key, lo=0, hi=None):
|
||||
if not m: return None
|
||||
rows = len(m)
|
||||
cols = len(m[0])
|
||||
hi = hi or rows*cols
|
||||
if hi > lo: # -----> REMEMBER THIS OR INDEX WILL EXPLODE!!!!!!!!
|
||||
mid = (hi + lo)//2
|
||||
row = mid//cols
|
||||
col = mid%cols
|
||||
item = m[row][col]
|
||||
if key == item: return row, col
|
||||
elif key < item: return binary_search_matrix_rec(m, key, lo, mid-1)
|
||||
else: return binary_search_matrix_rec(m, key, mid+1, hi)
|
||||
return None
|
||||
|
||||
|
||||
|
||||
def binary_search_matrix_iter(m, key):
|
||||
if not m: return None
|
||||
rows = len(m)
|
||||
cols = len(m[0])
|
||||
lo, hi = 0, rows*cols
|
||||
while lo < hi:
|
||||
mid = (hi + lo)//2
|
||||
row = mid//rows
|
||||
col = mid%rows
|
||||
item = m[row][col]
|
||||
if key == item: return (row, col)
|
||||
elif key < item: hi = mid
|
||||
else: lo = mid +1
|
||||
return None
|
||||
|
||||
|
||||
def searching_matrix(m, key):
|
||||
if not m: return None
|
||||
rows = len(m)
|
||||
cols = len(m[0])
|
||||
i, j = 0, cols -1
|
||||
while i < rows and j > 0:
|
||||
item = m[i][j]
|
||||
if key == item: return (i, j)
|
||||
elif key < item: j -= 1
|
||||
else: i += 1
|
||||
return None
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import doctest
|
||||
doctest.testmod()
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
#!/usr/bin/python3
|
||||
# mari von steinkirch @2013
|
||||
# steinkirch at gmail
|
||||
|
||||
''' 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):
|
||||
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
|
||||
|
||||
# if left is ordered --> we work here
|
||||
if seq[lo] <= seq[mid]:
|
||||
# now, is the key there?
|
||||
if key < seq[mid] and key >= seq[lo]:
|
||||
return find_element_rot_array(seq, key, lo, mid)
|
||||
else:
|
||||
# all the other cases
|
||||
return find_element_rot_array(seq, key, mid+1, hi)
|
||||
|
||||
# right is ordered --> we work here
|
||||
else:
|
||||
# now, is the key there?
|
||||
if key > seq[mid] and key <= seq[hi-1]: # stupid hi-1!!!
|
||||
return find_element_rot_array(seq, key, mid+1, hi)
|
||||
else:
|
||||
# all the other cases
|
||||
return find_element_rot_array(seq, key, lo, mid)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import doctest
|
||||
doctest.testmod()
|
||||
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
#!/usr/bin/python3
|
||||
# mari von steinkirch @2013
|
||||
# steinkirch at gmail
|
||||
|
||||
''' Given a sorted an array with empty strings, we use binary search to find some string (since
|
||||
the list is sorted):
|
||||
--> 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):
|
||||
>>> 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')
|
||||
'''
|
||||
|
||||
|
||||
def find_str_array_with_empty_str(seq, s1):
|
||||
if not seq or not s1: return None
|
||||
hi = len(seq)
|
||||
lo = 0
|
||||
while hi > lo:
|
||||
mid = (hi+lo)//2
|
||||
|
||||
if seq[mid] == '':
|
||||
while True:
|
||||
left = mid-1
|
||||
right = mid+1
|
||||
if left < lo or right > hi: return None
|
||||
elif right < hi and seq[right]:
|
||||
mid = right
|
||||
break
|
||||
elif left > lo and seq[left]:
|
||||
mid = left
|
||||
break
|
||||
right += 1
|
||||
left -= 1
|
||||
|
||||
if s1 == seq[mid] == s1: return mid
|
||||
elif s1 < seq[mid]: hi = mid
|
||||
else: lo = mid + 1
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import doctest
|
||||
doctest.testmod()
|
||||
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
3
|
||||
5
|
||||
6
|
||||
7
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
1
|
||||
3
|
||||
5
|
||||
8
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
#!/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()
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,95 @@
|
|||
#!/usr/bin/python3
|
||||
# mari von steinkirch @2013
|
||||
# steinkirch at gmail
|
||||
|
||||
''' --> 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
|
||||
|
||||
1) If we can modify the arrays (pop) we can use:
|
||||
def merge(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
|
||||
|
||||
|
||||
2) If we can't modify or we want to in place, we need two pointers:
|
||||
>>> l1 = [1, 2, 3, 4, 5, 6, 7]
|
||||
>>> l2 = [2, 4, 5, 8]
|
||||
>>> merge(l1, l2)
|
||||
[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:
|
||||
>>> l1 = [1, 2, 3, 4, 5, 6, 7, 0, 0, 0, 0]
|
||||
>>> l2 = [2, 4, 5, 8]
|
||||
>>> merge_two_arrays_inplace(l1, l2)
|
||||
[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):
|
||||
>>> list_files = ['1.dat', '2.dat', '3.dat']
|
||||
>>> merge_files(list_files)
|
||||
[1, 1, 2, 3, 3, 3, 4, 5, 5, 5, 6, 7, 8]
|
||||
'''
|
||||
|
||||
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
|
||||
|
||||
|
||||
|
||||
def merge_two_arrays_inplace(l1, l2):
|
||||
if not l1 or not l2: return l1 or l2 # nothing to be merged
|
||||
p2 = len(l2) - 1
|
||||
p1 = len(l1) - len(l2) - 1
|
||||
p12 = len(l1) - 1
|
||||
while p2 >= 0 and p1 >= 0:
|
||||
item_to_be_merged = l2[p2]
|
||||
item_bigger_array = l1[p1]
|
||||
if item_to_be_merged < item_bigger_array:
|
||||
l1[p12] = item_bigger_array
|
||||
p1 -= 1
|
||||
else:
|
||||
l1[p12] = item_to_be_merged
|
||||
p2 -= 1
|
||||
p12 -= 1
|
||||
return l1
|
||||
|
||||
|
||||
def merge_files(list_files):
|
||||
result = []
|
||||
final = []
|
||||
for filename in list_files:
|
||||
aux = []
|
||||
with open(filename, 'r') as file:
|
||||
for line in file:
|
||||
aux.append(int(line))
|
||||
result.append(aux)
|
||||
final.extend(result.pop())
|
||||
for l in result:
|
||||
final = merge(l, final)
|
||||
return final
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import doctest
|
||||
doctest.testmod()
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
#!/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()
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
#!/usr/bin/python3
|
||||
# mari von steinkirch @2013
|
||||
# steinkirch at gmail
|
||||
|
||||
''' 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
|
||||
algorithm is O(n).
|
||||
>>> l1 = ['hat', 'ball', 'tha', 'cut', 'labl', 'hta', 'cool', 'cuy', 'uct']
|
||||
>>> sort_anagrams_together(l1)
|
||||
['cut', 'uct', 'cool', 'ball', 'labl', 'hat', 'tha', 'hta', 'cuy']
|
||||
'''
|
||||
|
||||
from collections import defaultdict
|
||||
def sort_anagrams_together(l1):
|
||||
result = []
|
||||
|
||||
# step 1 save the anagrams together
|
||||
dict_aux = defaultdict(list) # rememebr to indicate the type
|
||||
for word in l1:
|
||||
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
|
||||
|
||||
# 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
|
||||
for key in dict_aux:
|
||||
result.extend(dict_aux[key])
|
||||
|
||||
return result
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import doctest
|
||||
doctest.testmod()
|
||||
|
||||
|
|
@ -0,0 +1,102 @@
|
|||
#!/usr/bin/python3
|
||||
# mari von steinkirch 2013
|
||||
|
||||
from binary_tree import BinaryTree, NodeBT
|
||||
|
||||
''' Implementation of a binary search tree and its properties.
|
||||
We use the Binary Tree class and its Node class as superclasses, and we modify the methods
|
||||
that are needeed to create a BST (polymorphism). For example, the following bst:
|
||||
|
||||
7 ---> level 0
|
||||
4 9 ---> level 1
|
||||
2 5 8 10 ---> level 2
|
||||
1 6 ---> level 3
|
||||
|
||||
has the following properties:
|
||||
|
||||
- SIZE OR NUMBER OF NODES: n = 10
|
||||
- NUMBER OF BRANCHES OR INTERNAL NODES: b = n-1 = 9
|
||||
- VALUE OF ROOT = 7
|
||||
- MAX_DEPTH OR HEIGHT: h = 3
|
||||
- IS BALANCED? YES
|
||||
- IS BST? YES
|
||||
- INORDER DFT: 1, 2, 4, 5, 6, 7, 8, 9, 10
|
||||
- POSTORDER DFT: 1, 2, 6, 5, 4, 8, 10, 9, 7
|
||||
- PREORDER DFT: 7, 4, 2, 1, 5, 6, 9, 8, 10
|
||||
- BFT: 7, 4, 9, 2, 5, 8, 10, 1, 6
|
||||
'''
|
||||
|
||||
|
||||
class NodeBST(NodeBT):
|
||||
|
||||
def _addNextNode(self, value, level_here=1):
|
||||
''' Aux for self.addNode(value): for BST, best O(1), worst O(log n) '''
|
||||
self.traversal = []
|
||||
new_node = NodeBST(value, level_here)
|
||||
if not self.item:
|
||||
self.item = new_node
|
||||
elif value < self.item:
|
||||
self.left = self.left and self.left._addNextNode(value, level_here+1) or new_node
|
||||
else:
|
||||
self.right = self.right and self.right._addNextNode(value, level_here+1) or new_node
|
||||
return self
|
||||
|
||||
def _searchForNode(self, value):
|
||||
''' Traverse the tree looking for the node. For BST it is O(logn) if the
|
||||
tree is balanced, otherwise it can be O(n) '''
|
||||
if self.item == value: return self
|
||||
elif value > self.item and self.right: return self.right._findNode(value)
|
||||
elif value < self.item and self.left: return self.left._findNode(value)
|
||||
return None
|
||||
|
||||
|
||||
|
||||
class BinarySearchTree(BinaryTree):
|
||||
'''
|
||||
>>> bst = BinarySearchTree()
|
||||
>>> l1 = [7, 4, 5, 9, 2, 8, 1, 6, 10]
|
||||
>>> for i in l1: bst.addNode(i)
|
||||
>>> bst.hasNode(3)
|
||||
False
|
||||
>>> bst.hasNode(10)
|
||||
True
|
||||
>>> bst.printTree('pre')
|
||||
[7, 4, 2, 1, 5, 6, 9, 8, 10]
|
||||
>>> bst.printTree('post')
|
||||
[1, 2, 6, 5, 4, 8, 10, 9, 7]
|
||||
>>> bst.printTree('in')
|
||||
[1, 2, 4, 5, 6, 7, 8, 9, 10]
|
||||
>>> bst.printTree('bft')
|
||||
[7, 4, 9, 2, 5, 8, 10, 1, 6]
|
||||
>>> bst.getHeight()
|
||||
3
|
||||
>>> bst.isBST()
|
||||
True
|
||||
>>> bst.isBalanced()
|
||||
False
|
||||
>>> bst.isBalanced(2)
|
||||
False
|
||||
>>> bst.getAncestor(2, 9)
|
||||
7
|
||||
>>> bst.getAncestor(2, 9, 'bst')
|
||||
7
|
||||
>>> bst.getAncestor(2, 9, 'pre-post')
|
||||
7
|
||||
>>> bst.getAncestor(2, 9, 'post-in')
|
||||
7
|
||||
'''
|
||||
|
||||
|
||||
def addNode(self, value):
|
||||
''' Add new node to the tree, by the left first, O(n).
|
||||
The only difference from the Binary Tree class is the node class is
|
||||
NodeBST and not NodeBT '''
|
||||
if not self.root: self.root = NodeBST(value)
|
||||
else: self.root._addNextNode(value)
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import doctest
|
||||
doctest.testmod()
|
||||
|
||||
|
|
@ -0,0 +1,464 @@
|
|||
#!/usr/bin/python3
|
||||
# mari von steinkirch 2013
|
||||
# http://astro.sunysb.edu/steinkirch
|
||||
|
||||
|
||||
|
||||
|
||||
''' Implementation of a binary tree and its properties. For example, the following bt:
|
||||
|
||||
1 ---> level 0
|
||||
2 3 ---> level 1
|
||||
4 5 ---> level 2
|
||||
6 7 ---> level 3
|
||||
8 9 ---> level 4
|
||||
|
||||
has the following properties:
|
||||
|
||||
- SIZE OR NUMBER OF NODES: n = 9
|
||||
- NUMBER OF BRANCHES OR INTERNAL NODES: b = n-1 = 8
|
||||
- VALUE OF ROOT = 1
|
||||
- MAX_DEPTH OR HEIGHT: h = 4
|
||||
- IS BALANCED? NO
|
||||
- IS BST? NO
|
||||
- INORDER DFT: 8, 6, 9, 4, 7, 2, 5, 1, 3
|
||||
- POSTORDER DFT: 8, 9, 6, 7, 4, 5, 2, 3, 1
|
||||
- PREORDER DFT: 1, 2, 4, 6, 8, 9, 7, 5, 3
|
||||
- BFT: 1, 2, 3, 4, 5, 6, 7, 8, 9
|
||||
'''
|
||||
|
||||
from collections import deque
|
||||
class NodeBT(object):
|
||||
def __init__(self, item=None, level=0):
|
||||
''' Construtor for a Node in the Tree '''
|
||||
self.item = item
|
||||
self.level = level
|
||||
self.left = None
|
||||
self.right = None
|
||||
self.traversal = []
|
||||
#self.parent = None # not used here but can be necessary for some problems
|
||||
|
||||
'''
|
||||
METHODS TO MODIFY NODES
|
||||
'''
|
||||
|
||||
def _addNextNode(self, value, level_here=1):
|
||||
''' Aux for self.addNode(value)'''
|
||||
self.traversal = []
|
||||
new_node = NodeBT(value, level_here)
|
||||
if not self.item:
|
||||
self.item = new_node
|
||||
elif not self.left:
|
||||
self.left = new_node
|
||||
elif not self.right:
|
||||
self.right = new_node
|
||||
else:
|
||||
self.left = self.left._addNextNode(value, level_here+1)
|
||||
return self
|
||||
|
||||
|
||||
|
||||
'''
|
||||
METHODS TO PRINT/SHOW NODES' ATTRIBUTES
|
||||
'''
|
||||
|
||||
def __repr__(self):
|
||||
''' Private method for this class'string representation'''
|
||||
return '{}'.format(self.item)
|
||||
|
||||
def _getDFTpreOrder(self, node):
|
||||
''' Traversal Pre-Order, O(n)'''
|
||||
if node:
|
||||
if node.item: self.traversal.append(node.item)
|
||||
self._getDFTpreOrder(node.left)
|
||||
self._getDFTpreOrder(node.right)
|
||||
return self
|
||||
|
||||
def _printDFTpreOrder(self, noderoot):
|
||||
''' Fill the pre-order traversal array '''
|
||||
self.traversal = []
|
||||
self._getDFTpreOrder(noderoot)
|
||||
return self.traversal
|
||||
|
||||
def _getDFTinOrder(self, node):
|
||||
''' Traversal in-Order, O(n)'''
|
||||
if node:
|
||||
self._getDFTinOrder(node.left)
|
||||
if node.item: self.traversal.append(node.item)
|
||||
self._getDFTinOrder(node.right)
|
||||
return self
|
||||
|
||||
def _printDFTinOrder(self, noderoot):
|
||||
''' Fill the in-order traversal array '''
|
||||
self.traversal = []
|
||||
self._getDFTinOrder(noderoot)
|
||||
return self.traversal
|
||||
|
||||
def _getDFTpostOrder(self, node):
|
||||
''' Traversal post-Order, O(n)'''
|
||||
if node:
|
||||
self._getDFTpostOrder(node.left)
|
||||
self._getDFTpostOrder(node.right)
|
||||
if node.item: self.traversal.append(node.item)
|
||||
return self
|
||||
|
||||
def _getBFT(self, node):
|
||||
''' Traversal bft, O(n)'''
|
||||
if node:
|
||||
queue = deque()
|
||||
queue.append(node)
|
||||
while len(queue) > 0:
|
||||
current = queue.popleft()
|
||||
if current.item: self.traversal.append(current)
|
||||
if current.left: queue.append(current.left)
|
||||
if current.right: queue.append(current.right)
|
||||
return self
|
||||
|
||||
def _printBFT(self, noderoot):
|
||||
''' Fill the in-order traversal array '''
|
||||
self.traversal = []
|
||||
self._getBFT(noderoot)
|
||||
return self.traversal
|
||||
|
||||
|
||||
def _printDFTpostOrder(self, noderoot):
|
||||
''' Fill the post-order traversal array '''
|
||||
self.traversal = []
|
||||
self._getDFTpostOrder(noderoot)
|
||||
return self.traversal
|
||||
|
||||
def _searchForNode(self, value):
|
||||
''' Traverse the tree looking for the node'''
|
||||
if self.item == value: return self
|
||||
else:
|
||||
found = None
|
||||
if self.left: found = self.left._searchForNode(value)
|
||||
if self.right: found = found or self.right._searchForNode(value)
|
||||
return found
|
||||
|
||||
def _findNode(self, value):
|
||||
''' Find whether a node is in the tree.
|
||||
if the traversal was calculated, it is just a membership
|
||||
checking, which is O(1), otherwise it is necessary to traverse
|
||||
the binary tree, so best case is O(1) and worst is O(n). '''
|
||||
if self.traversal: return value in self.traversal
|
||||
else: return self._searchForNode(value)
|
||||
|
||||
def _isLeaf(self):
|
||||
''' Return True if the node is a leaf '''
|
||||
return not self.right and not self.left
|
||||
|
||||
def _getMaxHeight(self):
|
||||
''' Get the max height at the node, O(n)'''
|
||||
levelr, levell = 0, 0
|
||||
if self.right:
|
||||
levelr = self.right._getMaxHeight() + 1
|
||||
if self.left:
|
||||
levell = self.left._getMaxHeight() + 1
|
||||
return max(levelr, levell)
|
||||
|
||||
def _getMinHeight(self, level=0):
|
||||
''' Get the min height at the node, O(n)'''
|
||||
levelr, levell = -1, -1
|
||||
if self.right:
|
||||
levelr = self.right._getMinHeight(level +1)
|
||||
if self.left:
|
||||
levell = self.left._getMinHeight(level +1)
|
||||
return min(levelr, levell) + 1
|
||||
|
||||
def _isBalanced(self):
|
||||
''' Find whether the tree is balanced, by calculating heights first, O(n2) '''
|
||||
if self._getMaxHeight() - self._getMinHeight() < 2:
|
||||
return False
|
||||
else:
|
||||
if self._isLeaf():
|
||||
return True
|
||||
elif self.left and self.right:
|
||||
return self.left._isBalanced() and self.right._isBalanced()
|
||||
elif not self.left and self.right:
|
||||
return self.right._isBalanced()
|
||||
elif not self.right and self.left:
|
||||
return self.right._isBalanced()
|
||||
|
||||
|
||||
|
||||
def _isBalancedImproved(self):
|
||||
''' Find whehter the tree is balanced in each node, O(n) '''
|
||||
return 'To Be written'
|
||||
|
||||
''' There are two solutions to check whether a bt is a bst:
|
||||
(1) Do an inorder, check if the inorder is sorted. However inorder
|
||||
can't handle the difference between duplicate values on the left
|
||||
or on the right (if it is in the right, the tree is not bst).
|
||||
'''
|
||||
|
||||
|
||||
def _isBST(self):
|
||||
''' Find whether the tree is a BST, inorder '''
|
||||
if self.item:
|
||||
if self._isLeaf(): return True
|
||||
elif self.left:
|
||||
if self.left.item < self.item: return self.left._isBST()
|
||||
else: return False
|
||||
elif self.right:
|
||||
if self.right.item > self.item: return self.right._isBST()
|
||||
else: return False
|
||||
else:
|
||||
raise Exception('Tree is empty')
|
||||
|
||||
|
||||
def _getAncestorBST(self, n1, n2):
|
||||
''' Return the ancestor of two nodes if it is a bst.
|
||||
we are supposing the values in the tree are unique.'''
|
||||
if n1 == self.item or n2 == self.item : return self.item
|
||||
elif self.item < n1 and self.item < n2:
|
||||
self.right.getAncestorBST(n1, n2)
|
||||
elif self.item > n1 and self.item > n2:
|
||||
self.left.getAncestorBST(n1, n2)
|
||||
else:
|
||||
return self.item
|
||||
|
||||
|
||||
|
||||
|
||||
class BinaryTree(object):
|
||||
'''
|
||||
>>> bt = BinaryTree()
|
||||
>>> for i in range(1, 10): bt.addNode(i)
|
||||
>>> bt.hasNode(7)
|
||||
True
|
||||
>>> bt.hasNode(12)
|
||||
False
|
||||
>>> bt.printTree()
|
||||
[1, 2, 4, 6, 8, 9, 7, 5, 3]
|
||||
>>> bt.printTree('pre')
|
||||
[1, 2, 4, 6, 8, 9, 7, 5, 3]
|
||||
>>> bt.printTree('bft')
|
||||
[1, 2, 3, 4, 5, 6, 7, 8, 9]
|
||||
>>> bt.printTree('post')
|
||||
[8, 9, 6, 7, 4, 5, 2, 3, 1]
|
||||
>>> bt.printTree('in')
|
||||
[8, 6, 9, 4, 7, 2, 5, 1, 3]
|
||||
>>> bt.hasNode(9)
|
||||
True
|
||||
>>> bt.hasNode(11)
|
||||
False
|
||||
>>> bt.isLeaf(8)
|
||||
True
|
||||
>>> bt.getNodeLevel(1)
|
||||
0
|
||||
>>> bt.getNodeLevel(8)
|
||||
4
|
||||
>>> bt.getSizeTree()
|
||||
9
|
||||
>>> bt.isRoot(10)
|
||||
False
|
||||
>>> bt.isRoot(1)
|
||||
True
|
||||
>>> bt.getHeight()
|
||||
4
|
||||
>>> bt.isBST(1)
|
||||
False
|
||||
>>> bt.isBalanced()
|
||||
False
|
||||
>>> bt.isBalanced(2)
|
||||
False
|
||||
>>> bt.getAncestor(8, 5)
|
||||
2
|
||||
>>> bt.getAncestor(8, 5, 'pre-post')
|
||||
2
|
||||
>>> bt.getAncestor(8, 5, 'post-in')
|
||||
2
|
||||
'''
|
||||
|
||||
|
||||
|
||||
def __init__(self):
|
||||
''' Construtor for the Binary Tree, which is a container of Nodes'''
|
||||
self.root = None
|
||||
|
||||
|
||||
'''
|
||||
METHODS TO MODIFY THE TREE
|
||||
'''
|
||||
|
||||
def addNode(self, value):
|
||||
''' Add new node to the tree, by the left first, O(n) '''
|
||||
if not self.root: self.root = NodeBT(value)
|
||||
else: self.root._addNextNode(value)
|
||||
|
||||
'''
|
||||
METHODS TO PRINT/SHOW TREES' ATTRIBUTES
|
||||
'''
|
||||
|
||||
def __repr__(self):
|
||||
''' Private method for this class'string representation'''
|
||||
return '{}'.format(self.item)
|
||||
|
||||
def printTree(self, order = 'pre'):
|
||||
''' Print Tree in the chosen order '''
|
||||
if self.root:
|
||||
if order == 'pre': return self.root._printDFTpreOrder(self.root)
|
||||
elif order == 'in': return self.root._printDFTinOrder(self.root)
|
||||
elif order == 'post': return self.root._printDFTpostOrder(self.root)
|
||||
elif order == 'bft': return self.root._printBFT(self.root)
|
||||
else: raise Exception('Tree is empty')
|
||||
|
||||
def hasNode(self, value):
|
||||
''' Verify whether the node is in the Tree '''
|
||||
return bool(self.root._findNode(value))
|
||||
|
||||
def isLeaf(self, value):
|
||||
''' Return True if the node is a Leaf '''
|
||||
node = self.root._searchForNode(value)
|
||||
return node._isLeaf()
|
||||
|
||||
def getNodeLevel(self, item):
|
||||
''' Return the level of the node, best O(1), worst O(n) '''
|
||||
node = self.root._searchForNode(item)
|
||||
if node: return node.level
|
||||
else: raise Exception('Node not found')
|
||||
|
||||
def getSizeTree(self):
|
||||
''' Return how many nodes in the tree, O(n) '''
|
||||
return len(self.root._printDFTpreOrder(self.root))
|
||||
|
||||
def isRoot(self, value):
|
||||
'''Return the root of the tree '''
|
||||
return self.root.item == value
|
||||
|
||||
def getHeight(self):
|
||||
''' Returns the height/depth of the tree, best/worst O(n) '''
|
||||
return self.root._getMaxHeight()
|
||||
|
||||
def isBalanced(self, method=1):
|
||||
''' Return True if the tree is balanced'''
|
||||
if method == 1:
|
||||
''' O(n2)'''
|
||||
return self.root._isBalanced()
|
||||
else:
|
||||
''' O(n)'''
|
||||
return self.root._isBalancedImproved()
|
||||
|
||||
|
||||
|
||||
''' The followin methods are for searching the lowest common ancestor
|
||||
in a BT. Since a simple BT does not have ordering, it can be O(n). If
|
||||
we have a link for the ancestors, the steps are:
|
||||
(1) search both trees in order to find the nodes separately
|
||||
(2) list all ancestors
|
||||
(3) find first that mach
|
||||
obs: if we do this too many times we can do a pre and use the methods here'''
|
||||
|
||||
def isBST(self, method=1):
|
||||
''' Return True if the tree is BST'''
|
||||
if method == 1:
|
||||
inorder = self.root._printDFTinOrder(self.root)
|
||||
return inorder == sorted(inorder)
|
||||
elif method == 2:
|
||||
return self.root._isBST()
|
||||
|
||||
|
||||
def _getAncestorPreIn(self, preorder, inorder, value1, value2):
|
||||
''' Return the ancestor of two nodes with pre and in'''
|
||||
root = preorder[0]
|
||||
preorder = preorder[1:]
|
||||
i = 0
|
||||
item = inorder[0]
|
||||
value1left, value2left = False, False
|
||||
while item != root and i < len(inorder):
|
||||
if item == value1: value1left = True
|
||||
elif item == value2: value2left = True
|
||||
i += 1
|
||||
item = inorder[i]
|
||||
if (value1left and not value2left) or (value2left and not value1left):
|
||||
return root
|
||||
else:
|
||||
return self._getAncestorPreIn(preorder, inorder[:i] + inorder[i+1:], value1, value2)
|
||||
|
||||
def _getAncestorPrePost(self, preorder, postorder, value1, value2):
|
||||
''' Return the ancestor of two nodes with pre and post'''
|
||||
root = preorder[0]
|
||||
preorder = preorder[1:]
|
||||
postorder = postorder[:-1]
|
||||
value1right, value2right = False, False
|
||||
i = len(postorder)-1
|
||||
itempre = preorder[0]
|
||||
itempos = postorder[i]
|
||||
while itempre != itempos and i > 0:
|
||||
if itempos == value1: value1right = True
|
||||
elif itempos == value2: value2right = True
|
||||
i -= 1
|
||||
itempos = postorder[i]
|
||||
|
||||
if (value1right and not value2right) or (value2right and not value1right):
|
||||
return root
|
||||
else:
|
||||
return self._getAncestorPrePost(preorder, postorder[:i] + postorder[i+1:], value1, value2)
|
||||
|
||||
def _getAncestorInPost(self, inorder, postorder, value1, value2):
|
||||
''' Return the ancestor of two nodes with in and post'''
|
||||
root = postorder[-1]
|
||||
postorder = postorder[:-1]
|
||||
value1left, value2left = False, False
|
||||
i = 0
|
||||
item = inorder[i]
|
||||
while item != root and i < len(inorder):
|
||||
if item == value1: value1left = True
|
||||
elif item == value2: value2left = True
|
||||
i += 1
|
||||
item = inorder[i]
|
||||
|
||||
if (value1left and not value2left) or (value2left and not value1left):
|
||||
return root
|
||||
else:
|
||||
return self._getAncestorInPost(postorder, inorder[:i] + inorder[i+1:], value1, value2)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def _getAncestorBST2(self, preorder, value1, value2):
|
||||
''' Return the ancestor of two nodes if it is a bst, using traversal'''
|
||||
while preorder:
|
||||
current = preorder[0]
|
||||
if current < value1:
|
||||
try: preorder = preorder[2:]
|
||||
except: return current
|
||||
elif current > value2:
|
||||
try: preorder = preorder[1:]
|
||||
except: return current
|
||||
elif value1 <= current <= value2:
|
||||
return current
|
||||
return None
|
||||
|
||||
def getAncestor(self, value1, value2, method='pre-in'):
|
||||
''' Return the commom ancestor for two nodes'''
|
||||
if method == 'pre-in':
|
||||
''' Using pre and inorder, best/worst O(n)'''
|
||||
preorder = self.root._printDFTpreOrder(self.root)
|
||||
inorder = self.root._printDFTinOrder(self.root)
|
||||
return self._getAncestorPreIn(preorder, inorder, value1, value2)
|
||||
if method == 'pre-post':
|
||||
''' Using pre and postorder, best/worst O(n)'''
|
||||
preorder = self.root._printDFTpreOrder(self.root)
|
||||
postorder = self.root._printDFTpostOrder(self.root)
|
||||
return self._getAncestorPrePost(preorder, postorder, value1, value2)
|
||||
if method == 'post-in':
|
||||
''' Using in and postorder, best/worst O(n)'''
|
||||
inorder = self.root._printDFTinOrder(self.root)
|
||||
postorder = self.root._printDFTpostOrder(self.root)
|
||||
return self._getAncestorInPost(inorder, postorder, value1, value2)
|
||||
if method == 'bst':
|
||||
if self.isBST():
|
||||
return self.root._getAncestorBST(value1, value2)
|
||||
|
||||
#preorder = self.root._printDFTpreOrder(self.root)
|
||||
#return self._getAncestorBST2(preorder, value1, value2)
|
||||
else:
|
||||
return Exception('The tree is not a BST')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import doctest
|
||||
doctest.testmod()
|
||||
|
|
@ -0,0 +1,131 @@
|
|||
#!/usr/bin/python3
|
||||
# mari von steinkirch @2013
|
||||
# steinkirch at gmail
|
||||
|
||||
from BST import BST
|
||||
|
||||
|
||||
from collections import deque
|
||||
class TranversalBST(object):
|
||||
def __init__(self):
|
||||
self.bst = BST(None)
|
||||
self.nodes = []
|
||||
|
||||
def insert(self, value):
|
||||
if not self.bst.value:
|
||||
self.bst.value = value
|
||||
else:
|
||||
self.bst.insert(value)
|
||||
|
||||
def contains(self, value):
|
||||
return bool(self.bst.find(value))
|
||||
|
||||
def get(self, index):
|
||||
for i, value in enumerate(self.inorder()):
|
||||
if i == index:
|
||||
return value
|
||||
|
||||
def inorder(self):
|
||||
current = self.bst
|
||||
self.nodes = []
|
||||
stack = []
|
||||
while len(stack) > 0 or current is not None:
|
||||
if current is not None:
|
||||
stack.append(current)
|
||||
current = current.left
|
||||
else:
|
||||
current = stack.pop()
|
||||
self.nodes.append(current.value)
|
||||
current = current.right
|
||||
return self.nodes
|
||||
|
||||
|
||||
def preorder(self):
|
||||
self.nodes = []
|
||||
stack = [self.bst]
|
||||
while len(stack) > 0:
|
||||
curr = stack.pop()
|
||||
if curr is not None:
|
||||
self.nodes.append(curr.value)
|
||||
stack.append(curr.right)
|
||||
stack.append(curr.left)
|
||||
return self.nodes
|
||||
|
||||
|
||||
def preorder2(self):
|
||||
self.nodes = []
|
||||
current = self.bst
|
||||
stack = []
|
||||
while len(stack) > 0 or current is not None:
|
||||
if current is not None:
|
||||
self.nodes.append(current.value)
|
||||
stack.append(current)
|
||||
current = current.left
|
||||
else:
|
||||
current = stack.pop()
|
||||
current = current.right
|
||||
return self.nodes
|
||||
|
||||
|
||||
|
||||
def preorder3(self):
|
||||
self.nodes = []
|
||||
node = self.bst
|
||||
if not node: return None
|
||||
stack = []
|
||||
stack.append(node)
|
||||
while stack:
|
||||
node = stack.pop()
|
||||
self.nodes.append(node.value)
|
||||
if node.right: stack.append(node.right) # RIGHT FIRST!
|
||||
if node.left: stack.append(node.left)
|
||||
return self.nodes
|
||||
|
||||
|
||||
|
||||
|
||||
def BFT(self):
|
||||
self.nodes = []
|
||||
node = self.bst
|
||||
if not node: return None
|
||||
queue = deque()
|
||||
queue.append(node)
|
||||
while queue:
|
||||
node = queue.popleft()
|
||||
self.nodes.append(node.value)
|
||||
if node.left: queue.append(node.left) # LEFT FIRST!
|
||||
if node.right: queue.append(node.right)
|
||||
|
||||
return self.nodes
|
||||
|
||||
|
||||
|
||||
|
||||
def main():
|
||||
"""
|
||||
10
|
||||
5 15
|
||||
1 6 11 50
|
||||
"""
|
||||
t = TranversalBST()
|
||||
t.insert(10)
|
||||
t.insert(5)
|
||||
t.insert(15)
|
||||
t.insert(1)
|
||||
t.insert(6)
|
||||
t.insert(11)
|
||||
t.insert(50)
|
||||
print(t.preorder())
|
||||
print(t.preorder2())
|
||||
print(t.preorder3())
|
||||
print(t.inorder())
|
||||
print(t.BFT())
|
||||
'''
|
||||
[10, 5, 1, 6, 15, 11, 50]
|
||||
[10, 5, 1, 6, 15, 11, 50]
|
||||
[10, 5, 1, 6, 15, 11, 50]
|
||||
[1, 5, 6, 10, 11, 15, 50]
|
||||
[10, 5, 15, 1, 6, 11, 50]
|
||||
'''
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
44
src/further_examples/project_euler/amicable_numbers.py
Normal file
44
src/further_examples/project_euler/amicable_numbers.py
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
#!/usr/bin/python3
|
||||
# mari von steinkirch @2013
|
||||
# steinkirch at gmail
|
||||
|
||||
'''
|
||||
Let d(n) be defined as the sum of proper divisors of n (numbers less than n which divide evenly into n).
|
||||
If d(a) = b and d(b) = a, where a b, then a and b are an amicable pair and each of a and b are called amicable numbers.
|
||||
|
||||
For example, the proper divisors of 220 are 1, 2, 4, 5, 10, 11, 20, 22, 44, 55 and 110; therefore d(220) = 284. The proper divisors of 284 are 1, 2, 4, 71 and 142; so d(284) = 220.
|
||||
|
||||
Evaluate the sum of all the amicable numbers under 10000.
|
||||
'''
|
||||
|
||||
def find_sum_proper_divisors(n):
|
||||
sum_proper_div = 0
|
||||
for i in range(1, n):
|
||||
if n%i == 0:
|
||||
sum_proper_div += i
|
||||
return sum_proper_div
|
||||
|
||||
|
||||
def amicable_numbers(N):
|
||||
sum_div_list = [find_sum_proper_divisors(i) for i in range(1, N+1)]
|
||||
sum_amicable_numbers = 0
|
||||
set_div = set()
|
||||
for a in range(1, N):
|
||||
da = sum_div_list[a-1]
|
||||
if da < N:
|
||||
b = da
|
||||
db = sum_div_list[b-1]
|
||||
if a != b and db == a and a not in set_div and b not in set_div:
|
||||
sum_amicable_numbers += a + b
|
||||
set_div.add(a)
|
||||
set_div.add(b)
|
||||
return sum_amicable_numbers
|
||||
|
||||
|
||||
def main():
|
||||
print(amicable_numbers(10000))
|
||||
print('Tests Passed!')
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
91
src/further_examples/project_euler/circular_primes.py
Normal file
91
src/further_examples/project_euler/circular_primes.py
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
#!/usr/bin/python3
|
||||
# mari von steinkirch @2013
|
||||
# steinkirch at gmail
|
||||
|
||||
def isPrime(n):
|
||||
n = abs(int(n))
|
||||
if n < 2:
|
||||
return False
|
||||
if n == 2:
|
||||
return True
|
||||
for x in range(2, int(n**0.5)+1):
|
||||
if n%x == 0:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def findPermutations(s):
|
||||
res = []
|
||||
if len(s) == 1:
|
||||
res.append(s)
|
||||
else:
|
||||
for i, c in enumerate(s):
|
||||
for perm in findPermutations(s[:i] + s[i+1:]):
|
||||
res.append(c + perm)
|
||||
return res
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def isCircular(n):
|
||||
n_str = str(n)
|
||||
permutations = findPermutations(n_str)
|
||||
for perm in permutations:
|
||||
if not isPrime(perm):
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
|
||||
def generatePrimes(n):
|
||||
if n == 2: return [2]
|
||||
elif n < 2: return []
|
||||
s = [i for i in range(3, n+1, 2)]
|
||||
mroot = n ** 0.5
|
||||
half = (n+1)//2 - 1
|
||||
i, m = 0, 3
|
||||
while m <= mroot:
|
||||
if s[i]:
|
||||
j = (m*m-3)//2
|
||||
s[j] = 0
|
||||
while j < half:
|
||||
s[j] = 0
|
||||
j += m
|
||||
i = i+1
|
||||
m = 2*i+3
|
||||
return [2]+[x for x in s if x]
|
||||
|
||||
|
||||
def generate_n_Primes(n):
|
||||
primes = []
|
||||
chkthis = 2
|
||||
while len(primes) < n:
|
||||
ptest = [chkthis for i in primes if chkthis%i == 0]
|
||||
primes += [] if ptest else [chkthis]
|
||||
chkthis += 1
|
||||
return primes
|
||||
|
||||
|
||||
|
||||
def circular_primes(n):
|
||||
primes = generatePrimes(n)
|
||||
count = 0
|
||||
for prime in primes:
|
||||
if isCircular(prime):
|
||||
count += 1
|
||||
return count
|
||||
|
||||
|
||||
def main():
|
||||
import time
|
||||
start = time.time()
|
||||
|
||||
print(circular_primes(1000000))
|
||||
|
||||
elapsed = (time.time() - start)
|
||||
print('Tests Passed!\n It took %s seconds to run them.' % (elapsed))
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
65
src/further_examples/project_euler/counting_sundays.py
Normal file
65
src/further_examples/project_euler/counting_sundays.py
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
#!/usr/bin/python3
|
||||
# mari von steinkirch @2013
|
||||
# steinkirch at gmail
|
||||
|
||||
'''
|
||||
1 Jan 1900 was a Monday.
|
||||
Thirty days has September,
|
||||
April, June and November.
|
||||
All the rest have thirty-one,
|
||||
Saving February alone,
|
||||
Which has twenty-eight, rain or shine.
|
||||
And on leap years, twenty-nine.
|
||||
A leap year occurs on any year evenly divisible by 4, but not on a century unless it is divisible by 400.
|
||||
How many Sundays fell on the first of the month during the twentieth century (1 Jan 1901 to 31 Dec 2000)?
|
||||
'''
|
||||
|
||||
|
||||
def find_if_leap_year(y):
|
||||
if (y%4 == 0 and y%100 != 0) or (y%400 == 0):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def counting_sundays():
|
||||
''' define variables '''
|
||||
days_year = 7*31 + 4*30 + 28
|
||||
count_sundays = 0
|
||||
days_week = 7
|
||||
dict_week = {0: 'mon', 1:'tue', 2:'wed', 3:'thu', 4:'fri', 5:'sat', 6:'sun'}
|
||||
|
||||
|
||||
''' with info from 1900 find first day for 1901 '''
|
||||
first_day = days_year%days_week # not a leap year
|
||||
|
||||
for y in range (1901, 2001):
|
||||
leap_year = find_if_leap_year(y)
|
||||
days_count = first_day
|
||||
|
||||
for m in range(1, 13):
|
||||
if days_count%7 == 6:
|
||||
count_sundays += 1
|
||||
if m == 2:
|
||||
if leap_year:
|
||||
days_count += 29
|
||||
else:
|
||||
days_count += 28
|
||||
elif m == 4 or m == 6 or m == 9 or m == 11:
|
||||
days_count += 30
|
||||
else:
|
||||
days_count += 31
|
||||
|
||||
if leap_year: first_day = (first_day +2)%days_week
|
||||
else: first_day = (first_day +1)%days_week
|
||||
|
||||
return count_sundays
|
||||
|
||||
|
||||
|
||||
def main():
|
||||
print(counting_sundays())
|
||||
print('Tests Passed!')
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
30
src/further_examples/project_euler/digit_fifth_pow.py
Normal file
30
src/further_examples/project_euler/digit_fifth_pow.py
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
#!/usr/bin/python3
|
||||
# mari von steinkirch @2013
|
||||
# steinkirch at gmail
|
||||
|
||||
def digit_fifth_pow(n):
|
||||
lnum = []
|
||||
for num in range(10**(2), 10**(n+2)):
|
||||
sum_here = 0
|
||||
num_str = str(num)
|
||||
for i in num_str:
|
||||
num_int = int(i)
|
||||
num_int_pow = num_int**n
|
||||
sum_here += num_int_pow
|
||||
if sum_here == num:
|
||||
lnum.append(num)
|
||||
return lnum, sum(lnum)
|
||||
|
||||
|
||||
def main():
|
||||
import time
|
||||
start = time.time()
|
||||
|
||||
print(digit_fifth_pow(5))
|
||||
|
||||
elapsed = (time.time() - start)
|
||||
print('Tests Passed!\n It took %s seconds to run them.' % (elapsed))
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
27
src/further_examples/project_euler/dist_pow.py
Normal file
27
src/further_examples/project_euler/dist_pow.py
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
#!/usr/bin/python3
|
||||
# mari von steinkirch @2013
|
||||
# steinkirch at gmail
|
||||
|
||||
def dist_pow(a1, a2, b1, b2):
|
||||
set1 = set()
|
||||
for a in range(a1, a2 + 1):
|
||||
for b in range(b1, b2 + 1):
|
||||
set1.add(a**b)
|
||||
return len(set1)
|
||||
|
||||
|
||||
|
||||
|
||||
def main():
|
||||
import time
|
||||
start = time.time()
|
||||
|
||||
print(dist_pow(2, 5, 2, 5))
|
||||
print(dist_pow(2, 100, 2, 100))
|
||||
|
||||
elapsed = (time.time() - start)
|
||||
print('Tests Passed!\n It took %s seconds to run them.' % (elapsed))
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
18
src/further_examples/project_euler/even_fib_num.py
Normal file
18
src/further_examples/project_euler/even_fib_num.py
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
#!/usr/bin/python3
|
||||
# mari von steinkirch @2013
|
||||
# steinkirch at gmail
|
||||
|
||||
|
||||
def even_fib_num(limit):
|
||||
a, b = 0, 1
|
||||
while a < limit:
|
||||
yield a
|
||||
a, b = b, a + b
|
||||
|
||||
def main():
|
||||
print(sum(n for n in even_fib_num(4e6) if not (n & 1)))
|
||||
print('Tests Passed!')
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
32
src/further_examples/project_euler/factorial.py
Normal file
32
src/further_examples/project_euler/factorial.py
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
#!/usr/bin/python3
|
||||
# mari von steinkirch @2013
|
||||
# steinkirch at gmail
|
||||
|
||||
def factorial(n):
|
||||
prod = 1
|
||||
for i in range(1,n):
|
||||
prod *= i
|
||||
return prod
|
||||
|
||||
def find_sum(n):
|
||||
sum_ = 0
|
||||
fact = factorial(n)
|
||||
number = str(fact)
|
||||
for i in number:
|
||||
sum_ += int(i)
|
||||
return sum_
|
||||
|
||||
|
||||
def main():
|
||||
import time
|
||||
start = time.time()
|
||||
|
||||
assert(find_sum(10) == 27)
|
||||
print(find_sum(100))
|
||||
|
||||
elapsed = (time.time() - start)
|
||||
print('Tests Passed!\n It took %s seconds to run them.' % (elapsed))
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
32
src/further_examples/project_euler/findstprime.py
Normal file
32
src/further_examples/project_euler/findstprime.py
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
#!/usr/bin/python3
|
||||
# mari von steinkirch @2013
|
||||
# steinkirch at gmail
|
||||
|
||||
import math
|
||||
|
||||
def is_prime(number, prime_set):
|
||||
if number in prime_set: return True
|
||||
for i in range(2, int(math.sqrt(number)) + 1):
|
||||
if not number%i: return False
|
||||
return True
|
||||
|
||||
|
||||
def findstprime(n):
|
||||
count = 0
|
||||
candidate = 1
|
||||
prime_set = set()
|
||||
while count < n:
|
||||
candidate +=1
|
||||
if is_prime(candidate, prime_set):
|
||||
prime_set.add(candidate)
|
||||
count += 1
|
||||
return candidate
|
||||
|
||||
def main():
|
||||
assert(findstprime(6 == 13))
|
||||
print(findstprime(10001))
|
||||
print('Tests Passed!')
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
64
src/further_examples/project_euler/gold_other.py
Normal file
64
src/further_examples/project_euler/gold_other.py
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
#!/usr/bin/python3
|
||||
# mari von steinkirch @2013
|
||||
# steinkirch at gmail
|
||||
|
||||
def isPrime(n):
|
||||
n = abs(int(n))
|
||||
if n < 2:
|
||||
return False
|
||||
if n == 2:
|
||||
return True
|
||||
if not n & 1:
|
||||
return False
|
||||
for x in range(3, int(n**0.5)+1, 2):
|
||||
if n % x == 0:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def generetePrimes(n):
|
||||
if n == 2: return [2]
|
||||
elif n < 2: return []
|
||||
s = [i for i in range(3, n+1,2)]
|
||||
mroot = n ** 0.5
|
||||
half = (n+1)//2-1
|
||||
i = 0
|
||||
m = 3
|
||||
while m <= mroot:
|
||||
if s[i]:
|
||||
j = (m*m - 3)//2
|
||||
s[j] = 0
|
||||
while j < half:
|
||||
s[j] = 0
|
||||
j += m
|
||||
i = i+1
|
||||
m = 2*i+3
|
||||
return [2]+[x for x in s if x]
|
||||
|
||||
|
||||
def gold_other(n):
|
||||
primes_for_n = generetePrimes(n)
|
||||
numbers = {prime + 2*x**2 for prime in primes_for_n for x in range(1, int(n**0.5))}
|
||||
conj = {x for x in range(3, n, 2) if not isPrime(x)}
|
||||
|
||||
while True:
|
||||
candidates = conj - numbers
|
||||
if not candidates:
|
||||
gold_other(2*n)
|
||||
else:
|
||||
return min(candidates)
|
||||
|
||||
|
||||
|
||||
def main():
|
||||
import time
|
||||
start = time.time()
|
||||
|
||||
print(gold_other(10000))
|
||||
|
||||
elapsed = (time.time() - start)
|
||||
print('Tests Passed!\n It took %s seconds to run them.' % (elapsed))
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
#!/usr/bin/python3
|
||||
# mari von steinkirch @2013
|
||||
# steinkirch at gmail
|
||||
|
||||
import math
|
||||
|
||||
def find_div(n):
|
||||
''' find the divisor of a given n'''
|
||||
set_div = {1, n}
|
||||
for i in range(2, int(math.sqrt(n))+ 1):
|
||||
if not n % i:
|
||||
set_div.add(i)
|
||||
set_div.add(n//i)
|
||||
l1 = list(set_div)
|
||||
return len(l1)
|
||||
|
||||
|
||||
def find_trian(l):
|
||||
''' find the lth trian number'''
|
||||
return sum(range(1, l+1))
|
||||
|
||||
|
||||
def highly_divisible_trian_num(d):
|
||||
thtriangle, n_div, count = 1, 0, 1
|
||||
while n_div < d:
|
||||
count += 1
|
||||
thtriangle += count
|
||||
n_div = find_div(thtriangle)
|
||||
return (thtriangle, count)
|
||||
|
||||
|
||||
def main():
|
||||
import time
|
||||
start = time.time()
|
||||
assert(highly_divisible_trian_num(6) == (28, 7))
|
||||
print(highly_divisible_trian_num(500))
|
||||
|
||||
elapsed = (time.time() - start)
|
||||
print('Tests Passed!\n It took %s seconds to run them.' % (elapsed))
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
47
src/further_examples/project_euler/larg_palindrome.py
Normal file
47
src/further_examples/project_euler/larg_palindrome.py
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
#!/usr/bin/python3
|
||||
# mari von steinkirch @2013
|
||||
# steinkirch at gmail
|
||||
|
||||
|
||||
|
||||
def is_palindrome(s):
|
||||
return s == reverse(s)
|
||||
|
||||
def reverse(s):
|
||||
rev = 0
|
||||
while s > 0:
|
||||
rev = 10*rev + s%10
|
||||
s = s//10
|
||||
return rev
|
||||
|
||||
|
||||
def is_palindrome_2(s):
|
||||
# to use it you need to cast str() first
|
||||
while s:
|
||||
if s[0] != s[-1]: return False
|
||||
else:
|
||||
s = s[1:-1]
|
||||
is_palindrome(s)
|
||||
return True
|
||||
|
||||
|
||||
def larg_palind_product(n):
|
||||
nmax, largpal = 9, 0
|
||||
for i in range(1, n):
|
||||
nmax += 9*10**i
|
||||
for i in range(nmax, nmax//2, -1):
|
||||
for j in range(i -1, (i -1)//2, -1):
|
||||
candidate = i*j
|
||||
if is_palindrome(candidate) and candidate > largpal:
|
||||
largpal = candidate
|
||||
return largpal
|
||||
|
||||
|
||||
def test_larg_palind_product():
|
||||
assert(larg_palind_product(2)== 9009)
|
||||
print(larg_palind_product(3))
|
||||
print('Tests Passed!')
|
||||
|
||||
if __name__ == '__main__':
|
||||
test_larg_palind_product()
|
||||
|
||||
20
src/further_examples/project_euler/larg_prod_grid.dat
Normal file
20
src/further_examples/project_euler/larg_prod_grid.dat
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
08 02 22 97 38 15 00 40 00 75 04 05 07 78 52 12 50 77 91 08
|
||||
49 49 99 40 17 81 18 57 60 87 17 40 98 43 69 48 04 56 62 00
|
||||
81 49 31 73 55 79 14 29 93 71 40 67 53 88 30 03 49 13 36 65
|
||||
52 70 95 23 04 60 11 42 69 24 68 56 01 32 56 71 37 02 36 91
|
||||
22 31 16 71 51 67 63 89 41 92 36 54 22 40 40 28 66 33 13 80
|
||||
24 47 32 60 99 03 45 02 44 75 33 53 78 36 84 20 35 17 12 50
|
||||
32 98 81 28 64 23 67 10 26 38 40 67 59 54 70 66 18 38 64 70
|
||||
67 26 20 68 02 62 12 20 95 63 94 39 63 08 40 91 66 49 94 21
|
||||
24 55 58 05 66 73 99 26 97 17 78 78 96 83 14 88 34 89 63 72
|
||||
21 36 23 09 75 00 76 44 20 45 35 14 00 61 33 97 34 31 33 95
|
||||
78 17 53 28 22 75 31 67 15 94 03 80 04 62 16 14 09 53 56 92
|
||||
16 39 05 42 96 35 31 47 55 58 88 24 00 17 54 24 36 29 85 57
|
||||
86 56 00 48 35 71 89 07 05 44 44 37 44 60 21 58 51 54 17 58
|
||||
19 80 81 68 05 94 47 69 28 73 92 13 86 52 17 77 04 89 55 40
|
||||
04 52 08 83 97 35 99 16 07 97 57 32 16 26 26 79 33 27 98 66
|
||||
88 36 68 87 57 62 20 72 03 46 33 67 46 55 12 32 63 93 53 69
|
||||
04 42 16 73 38 25 39 11 24 94 72 18 08 46 29 32 40 62 76 36
|
||||
20 69 36 41 72 30 23 88 34 62 99 69 82 67 59 85 74 04 36 16
|
||||
20 73 35 29 78 31 90 01 74 31 49 71 48 86 81 16 23 57 05 54
|
||||
01 70 54 71 83 51 54 69 16 92 33 48 61 43 52 01 89 19 67 48
|
||||
66
src/further_examples/project_euler/larg_prod_grid.py
Normal file
66
src/further_examples/project_euler/larg_prod_grid.py
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
#!/usr/bin/python3
|
||||
# mari von steinkirch @2013
|
||||
# steinkirch at gmail
|
||||
|
||||
import string
|
||||
|
||||
def get_grid(filename):
|
||||
grid = [ [ 0 for i in range(20) ] for j in range(20) ]
|
||||
with open(filename) as file:
|
||||
for row, line in enumerate(file):
|
||||
line.strip('\n')
|
||||
for collumn, number in enumerate(line.split(' ')):
|
||||
grid[row][collumn] = int(number)
|
||||
return grid
|
||||
|
||||
|
||||
def larg_prod_grid(grid):
|
||||
row, col, larg_prod = 0, 0, 0
|
||||
up, down, left, right, diag1, diag2, diag3, diag4 = 0, 0, 0, 0, 0, 0, 0, 0
|
||||
while row < len(grid):
|
||||
while col < len(grid[0]):
|
||||
if col > 2:
|
||||
up = grid[row][col] * grid[row][col-1] * grid[row][col-2] * grid[row][col-3]
|
||||
if col < len(grid[0]) - 3:
|
||||
down = grid[row][col] * grid[row][col+1] * grid[row][col+2] * grid[row][col+3]
|
||||
if row > 2:
|
||||
left = grid[row][col] * grid[row-1][col] * grid[row-2][col] * grid[row-3][col]
|
||||
if row < len(grid) - 3:
|
||||
right = grid[row][col] * grid[row+1][col] * grid[row+2][col] * grid[row+3][col]
|
||||
|
||||
if col > 2 and row > 2:
|
||||
diag1 = grid[row][col] * grid[row-1][col-1] * grid[row-2][col-2] * grid[row-3][col-3]
|
||||
if col > 2 and row < len(grid) - 3:
|
||||
diag2 = grid[row][col] * grid[row+1][col-1] * grid[row+2][col-2] * grid[row+3][col-3]
|
||||
|
||||
if col < len(grid[0]) - 3 and row > 2:
|
||||
diag3 = grid[row][col] * grid[row-1][col+1] * grid[row-2][col+2] * grid[row-3][col+3]
|
||||
if col < len(grid[0]) -3 and row < len(grid) - 3:
|
||||
down = grid[row][col] * grid[row+1][col+1] * grid[row+1][col+2] * grid[row+1][col+3]
|
||||
|
||||
l1 = [up, down, left, right, diag1, diag2, diag3, diag4]
|
||||
largest_prod_here = max(l1)
|
||||
if largest_prod_here > larg_prod:
|
||||
larg_prod = largest_prod_here
|
||||
col += 1
|
||||
col = 0
|
||||
row += 1
|
||||
|
||||
return larg_prod
|
||||
|
||||
|
||||
def main():
|
||||
import time
|
||||
start = time.time()
|
||||
|
||||
filename = 'larg_prod_grid.dat'
|
||||
grid = get_grid(filename)
|
||||
assert((grid[6][8], grid[7][9], grid[8][10], grid[9][11]) == (26, 63, 78, 14))
|
||||
print(larg_prod_grid(grid))
|
||||
|
||||
elapsed = (time.time() - start)
|
||||
print('Tests Passed!\n It took %s seconds to run them.' % (elapsed))
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
100
src/further_examples/project_euler/large_sum.dat
Normal file
100
src/further_examples/project_euler/large_sum.dat
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
37107287533902102798797998220837590246510135740250
|
||||
46376937677490009712648124896970078050417018260538
|
||||
74324986199524741059474233309513058123726617309629
|
||||
91942213363574161572522430563301811072406154908250
|
||||
23067588207539346171171980310421047513778063246676
|
||||
89261670696623633820136378418383684178734361726757
|
||||
28112879812849979408065481931592621691275889832738
|
||||
44274228917432520321923589422876796487670272189318
|
||||
47451445736001306439091167216856844588711603153276
|
||||
70386486105843025439939619828917593665686757934951
|
||||
62176457141856560629502157223196586755079324193331
|
||||
64906352462741904929101432445813822663347944758178
|
||||
92575867718337217661963751590579239728245598838407
|
||||
58203565325359399008402633568948830189458628227828
|
||||
80181199384826282014278194139940567587151170094390
|
||||
35398664372827112653829987240784473053190104293586
|
||||
86515506006295864861532075273371959191420517255829
|
||||
71693888707715466499115593487603532921714970056938
|
||||
54370070576826684624621495650076471787294438377604
|
||||
53282654108756828443191190634694037855217779295145
|
||||
36123272525000296071075082563815656710885258350721
|
||||
45876576172410976447339110607218265236877223636045
|
||||
17423706905851860660448207621209813287860733969412
|
||||
81142660418086830619328460811191061556940512689692
|
||||
51934325451728388641918047049293215058642563049483
|
||||
62467221648435076201727918039944693004732956340691
|
||||
15732444386908125794514089057706229429197107928209
|
||||
55037687525678773091862540744969844508330393682126
|
||||
18336384825330154686196124348767681297534375946515
|
||||
80386287592878490201521685554828717201219257766954
|
||||
78182833757993103614740356856449095527097864797581
|
||||
16726320100436897842553539920931837441497806860984
|
||||
48403098129077791799088218795327364475675590848030
|
||||
87086987551392711854517078544161852424320693150332
|
||||
59959406895756536782107074926966537676326235447210
|
||||
69793950679652694742597709739166693763042633987085
|
||||
41052684708299085211399427365734116182760315001271
|
||||
65378607361501080857009149939512557028198746004375
|
||||
35829035317434717326932123578154982629742552737307
|
||||
94953759765105305946966067683156574377167401875275
|
||||
88902802571733229619176668713819931811048770190271
|
||||
25267680276078003013678680992525463401061632866526
|
||||
36270218540497705585629946580636237993140746255962
|
||||
24074486908231174977792365466257246923322810917141
|
||||
91430288197103288597806669760892938638285025333403
|
||||
34413065578016127815921815005561868836468420090470
|
||||
23053081172816430487623791969842487255036638784583
|
||||
11487696932154902810424020138335124462181441773470
|
||||
63783299490636259666498587618221225225512486764533
|
||||
67720186971698544312419572409913959008952310058822
|
||||
95548255300263520781532296796249481641953868218774
|
||||
76085327132285723110424803456124867697064507995236
|
||||
37774242535411291684276865538926205024910326572967
|
||||
23701913275725675285653248258265463092207058596522
|
||||
29798860272258331913126375147341994889534765745501
|
||||
18495701454879288984856827726077713721403798879715
|
||||
38298203783031473527721580348144513491373226651381
|
||||
34829543829199918180278916522431027392251122869539
|
||||
40957953066405232632538044100059654939159879593635
|
||||
29746152185502371307642255121183693803580388584903
|
||||
41698116222072977186158236678424689157993532961922
|
||||
62467957194401269043877107275048102390895523597457
|
||||
23189706772547915061505504953922979530901129967519
|
||||
86188088225875314529584099251203829009407770775672
|
||||
11306739708304724483816533873502340845647058077308
|
||||
82959174767140363198008187129011875491310547126581
|
||||
97623331044818386269515456334926366572897563400500
|
||||
42846280183517070527831839425882145521227251250327
|
||||
55121603546981200581762165212827652751691296897789
|
||||
32238195734329339946437501907836945765883352399886
|
||||
75506164965184775180738168837861091527357929701337
|
||||
62177842752192623401942399639168044983993173312731
|
||||
32924185707147349566916674687634660915035914677504
|
||||
99518671430235219628894890102423325116913619626622
|
||||
73267460800591547471830798392868535206946944540724
|
||||
76841822524674417161514036427982273348055556214818
|
||||
97142617910342598647204516893989422179826088076852
|
||||
87783646182799346313767754307809363333018982642090
|
||||
10848802521674670883215120185883543223812876952786
|
||||
71329612474782464538636993009049310363619763878039
|
||||
62184073572399794223406235393808339651327408011116
|
||||
66627891981488087797941876876144230030984490851411
|
||||
60661826293682836764744779239180335110989069790714
|
||||
85786944089552990653640447425576083659976645795096
|
||||
66024396409905389607120198219976047599490197230297
|
||||
64913982680032973156037120041377903785566085089252
|
||||
16730939319872750275468906903707539413042652315011
|
||||
94809377245048795150954100921645863754710598436791
|
||||
78639167021187492431995700641917969777599028300699
|
||||
15368713711936614952811305876380278410754449733078
|
||||
40789923115535562561142322423255033685442488917353
|
||||
44889911501440648020369068063960672322193204149535
|
||||
41503128880339536053299340368006977710650566631954
|
||||
81234880673210146739058568557934581403627822703280
|
||||
82616570773948327592232845941706525094512325230608
|
||||
22918802058777319719839450180888072429661980811197
|
||||
77158542502016545090413245809786882778948721859617
|
||||
72107838435069186155435662884062257473692284509516
|
||||
20849603980134001723930671666823555245252804609722
|
||||
53503534226472524250874054075591789781264330331690
|
||||
25
src/further_examples/project_euler/large_sum.py
Normal file
25
src/further_examples/project_euler/large_sum.py
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
#!/usr/bin/python3
|
||||
# mari von steinkirch @2013
|
||||
# steinkirch at gmail
|
||||
|
||||
def large_sum(filename):
|
||||
sum_total, lines, numbers = 0, 0, 0
|
||||
with open(filename) as file:
|
||||
for line in file:
|
||||
sum_total += int(line.strip('\n'))
|
||||
return str(sum_total)[0:10]
|
||||
|
||||
|
||||
def main():
|
||||
import time
|
||||
start = time.time()
|
||||
|
||||
filename = 'large_sum.dat'
|
||||
print(large_sum(filename))
|
||||
|
||||
elapsed = (time.time() - start)
|
||||
print('Tests Passed!\n It took %s seconds to run them.' % (elapsed))
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
41
src/further_examples/project_euler/largest_prime_factor.py
Normal file
41
src/further_examples/project_euler/largest_prime_factor.py
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
#!/usr/bin/python3
|
||||
#!/usr/bin/python3
|
||||
|
||||
def is_prime(n):
|
||||
if n < 4 : return True
|
||||
for i in range(2, int(n**0.5 + 1)):
|
||||
if not n%i: return False
|
||||
return True
|
||||
|
||||
|
||||
def largest_prime_factor(n):
|
||||
i = int(n**0.5 +1)
|
||||
while i > 1 :
|
||||
if not n%i and i&1:
|
||||
if is_prime(i): return i
|
||||
i -= 1
|
||||
return None
|
||||
|
||||
|
||||
def largest_prime_factor_optimized(n):
|
||||
factor = 2
|
||||
lastfactor = 1
|
||||
while n > 1:
|
||||
if not n%factor:
|
||||
lastfactor = factor
|
||||
n = n//factor
|
||||
while n%factor == 0:
|
||||
n = n//factor
|
||||
factor += 1
|
||||
return lastfactor
|
||||
|
||||
|
||||
def test_largest_prime_factor():
|
||||
assert(largest_prime_factor(13195)== 29)
|
||||
print(largest_prime_factor(600851475143))
|
||||
assert(largest_prime_factor_optimized(13195) == 29)
|
||||
print(largest_prime_factor_optimized(600851475143))
|
||||
print('Tests Passed!')
|
||||
|
||||
if __name__ == '__main__':
|
||||
test_largest_prime_factor()
|
||||
28
src/further_examples/project_euler/largest_product_seq.py
Normal file
28
src/further_examples/project_euler/largest_product_seq.py
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
#!/usr/bin/python3
|
||||
# mari von steinkirch @2013
|
||||
# steinkirch at gmail
|
||||
|
||||
|
||||
|
||||
def largest_prod_seq(n):
|
||||
result = 0
|
||||
for i in range(0, len(n)-4):
|
||||
first = int(n[i])
|
||||
second = int(n[i+1])
|
||||
third = int(n[i+2])
|
||||
fourth = int(n[i+3])
|
||||
fifth = int(n[i+4])
|
||||
result_here = first*second*third*fourth*fifth
|
||||
if result < result_here:
|
||||
result = result_here
|
||||
return result
|
||||
|
||||
|
||||
def main():
|
||||
n = '7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869478851843858615607891129494954595017379583319528532088055111254069874715852386305071569329096329522744304355766896648950445244523161731856403098711121722383113622298934233803081353362766142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998797908792274921901699720888093776657273330010533678812202354218097512545405947522435258490771167055601360483958644670632441572215539753697817977846174064955149290862569321978468622482839722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758866688116427171479924442928230863465674813919123162824586178664583591245665294765456828489128831426076900422421902267105562632111110937054421750694165896040807198403850962455444362981230987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450'
|
||||
print(largest_prod_seq(n))
|
||||
print('Tests Passed!')
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
42
src/further_examples/project_euler/lattice_paths.py
Normal file
42
src/further_examples/project_euler/lattice_paths.py
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
#!/usr/bin/python3
|
||||
# mari von steinkirch @2013
|
||||
# steinkirch at gmail
|
||||
|
||||
def lattice_paths(squares):
|
||||
gridsize = squares+1
|
||||
grid = [[0 for i in range(gridsize)] for j in range(gridsize)]
|
||||
row, col = 0, 0
|
||||
|
||||
while col < gridsize:
|
||||
while row < gridsize:
|
||||
|
||||
if row == 0 and col == 0:
|
||||
grid[row][col] = 1
|
||||
|
||||
else:
|
||||
if row == 0 and col != 0:
|
||||
grid[row][col] += grid[row][col-1]
|
||||
elif row != 0 and col == 0:
|
||||
grid[row][col] += grid[row-1][col]
|
||||
else:
|
||||
grid[row][col] += grid[row][col-1] + grid[row-1][col]
|
||||
|
||||
row += 1
|
||||
row = 0
|
||||
col += 1
|
||||
return grid[gridsize-1][gridsize-1]
|
||||
|
||||
|
||||
def main():
|
||||
import time
|
||||
start = time.time()
|
||||
|
||||
assert(lattice_paths(2) == 6)
|
||||
print(lattice_paths(20))
|
||||
|
||||
elapsed = (time.time() - start)
|
||||
print('Tests Passed!\n It took %s seconds to run them.' % (elapsed))
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
33
src/further_examples/project_euler/lexico_per.py
Normal file
33
src/further_examples/project_euler/lexico_per.py
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
#!/usr/bin/python3
|
||||
# mari von steinkirch @2013
|
||||
# steinkirch at gmail
|
||||
|
||||
def perm_item(elements):
|
||||
if len(elements) <= 1:
|
||||
yield elements
|
||||
else:
|
||||
for (index, elmt) in enumerate(elements):
|
||||
other_elmts = elements[:index]+elements[index+1:]
|
||||
for permutation in perm_item(other_elmts):
|
||||
yield [elmt] + permutation
|
||||
|
||||
|
||||
def lex_perm(l1, n):
|
||||
perm_list = list(perm_item(l1))
|
||||
return sorted(perm_list)[n-1]
|
||||
|
||||
|
||||
def main():
|
||||
import time
|
||||
start = time.time()
|
||||
|
||||
l1 = [0,1,2,3,4,5,6,7,8,9]
|
||||
n = 10**6
|
||||
print(lex_perm(l1, n))
|
||||
|
||||
elapsed = (time.time() - start)
|
||||
print('Tests Passed!\n It took %s seconds to run them.' % (elapsed))
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
43
src/further_examples/project_euler/long_collatz_seq.py
Normal file
43
src/further_examples/project_euler/long_collatz_seq.py
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
#!/usr/bin/python3
|
||||
# mari von steinkirch @2013
|
||||
# steinkirch at gmail
|
||||
|
||||
def find_coll_seq(n):
|
||||
count = 1
|
||||
while n > 1:
|
||||
if n%2 == 0:
|
||||
n = n//2
|
||||
else:
|
||||
n = 3*n +1
|
||||
count += 1
|
||||
return count
|
||||
|
||||
|
||||
def find_longest_chain(limit):
|
||||
longest, number = 0, 0
|
||||
start = 0
|
||||
while start <= limit:
|
||||
size_chain = find_coll_seq(start)
|
||||
if size_chain > longest:
|
||||
longest = size_chain
|
||||
number = start
|
||||
start += 1
|
||||
|
||||
return (longest, number)
|
||||
|
||||
|
||||
|
||||
|
||||
def main():
|
||||
import time
|
||||
start = time.time()
|
||||
|
||||
#print(find_longest_chain(13))
|
||||
print(find_longest_chain(10**6))
|
||||
|
||||
elapsed = (time.time() - start)
|
||||
print('Tests Passed!\n It took %s seconds to run them.' % (elapsed))
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
15
src/further_examples/project_euler/max_path_sum.dat
Normal file
15
src/further_examples/project_euler/max_path_sum.dat
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
75
|
||||
95 64
|
||||
17 47 82
|
||||
18 35 87 10
|
||||
20 04 82 47 65
|
||||
19 01 23 75 03 34
|
||||
88 02 77 73 07 63 67
|
||||
99 65 04 28 06 16 70 92
|
||||
41 41 26 56 83 40 80 70 33
|
||||
41 48 72 33 47 32 37 16 94 29
|
||||
53 71 44 65 25 43 91 52 97 51 14
|
||||
70 11 33 28 77 73 17 78 39 68 17 57
|
||||
91 71 52 38 17 14 91 43 58 50 27 29 48
|
||||
63 66 04 68 89 53 67 30 73 16 69 87 40 31
|
||||
04 62 98 27 23 09 70 98 73 93 38 53 60 04 23
|
||||
55
src/further_examples/project_euler/max_path_sum.py
Normal file
55
src/further_examples/project_euler/max_path_sum.py
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
#!/usr/bin/python3
|
||||
# mari von steinkirch @2013
|
||||
# steinkirch at gmail
|
||||
|
||||
def max_path_sum(t):
|
||||
root = t[0][0]
|
||||
height, width, index, large_num = 1, 0, 0, 0
|
||||
max_sum = root
|
||||
heights = len(t[:])
|
||||
|
||||
while height < heights:
|
||||
values_here = t[height][index:index+2]
|
||||
if values_here[0] > values_here[1]:
|
||||
large_num = values_here[0]
|
||||
else:
|
||||
large_num = values_here[1]
|
||||
index += 1
|
||||
max_sum += large_num
|
||||
pivot = large_num
|
||||
width, large_num = 0, 0
|
||||
height += 1
|
||||
|
||||
return max_sum
|
||||
|
||||
def edit_input(filename):
|
||||
output = []
|
||||
with open(filename) as file:
|
||||
for line in file:
|
||||
line = line.rstrip('\n')
|
||||
output.append(line.split(' '))
|
||||
for i, l1 in enumerate(output):
|
||||
for j, c in enumerate(output[i]):
|
||||
output[i][j] = int(c)
|
||||
return(output)
|
||||
|
||||
|
||||
|
||||
def main():
|
||||
import time
|
||||
start = time.time()
|
||||
|
||||
filename = 'max_path_sum0.dat'
|
||||
t1 = edit_input(filename)
|
||||
print('Little pir: ',max_path_sum(t1))
|
||||
|
||||
filename = 'max_path_sum.dat'
|
||||
t2 = edit_input(filename)
|
||||
print('Big pir: ', max_path_sum(t2))
|
||||
|
||||
elapsed = (time.time() - start)
|
||||
print('Tests Passed!\n It took %s seconds to run them.' % (elapsed))
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
4
src/further_examples/project_euler/max_path_sum0.dat
Normal file
4
src/further_examples/project_euler/max_path_sum0.dat
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
3
|
||||
7 4
|
||||
2 4 6
|
||||
8 5 9 3
|
||||
22
src/further_examples/project_euler/multiples_of_3_and_5.py
Normal file
22
src/further_examples/project_euler/multiples_of_3_and_5.py
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
#!/usr/bin/python3
|
||||
# mari von steinkirch @2013
|
||||
# steinkirch at gmail
|
||||
|
||||
|
||||
def mul3and5(n):
|
||||
result = 0
|
||||
for num in range(1, n):
|
||||
if num%3 == 0 or num%5 == 0:
|
||||
result += num
|
||||
return result
|
||||
|
||||
|
||||
|
||||
def test_():
|
||||
assert(mul3and5(10) == 23)
|
||||
print(mul3and5(1000))
|
||||
print('Tests Passed!')
|
||||
|
||||
if __name__ == '__main__':
|
||||
test_()
|
||||
|
||||
1
src/further_examples/project_euler/names.txt
Normal file
1
src/further_examples/project_euler/names.txt
Normal file
File diff suppressed because one or more lines are too long
33
src/further_examples/project_euler/names_score.py
Normal file
33
src/further_examples/project_euler/names_score.py
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
#!/usr/bin/python3
|
||||
# mari von steinkirch @2013
|
||||
# steinkirch at gmail
|
||||
|
||||
|
||||
def calculate_score(name, dict_letters):
|
||||
sum_letters = 0
|
||||
for letter in name:
|
||||
sum_letters += dict_letters[letter]
|
||||
return sum_letters
|
||||
|
||||
def names_score(filename):
|
||||
dict_letters ={'A':1,'B':2,'C':3,'D':4,'E':5,'F':6,'G':7,'H':8,'I':9,'J':10,'K':11,'L':12,'M':13,'N':14,'O':15,'P':16,'Q':17,'R':18,'S':19, 'T':20,'U':21,'V':22,'W':23,'X':24,'Y':25,'Z':26}
|
||||
total_score = 0
|
||||
with open(filename) as file:
|
||||
for line in file:
|
||||
names = [name.strip('"') for name in line.split(',')]
|
||||
names.sort()
|
||||
for i, name in enumerate(names):
|
||||
total_score += (i+1)* calculate_score(name, dict_letters)
|
||||
|
||||
return total_score
|
||||
|
||||
|
||||
|
||||
def main():
|
||||
filename = 'names.txt'
|
||||
print(names_score(filename))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
44
src/further_examples/project_euler/non_abund_sums.py
Normal file
44
src/further_examples/project_euler/non_abund_sums.py
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
#!/usr/bin/python3
|
||||
# mari von steinkirch @2013
|
||||
# steinkirch at gmail
|
||||
|
||||
def find_sum_proper_div(n):
|
||||
sum_proper_div = 0
|
||||
for i in range(1, n):
|
||||
if n%i == 0:
|
||||
sum_proper_div += i
|
||||
return sum_proper_div
|
||||
|
||||
|
||||
def find_all_abund(n):
|
||||
sum_div_list = [find_sum_proper_div(i) for i in range(n)]
|
||||
abu = set()
|
||||
for i in range(n):
|
||||
if i < sum_div_list[i]:
|
||||
abu.add(i)
|
||||
return abu
|
||||
|
||||
|
||||
def non_abund_sums(n):
|
||||
abu = find_all_abund(n)
|
||||
sum_nom_abu = 0
|
||||
|
||||
for i in range(n):
|
||||
if not any( (i-a in abu) for a in abu):
|
||||
sum_nom_abu += i
|
||||
|
||||
return sum_nom_abu
|
||||
|
||||
|
||||
def test_():
|
||||
r = set([i for i in range(25)])
|
||||
r_abu = {24}
|
||||
r = r - r_abu
|
||||
assert(non_abund_sums(25) == sum(r))
|
||||
print(non_abund_sums(28123))
|
||||
print('Tests Passed!')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
test_()
|
||||
|
||||
63
src/further_examples/project_euler/number_letter_counts.py
Normal file
63
src/further_examples/project_euler/number_letter_counts.py
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
#!/usr/bin/python3
|
||||
# mari von steinkirch @2013
|
||||
# steinkirch at gmail
|
||||
|
||||
|
||||
|
||||
def number_letter_counts(n):
|
||||
dict_lett = build_dict(n)
|
||||
sum_letter = 0
|
||||
for item in dict_lett:
|
||||
sum_letter += dict_lett[item]
|
||||
return sum_letter
|
||||
|
||||
|
||||
def build_dict(n):
|
||||
lett_dict = {}
|
||||
numbers = (x for x in range(1, n+1))
|
||||
dec = ['one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten', 'eleven', 'twelve', 'thirteen', 'fourteen', 'fifteen', 'sixteen', 'seventeen', 'eighteen', 'nineteen']
|
||||
ties = ['twenty', 'thirty', 'forty', 'fifty', 'sixty', 'seventy', 'eighty', 'ninety']
|
||||
|
||||
for number in numbers:
|
||||
if 1 <= number < 20:
|
||||
lett_dict[number] = len(dec[number-1])
|
||||
elif 20 <= number < 100:
|
||||
index_dec = number//10
|
||||
index_num = number%10
|
||||
if index_num == 0:
|
||||
lett_dict[number] = len(ties[index_dec-2])
|
||||
else:
|
||||
lett_dict[number] = len(ties[index_dec-2]) + len(dec[index_num-1])
|
||||
elif 100 <= number < 1000:
|
||||
index_hun = number//100
|
||||
index_dec = number%100
|
||||
if index_dec == 0:
|
||||
lett_dict[number] = len(dec[index_hun-1]) + len('hundred')
|
||||
else:
|
||||
if 1 <= index_dec < 20:
|
||||
lett_dict[number] = len(dec[index_hun-1]) + len('hundred') + len('and') + len(dec[index_dec-1])
|
||||
elif 20 <= index_dec < 100:
|
||||
index_dec2 = index_dec//10
|
||||
index_num = index_dec%10
|
||||
if index_num == 0:
|
||||
lett_dict[number] = len(dec[index_hun-1]) + len('hundred') + len('and') + len(ties[index_dec2-2])
|
||||
else:
|
||||
lett_dict[number] = len(dec[index_hun-1]) + len('hundred') + len('and') + len(ties[index_dec2-2]) + len(dec[index_num-1])
|
||||
elif number == 1000:
|
||||
lett_dict[number] = len('onethousand')
|
||||
|
||||
return lett_dict
|
||||
|
||||
|
||||
def main():
|
||||
import time
|
||||
start = time.time()
|
||||
|
||||
assert(number_letter_counts(5) == 19)
|
||||
print(number_letter_counts(1000))
|
||||
elapsed = (time.time() - start)
|
||||
print('Tests Passed!\n It took %s seconds to run them.' % (elapsed))
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
39
src/further_examples/project_euler/number_spiral.py
Normal file
39
src/further_examples/project_euler/number_spiral.py
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
#!/usr/bin/python3
|
||||
# mari von steinkirch @2013
|
||||
# steinkirch at gmail
|
||||
|
||||
def number_spiral(spiral):
|
||||
|
||||
|
||||
return rows, mid
|
||||
|
||||
def make_spiral(n):
|
||||
spiral = []
|
||||
row = rows//2
|
||||
col = col//2
|
||||
count = 1
|
||||
while row < n:
|
||||
while col < n:
|
||||
spiral[col][row] = count
|
||||
count += 1
|
||||
if count%2 == 0:
|
||||
col += 1
|
||||
else:
|
||||
row += 1
|
||||
|
||||
return spiral
|
||||
|
||||
def main():
|
||||
import time
|
||||
start = time.time()
|
||||
|
||||
n = 5
|
||||
spiral = make_spiral(n)
|
||||
print(number_spiral(spiral))# 101
|
||||
|
||||
elapsed = (time.time() - start)
|
||||
print('Tests Passed!\n It took %s seconds to run them.' % (elapsed))
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
28
src/further_examples/project_euler/path_sum_two_ways.py~
Normal file
28
src/further_examples/project_euler/path_sum_two_ways.py~
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
#!/usr/bin/python3
|
||||
# mari von steinkirch @2013
|
||||
# steinkirch at gmail
|
||||
|
||||
def path_sum_two_ways(m1):
|
||||
paths = []
|
||||
|
||||
row, col = 0, 0
|
||||
p = len(m1)
|
||||
|
||||
while row < len(m1):
|
||||
print(m1[0:p])
|
||||
while p:
|
||||
aux = sum([x for x in m1[0:p]])
|
||||
paths.append(aux)
|
||||
p -= 1
|
||||
row += 1
|
||||
|
||||
return max(paths)
|
||||
|
||||
|
||||
def main():
|
||||
m1 = [[131, 673, 234, 103, 18], [201, 96, 342, 965, 150], [630, 803, 746, 422, 111], [537, 699, 497, 121, 956], [805, 732, 524, 37, 331]]
|
||||
print(path_sum_two_ways(m1))
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
22
src/further_examples/project_euler/power_digit_sum.py
Normal file
22
src/further_examples/project_euler/power_digit_sum.py
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
#!/usr/bin/python3
|
||||
# mari von steinkirch @2013
|
||||
# steinkirch at gmail
|
||||
|
||||
|
||||
def power_digit_sum(n):
|
||||
number = str(2**n)
|
||||
sum_res = 0
|
||||
for i in number:
|
||||
sum_res += int(i)
|
||||
return sum_res
|
||||
|
||||
|
||||
|
||||
def test_():
|
||||
assert(power_digit_sum(15) == 26)
|
||||
print(power_digit_sum(1000))
|
||||
print('Tests Passed!')
|
||||
|
||||
if __name__ == '__main__':
|
||||
test_()
|
||||
|
||||
50
src/further_examples/project_euler/quad_primes.py
Normal file
50
src/further_examples/project_euler/quad_primes.py
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
#!/usr/bin/python3
|
||||
# mari von steinkirch @2013
|
||||
# steinkirch at gmail
|
||||
|
||||
def quad_form(n, a, b):
|
||||
return n**2 + a*n + b
|
||||
|
||||
def isPrime(n):
|
||||
n = abs(int(n))
|
||||
if n < 2:
|
||||
return False
|
||||
if n == 2:
|
||||
return True
|
||||
if not n & 1:
|
||||
return False
|
||||
for x in range(3, int(n**0.5)+1, 2):
|
||||
if n % x == 0:
|
||||
return False
|
||||
return True
|
||||
|
||||
def quad_primes(a, b):
|
||||
count_max = 0
|
||||
coef = ()
|
||||
for aa in range(-a, a):
|
||||
for bb in range(-b, b):
|
||||
n = 0
|
||||
while True:
|
||||
number = quad_form(n, aa, bb)
|
||||
if isPrime(number):
|
||||
n += 1
|
||||
else:
|
||||
if n > count_max:
|
||||
count_max = n
|
||||
coef = (aa, bb)
|
||||
break
|
||||
return coef(0)*coef(1), coef
|
||||
|
||||
|
||||
def main():
|
||||
import time
|
||||
start = time.time()
|
||||
|
||||
print(quad_primes(1000, 1000))
|
||||
|
||||
elapsed = (time.time() - start)
|
||||
print('Tests Passed!\n It took %s seconds to run them.' % (elapsed))
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
29
src/further_examples/project_euler/self_powers.py
Normal file
29
src/further_examples/project_euler/self_powers.py
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
#!/usr/bin/python3
|
||||
# mari von steinkirch @2013
|
||||
# steinkirch at gmail
|
||||
|
||||
def self_powers(power, digits):
|
||||
sum_total = 0
|
||||
for pow in range(1, power+1):
|
||||
sum_total += pow**pow
|
||||
sum_total_str = str(sum_total)
|
||||
last_digits = ''
|
||||
for i, c in enumerate(sum_total_str[-digits:]):
|
||||
last_digits += c
|
||||
return int(last_digits)
|
||||
|
||||
|
||||
def main():
|
||||
import time
|
||||
start = time.time()
|
||||
|
||||
|
||||
assert(self_powers(10, len('10405071317')) == 10405071317)
|
||||
print(self_powers(1000, 10))
|
||||
|
||||
elapsed = (time.time() - start)
|
||||
print('Tests Passed!\n It took %s seconds to run them.' % (elapsed))
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
32
src/further_examples/project_euler/smallest_multiple.py
Normal file
32
src/further_examples/project_euler/smallest_multiple.py
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
#!/usr/bin/python3
|
||||
|
||||
def smallest_multiple(n):
|
||||
set1 = set([x for x in range(1, n+1)])
|
||||
set2 = set()
|
||||
for i in range(len(set1), 0, -1):
|
||||
for j in range(1, i):
|
||||
if i%j == 0:
|
||||
set2.add(j)
|
||||
set1 = set1 - set2
|
||||
res_num = n*n
|
||||
while True:
|
||||
for i in set1:
|
||||
missing_div = False
|
||||
if res_num%i:
|
||||
missing_div = True
|
||||
shift = res_num%i
|
||||
break
|
||||
if not missing_div: return res_num
|
||||
res_num += 1 or shift
|
||||
shift = 0
|
||||
|
||||
|
||||
|
||||
|
||||
def test_():
|
||||
assert(smallest_multiple(10) == 2520)
|
||||
print(smallest_multiple(20))
|
||||
print('Tests Passed!')
|
||||
|
||||
if __name__ == '__main__':
|
||||
test_()
|
||||
26
src/further_examples/project_euler/special_pyt.py
Normal file
26
src/further_examples/project_euler/special_pyt.py
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
#!/usr/bin/python3
|
||||
# mari von steinkirch @2013
|
||||
# steinkirch at gmail
|
||||
|
||||
|
||||
|
||||
def special_pyt(n):
|
||||
for i in range(3, n):
|
||||
for j in range(i+1, n):
|
||||
c = calc_c(i,j)
|
||||
if i + j + c == n:
|
||||
return i*j*c
|
||||
|
||||
def calc_c(a, b):
|
||||
return (a**2 + b**2)**0.5
|
||||
|
||||
|
||||
|
||||
def main():
|
||||
assert(special_pyt(3+4+5) == (3*4*5))
|
||||
print(special_pyt(1000))
|
||||
print('Tests Passed!')
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
38
src/further_examples/project_euler/square_dig_chains.py
Normal file
38
src/further_examples/project_euler/square_dig_chains.py
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
#!/usr/bin/python3
|
||||
# mari von steinkirch @2013
|
||||
# steinkirch at gmail
|
||||
|
||||
def calculate_chain(n):
|
||||
n_str = str(n)
|
||||
while n_str != 1 or n_str != 89:
|
||||
n_str = str(n_str)
|
||||
sum_here = 0
|
||||
for d in n_str:
|
||||
sum_here += int(d)**2
|
||||
n_str = sum_here
|
||||
if n_str == 89:
|
||||
return 1
|
||||
if n_str == 1:
|
||||
return 0
|
||||
|
||||
|
||||
def square_dig_chains(n):
|
||||
count = 0
|
||||
for i in range(1, n+1):
|
||||
count += calculate_chain(i)
|
||||
return count
|
||||
|
||||
|
||||
|
||||
def main():
|
||||
import time
|
||||
start = time.time()
|
||||
|
||||
print(square_dig_chains(10**7))
|
||||
|
||||
elapsed = (time.time() - start)
|
||||
print('Tests Passed!\n It took %s seconds to run them.' % (elapsed))
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
21
src/further_examples/project_euler/sum_square_diff.py
Normal file
21
src/further_examples/project_euler/sum_square_diff.py
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
#!/usr/bin/python3
|
||||
# mari von steinkirch @2013
|
||||
# steinkirch at gmail
|
||||
|
||||
|
||||
def sum_square_diff(n):
|
||||
sq_sum, sum_sq = 0, 0
|
||||
for i in range(1, n+1):
|
||||
sum_sq += i**2
|
||||
sq_sum += i
|
||||
sq_sum = sq_sum **2
|
||||
return sq_sum - sum_sq
|
||||
|
||||
def main():
|
||||
assert(sum_square_diff(10) == 2640)
|
||||
print(sum_square_diff(100))
|
||||
print('Tests Passed!')
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
24
src/further_examples/project_euler/summation_primes.py
Normal file
24
src/further_examples/project_euler/summation_primes.py
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
#!/usr/bin/python3
|
||||
# mari von steinkirch @2013
|
||||
# steinkirch at gmail
|
||||
|
||||
from findstprime import is_prime
|
||||
|
||||
def summation_primes(n):
|
||||
candidate = 2
|
||||
prime_set = set()
|
||||
while candidate < n:
|
||||
if is_prime(candidate, prime_set):
|
||||
prime_set.add(candidate)
|
||||
candidate +=1
|
||||
return sum(prime_set)
|
||||
|
||||
|
||||
def main():
|
||||
assert(summation_primes(10) == 17)
|
||||
print(summation_primes(2000000))
|
||||
print('Tests Passed!')
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
70
src/further_examples/top_coder/tco2013_round3_3b_div1.py
Normal file
70
src/further_examples/top_coder/tco2013_round3_3b_div1.py
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
#!/usr/bin/python3
|
||||
# mari von steinkirch @2013
|
||||
# steinkirch at gmail
|
||||
|
||||
|
||||
|
||||
def findToneDiff(tones):
|
||||
tonesDiff = []
|
||||
n = len(tones)
|
||||
for i, tone in enumerate(tones):
|
||||
for j in range(i+1, len(tones)):
|
||||
sum_here = abs(tone - tones[j])
|
||||
tonesDiff.append([sum_here, i, j])
|
||||
return sorted(tonesDiff)
|
||||
|
||||
def findAllPossible(duration, tones, T):
|
||||
tonesDiff = findToneDiff(tones)
|
||||
sumsTone1 = [(song, i) for i, song in enumerate(duration) if song <= T]
|
||||
sumsTone2 = []
|
||||
for song in tonesDiff:
|
||||
sum_here = song[0] + duration[song[1]] + duration[song[2]]
|
||||
if sum_here <= T:
|
||||
sumsTone2.append((sum_here, song[1], song[2], 2))
|
||||
return sumsTone1, sumsTone2
|
||||
|
||||
|
||||
def findAllPossibleNext(sumsTone, T, n_music):
|
||||
sumsTone2 = []
|
||||
for i, song1 in enumerate(sumsTone):
|
||||
index1 = song1[1]
|
||||
for j in range(i+1, len(sumsTone)):
|
||||
song2 = sumsTone[j]
|
||||
index2 = song2[1]
|
||||
if index1 == index2:
|
||||
sum_here = song1[0] + song2[0]
|
||||
if sum_here < T:
|
||||
sumsTone2.append((sum_here, song2[1], song2[2], n_music))
|
||||
|
||||
|
||||
return sumsTone2
|
||||
|
||||
|
||||
def maxSongs(duration, tones, T):
|
||||
|
||||
if min(duration) >= T:
|
||||
return 0
|
||||
|
||||
sumsTone1, sumsTone = findAllPossible(duration, tones, T)
|
||||
if not sumsTone:
|
||||
return 1
|
||||
|
||||
while sumsTone:
|
||||
n_music = sumsTone[0][3]+1
|
||||
sumsTone = findAllPossibleNext(sumsTone, T, n_music)
|
||||
if not sumsTone:
|
||||
return n_music
|
||||
|
||||
|
||||
|
||||
def tests_250():
|
||||
print(maxSongs([3, 5, 4, 11], [2, 1, 3, 1], 17)) #3
|
||||
print(maxSongs([9, 11, 13, 17], [2, 1, 3, 4], 20)) #1
|
||||
print(maxSongs([100, 200, 300], [1,2,3], 99)) #0
|
||||
print(maxSongs([87,21,20,73,97,57,12,80,86,97,98,85,41,12,89,15,41,17,68,37,21,1,9,65,4,67,38,91,46,82,7,98,21,70,99,41,21,65,11,1,8,12,77,62,52,69,56,33,98,97], [88,27,89,2,96,32,4,93,89,50,58,70,15,48,31,2,27,20,31,3,23,86,69,12,59,61,85,67,77,34,29,3,75,42,50,37,56,45,51,68,89,17,4,47,9,14,29,59,43,3], 212))
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
tests_250()
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue