├── 1.0_string_permutations.py ├── 1.1_string_unique.py ├── 1.2_reverse_string.py ├── 1.3_remove_duplicate_chars.py ├── 1.4_string_anagram.py ├── 1.5_replace_spaces.py ├── 1.6_rotate_matrix.py ├── 1.7_zeros_in_matrix.py ├── 1.8_is_rotation.py ├── 2.0_linked_list_basics.py ├── 2.1_remove_duplicates.py ├── 2.2_find_n_before_last.py ├── 2.3_delete_node_only.py ├── 2.4_add_lists.py ├── 2.5_find_loop.py ├── 3.0_stacks_queues.py ├── 3.5_hanoi_towers.py ├── 4.1_is_tree_balanced.py ├── 4.2_find_route.py ├── 4.2_x_dijkstra.py ├── 4.3_build_minimal_tree.py ├── README.md ├── binary_tree.py ├── binary_tree.pyc ├── binary_tree_add_delete.py ├── binary_tree_deserialize.py ├── binary_tree_traverse.py ├── birthday_paradox.py ├── fibonacci.py ├── graph.py ├── graph.pyc ├── heap.py ├── heap.pyc ├── knapsack.py ├── linked_list.py ├── linked_list.pyc ├── regex.py ├── sorting_tests.py ├── stack_queue.py └── stack_queue.pyc /1.0_string_permutations.py: -------------------------------------------------------------------------------- 1 | def permute(word, d): 2 | if len(word) > 0: 3 | print word 4 | if d < len(word): 5 | word = list(word) 6 | for i in range (d, len(word)): 7 | word[d], word[i] = word[i], word[d] 8 | permute(''.join(word), d + 1) 9 | 10 | permute('abc', 0) -------------------------------------------------------------------------------- /1.1_string_unique.py: -------------------------------------------------------------------------------- 1 | 2 | def is_unique_chars(s): 3 | chars = {} 4 | for i in range(len(s)): 5 | if (s[i] in chars): 6 | return False 7 | else: 8 | chars[s[i]] = 1 9 | return True 10 | 11 | def is_unique_chars_optimized(s): 12 | counter = 0 13 | 14 | for i in range(len(s)): 15 | char_ix = ord(s[i]) - ord('a') 16 | if (counter & (1 << char_ix) > 0): 17 | return False 18 | else: 19 | counter |= (1 << char_ix) 20 | return True 21 | 22 | strings = ['amiunique', 'abcd', ''] 23 | 24 | for s in strings: 25 | print "Unique: '" + s + "': " + str(is_unique_chars(s)) + ", " + str(is_unique_chars_optimized(s)) -------------------------------------------------------------------------------- /1.2_reverse_string.py: -------------------------------------------------------------------------------- 1 | s = 'Reverse me' 2 | ls = list(s) 3 | 4 | l = len(ls) 5 | print "Len: {0}".format(l) 6 | for i in range (0, l / 2): 7 | e = l - i - 1 8 | ls[i], ls[e] = ls[e], ls[i] 9 | 10 | for i in range (0, l): 11 | print "Letter {0}: {1}".format(i, ls[i]) -------------------------------------------------------------------------------- /1.3_remove_duplicate_chars.py: -------------------------------------------------------------------------------- 1 | 2 | def remove_duplicates(s): 3 | l = len(s) 4 | 5 | if (l < 2): 6 | return s 7 | 8 | s = list(s) 9 | i_dest = 0 10 | i_check = 1 11 | 12 | while ((i_dest < l) and (i_check < l)): 13 | if (s[i_dest] == s[i_check]): 14 | i_check += 1 15 | else: 16 | i_dest += 1 17 | s[i_dest] = s[i_check] 18 | i_check += 1 19 | 20 | s = s[:i_dest+1] 21 | s = "".join(s) 22 | return s 23 | 24 | print remove_duplicates('aaaa') 25 | print remove_duplicates('abcd') 26 | print remove_duplicates('aabccc') 27 | print remove_duplicates('aaabbbccc') -------------------------------------------------------------------------------- /1.4_string_anagram.py: -------------------------------------------------------------------------------- 1 | 2 | def is_anagram(s1, s2): 3 | 4 | if (len(s1) != len(s2)): 5 | return False 6 | 7 | h1 = {} 8 | h2 = {} 9 | 10 | for i in range(len(s1)): 11 | if s1[i] in h1: 12 | h1[s1[i]] += 1 13 | else: 14 | h1[s1[i]] = 0 15 | 16 | for i in range(len(s2)): 17 | if s2[i] in h2: 18 | h2[s2[i]] += 1 19 | else: 20 | h2[s2[i]] = 0 21 | 22 | for c in h1.keys(): 23 | if (c in h2) and (h2[c] == h1[c]): 24 | h2.pop(c) 25 | else: 26 | return False 27 | 28 | for c in h2.keys(): 29 | if (c not in h1) or (h1[c] != h2[c]): 30 | return False 31 | 32 | return True 33 | 34 | print is_anagram('xamarin', 'marinax') 35 | print is_anagram('aaa', 'aab') 36 | print is_anagram('aaa', '') 37 | print is_anagram('aabb', 'abab') 38 | 39 | -------------------------------------------------------------------------------- /1.5_replace_spaces.py: -------------------------------------------------------------------------------- 1 | 2 | def replace_spaces(s): 3 | cnt = 0 4 | 5 | for c in s: 6 | if c == ' ': 7 | cnt += 1 8 | 9 | if cnt == 0: 10 | return s 11 | 12 | r = list(s) 13 | r.extend(' ' * cnt * 2) 14 | 15 | l = len(s) 16 | new_len = l + cnt * 2 17 | 18 | for i in range(l - 1, 0, -1): 19 | if r[i] == ' ': 20 | r[new_len - 1] = '0' 21 | r[new_len - 2] = '2' 22 | r[new_len - 3] = '%' 23 | new_len -= 3 24 | else: 25 | r[new_len - 1] = r[i] 26 | new_len -= 1 27 | 28 | return "".join(r) 29 | 30 | tests = ['test #1', 'this is even more spaces', 'what?'] 31 | 32 | for t in tests: 33 | print t + ' -> ' + replace_spaces(t) -------------------------------------------------------------------------------- /1.6_rotate_matrix.py: -------------------------------------------------------------------------------- 1 | m = [] 2 | l = 4 3 | start = 0 4 | 5 | for row in range(l): 6 | m.append(range(start, start + l, 1)) 7 | start += l 8 | 9 | print "Original:" 10 | for row in m: 11 | print row 12 | 13 | def rotate_matrix(m): 14 | n = [] 15 | 16 | for r in range(len(m)): 17 | n.append([0] * len(m)) 18 | 19 | for r in range(len(m)): 20 | for c in range(len(m)): 21 | n[c][(len(m)-r-1)] = m[r][c] 22 | 23 | return n 24 | 25 | def rotate_matrix_inplace(m): 26 | side_len = len(m) 27 | shift = 0 28 | 29 | while (side_len > 1): 30 | block_len = len(m[shift])-2*shift 31 | 32 | # save top row 33 | top = m[shift][shift:shift+block_len] 34 | 35 | # move left to top 36 | for r in range(shift, shift + block_len): 37 | m[shift][len(m)-r-1] = m[r][shift] 38 | 39 | # move bottom to left 40 | for c in range(shift, shift + block_len): 41 | m[c][shift] = m[len(m)-shift-1][c] 42 | 43 | # move right to bottom 44 | for c in range(shift, shift + block_len): 45 | m[len(m)-shift-1][c] = m[len(m)-c-1][len(m)-shift-1] 46 | 47 | # move top to right 48 | i = 0 49 | for r in range(shift, shift + block_len): 50 | m[r][len(m)-shift-1] = top[i] 51 | i += 1 52 | 53 | side_len /= 2 54 | shift += 1 55 | 56 | return m 57 | 58 | n = rotate_matrix(m) 59 | 60 | print "Rotated:" 61 | for row in n: 62 | print row 63 | 64 | n = rotate_matrix_inplace(m) 65 | 66 | print "Rotated in place:" 67 | for row in n: 68 | print row 69 | -------------------------------------------------------------------------------- /1.7_zeros_in_matrix.py: -------------------------------------------------------------------------------- 1 | 2 | def set_zero_intersection(m): 3 | if (len(m) == 0) or (len(m[0]) == 0): 4 | return m 5 | 6 | rc = len(m) 7 | cc = len(m[0]) 8 | 9 | rows = [0] * rc 10 | 11 | columns = [0] * cc 12 | 13 | for r in range(rc): 14 | for c in range (cc): 15 | if m[r][c] == 0: 16 | rows[r] = 1 17 | columns[c] = 1 18 | 19 | for r in range(rc): 20 | for c in range (cc): 21 | if (rows[r] == 1) or (columns[c] == 1): 22 | m[r][c] = 0 23 | return m 24 | 25 | def print_matrix(m): 26 | for row in m: 27 | print row 28 | 29 | m = [[1, 1, 1, 0, 1], 30 | [1, 1, 1, 1, 1], 31 | [1, 0, 1, 1, 1], 32 | [1, 1, 1, 1, 1], 33 | [1, 1, 1, 1, 1], 34 | [1, 1, 1, 1, 1], 35 | [1, 1, 0, 1, 1]] 36 | 37 | print 'Original:' 38 | print_matrix(m) 39 | print 'Zeroed:' 40 | print_matrix(set_zero_intersection(m)) 41 | -------------------------------------------------------------------------------- /1.8_is_rotation.py: -------------------------------------------------------------------------------- 1 | 2 | def is_substring(string, substring): 3 | 4 | result = string.find(substring) 5 | 6 | if result == -1: 7 | return False 8 | 9 | return True 10 | 11 | tests = [ 12 | ['word', 'rdwo'], 13 | ['abcdef', 'cdefab'], 14 | ['abcdef', 'bcdef'], 15 | ] 16 | 17 | for t in tests: 18 | print t[0] + ', ' + t[1] + ' : ' + str(is_substring(t[1] + t[1], t[0])) 19 | 20 | -------------------------------------------------------------------------------- /2.0_linked_list_basics.py: -------------------------------------------------------------------------------- 1 | from linked_list import Node, LinkedList 2 | 3 | ll = LinkedList(range(1, 11)) 4 | 5 | to_remove = [2, 1, 8] 6 | 7 | print 'Original:' 8 | ll.output() 9 | 10 | 11 | for i in to_remove: 12 | print 'Removed ' + str(i) + ':' 13 | ll.remove(i) 14 | ll.output() 15 | -------------------------------------------------------------------------------- /2.1_remove_duplicates.py: -------------------------------------------------------------------------------- 1 | from linked_list import Node, LinkedList 2 | 3 | def remove_duplicates(ll): 4 | if (ll.head is None) or (ll.head.next is None): 5 | return ll 6 | 7 | h = {} 8 | 9 | n = ll.head 10 | while n is not None: 11 | if n.data in h: 12 | h[n.data] += 1 13 | else: 14 | h[n.data] = 1 15 | n = n.next 16 | 17 | p = ll.head 18 | n = ll.head.next 19 | 20 | while n is not None: 21 | if h[n.data] > 1: 22 | h[n.data] -= 1 23 | tmp = n.next 24 | p.next = tmp 25 | n = tmp 26 | else: 27 | p = n 28 | n = n.next 29 | 30 | return ll 31 | 32 | def remove_duplicates_no_buffer(ll): 33 | 34 | if (ll.head is None) or (ll.head.next is None): 35 | return ll 36 | 37 | p = ll.head 38 | n = ll.head.next 39 | 40 | while n is not None: 41 | # check from head to current 42 | checker = ll.head 43 | while checker != n: 44 | if checker.data == n.data: 45 | tmp = n.next 46 | p.next = tmp 47 | n = tmp 48 | break 49 | checker = checker.next 50 | if checker == n: 51 | p = n 52 | n = n.next 53 | 54 | return ll 55 | 56 | def test_remove_duplicates(ll, no_buffer): 57 | if no_buffer: 58 | print 'No buffer: ' + str(no_buffer) + ', ' + ll.to_string() + ' -> ' + remove_duplicates_no_buffer(ll).to_string() 59 | else: 60 | print 'No buffer: ' + str(no_buffer) + ', ' + ll.to_string() + ' -> ' + remove_duplicates(ll).to_string() 61 | 62 | test_remove_duplicates(LinkedList([1, 1, 1, 2, 3, 4, 1, 1, 1]), False) 63 | test_remove_duplicates(LinkedList([1]), False) 64 | test_remove_duplicates(LinkedList([]), False) 65 | test_remove_duplicates(LinkedList([1, 2, 3, 4]), False) 66 | test_remove_duplicates(LinkedList([1, 1, 1]), False) 67 | 68 | test_remove_duplicates(LinkedList([1, 1, 1, 2, 3, 4, 1, 1, 1]), True) 69 | test_remove_duplicates(LinkedList([1]), True) 70 | test_remove_duplicates(LinkedList([]), True) 71 | test_remove_duplicates(LinkedList([1, 2, 3, 4]), True) 72 | test_remove_duplicates(LinkedList([1, 1, 1]), True) 73 | -------------------------------------------------------------------------------- /2.2_find_n_before_last.py: -------------------------------------------------------------------------------- 1 | from linked_list import Node, LinkedList 2 | 3 | def find_before_last(ll, steps): 4 | if (ll is None) or (ll.head is None) or (steps < 0): 5 | return None 6 | 7 | i = 0 8 | fast = ll.head 9 | found = None 10 | while (i <= steps) and (fast is not None): 11 | if i == steps: 12 | found = fast 13 | break 14 | fast = fast.next 15 | i += 1 16 | 17 | if found is None: 18 | return None # list too short 19 | 20 | slow = ll.head 21 | 22 | while (fast != None) and (fast.next != None): 23 | slow = slow.next 24 | fast = fast.next 25 | 26 | return slow.data 27 | 28 | def test_find_before_last(ll, n): 29 | found = find_before_last(ll, n) 30 | print ll.to_string() + ', ' + str(n) + ' -> ' + str(found) 31 | 32 | for i in range(-1, 11, 1): 33 | test_find_before_last(LinkedList([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]), i) 34 | -------------------------------------------------------------------------------- /2.3_delete_node_only.py: -------------------------------------------------------------------------------- 1 | from linked_list import Node, LinkedList 2 | 3 | def delete_node(n): 4 | if (n is None) or (n.next is None): 5 | return # can't do this 6 | 7 | n.data = n.next.data 8 | n.next = n.next.next 9 | 10 | def find_node(from_node, data): 11 | if (data is None) or (from_node is None): 12 | return None 13 | 14 | n = from_node 15 | 16 | while n != None: 17 | if n.data == data: 18 | return n 19 | else: 20 | n = n.next 21 | 22 | return None 23 | 24 | def test_delete_node(ll, data): 25 | out = ll.to_string() 26 | node = find_node(ll.head, data) 27 | out += ', delete ' + str(node.data) 28 | delete_node(node) 29 | out += ' -> ' + ll.to_string() 30 | print out 31 | 32 | for i in range(1, 6): 33 | test_delete_node(LinkedList([1, 2, 3, 4, 5]), i) 34 | -------------------------------------------------------------------------------- /2.4_add_lists.py: -------------------------------------------------------------------------------- 1 | from linked_list import Node, LinkedList 2 | 3 | def add_lists(l1, l2): 4 | 5 | if (l1 is None) or (l2 is None) or ((l1.head is None) and (l2.head is None)): 6 | return None 7 | 8 | ll = LinkedList([]) 9 | 10 | h = 0 11 | n1 = l1.head 12 | n2 = l2.head 13 | 14 | if n1 is not None: h += n1.data 15 | if n2 is not None: h += n2.data 16 | 17 | digit = h % 10 18 | remember = (h - (h % 10)) / 10 19 | ll.append(digit) 20 | 21 | while (n1 is not None) or (n2 is not None): 22 | h = 0 23 | if n1 is not None: n1 = n1.next 24 | if n2 is not None: n2 = n2.next 25 | if n1 is not None: h += n1.data 26 | if n2 is not None: h += n2.data 27 | 28 | h += remember 29 | digit = h % 10 30 | remember = (h - (h % 10)) / 10 31 | 32 | if (n1 is not None) or (n2 is not None): 33 | ll.append(digit) 34 | else: 35 | if digit > 0: 36 | ll.append(digit) 37 | if remember > 0: 38 | ll.append(remember) 39 | 40 | return ll 41 | 42 | print add_lists(LinkedList([1, 1, 1]), LinkedList([9, 9, 9])).to_string() 43 | print add_lists(LinkedList([1]), LinkedList([9, 9, 9])).to_string() 44 | print add_lists(LinkedList([1]), LinkedList([2, 2])).to_string() 45 | -------------------------------------------------------------------------------- /2.5_find_loop.py: -------------------------------------------------------------------------------- 1 | from linked_list import Node, LinkedList 2 | 3 | def find_loop(ll): 4 | 5 | if (ll is None) or (ll.head is None): 6 | return None # no loop 7 | 8 | fast = ll.head 9 | slow = ll.head 10 | 11 | loop = None 12 | 13 | while (fast is not None) and (slow is not None): 14 | 15 | if (slow.next is None) or (fast.next is None) or (fast.next.next is None): 16 | return None # no loop 17 | 18 | slow = slow.next 19 | fast = fast.next.next 20 | 21 | if fast == slow: 22 | fast = ll.head 23 | 24 | while fast != slow: 25 | fast = fast.next 26 | slow = slow.next 27 | 28 | return slow 29 | 30 | return None 31 | 32 | def make_loop(rng, data): 33 | ll = LinkedList(rng) 34 | x = None 35 | y = None 36 | n = ll.head 37 | while True: 38 | if n.data == data: 39 | x = n 40 | if n.next == None: 41 | y = n 42 | break 43 | n = n.next 44 | y.next = x 45 | return ll 46 | 47 | for i in range(1, 9): 48 | l = find_loop(make_loop([1, 2, 3, 4, 5, 6, 7, 8], i)) 49 | print str(i) + ': loop in ' + str(l.data) 50 | -------------------------------------------------------------------------------- /3.0_stacks_queues.py: -------------------------------------------------------------------------------- 1 | from stack_queue import * 2 | 3 | s = Stack() 4 | for i in range(11): 5 | s.push(i) 6 | print s.to_string() 7 | 8 | while not s.is_empty(): 9 | n = s.pop() 10 | print 'Got ' + str(n) + ', remaining: ' + s.to_string() 11 | 12 | q = Queue() 13 | for i in range(11): 14 | q.enqueue(i) 15 | print q.to_string() 16 | 17 | while not q.is_empty(): 18 | n = q.dequeue() 19 | print 'Got ' + str(n) + ', remaining: ' + q.to_string() 20 | -------------------------------------------------------------------------------- /3.5_hanoi_towers.py: -------------------------------------------------------------------------------- 1 | from stack_queue import * 2 | 3 | def hanoi_towers(s1, s2, s3): 4 | move_stack(s1.length, s1, s3, s2) 5 | 6 | def move_stack(n, source, dest, other): 7 | if n > 1: 8 | move_stack(n - 1, source, other, dest) 9 | dest.push(source.pop()) 10 | if n > 1: 11 | move_stack(n - 1, other, dest, source) 12 | 13 | s1 = Stack() 14 | 15 | for i in range(10, 0, -1): 16 | s1.push(i) 17 | 18 | s2 = Stack() 19 | 20 | s3 = Stack() 21 | 22 | print 'Before:' 23 | print s1.to_string() 24 | print s2.to_string() 25 | print s3.to_string() 26 | 27 | hanoi_towers(s1, s2, s3) 28 | 29 | print 'After:' 30 | print s1.to_string() 31 | print s2.to_string() 32 | print s3.to_string() 33 | -------------------------------------------------------------------------------- /4.1_is_tree_balanced.py: -------------------------------------------------------------------------------- 1 | from binary_tree import * 2 | 3 | def is_balanced(n): 4 | maxd = max_depth(n) 5 | mind = min_depth(n) 6 | print 'Max depth: ' + str(maxd) 7 | print 'Min depth: ' + str(mind) 8 | 9 | return ((maxd - mind) <= 1) 10 | 11 | def max_depth(n): 12 | if n is None: 13 | return 0 14 | return 1 + max(max_depth(n.left), max_depth(n.right)) 15 | 16 | def min_depth(n): 17 | if n is None: 18 | return 0 19 | return 1 + min(min_depth(n.left), min_depth(n.right)) 20 | 21 | n = Node(10) 22 | r = n.add_right(Node(12)) 23 | rr = r.add_right(Node(13)) 24 | rl = r.add_left(Node(11)) 25 | 26 | l = n.add_left(Node(8)) 27 | ll = l.add_left(Node(7)) 28 | lr = l.add_right(Node(9)) 29 | 30 | print 'Balanced: ' + str(is_balanced(n)) 31 | -------------------------------------------------------------------------------- /4.2_find_route.py: -------------------------------------------------------------------------------- 1 | from graph import * 2 | from stack_queue import * 3 | 4 | state_unvisited = 'unvisited' 5 | state_visiting = 'visiting' 6 | state_visited = 'visited' 7 | 8 | def has_route_bfs(g, src, dst): 9 | if src == dst: return True 10 | 11 | state = {} 12 | for v in g.vertices: 13 | state[v.name] = state_unvisited 14 | 15 | q = Queue() 16 | state[src.name] = state_visiting 17 | q.enqueue(src) 18 | 19 | while not q.is_empty(): 20 | v = q.dequeue() 21 | 22 | if v == dst: return True 23 | 24 | for a in g.get_adjacent(v): 25 | if state[a.name] == state_unvisited: 26 | if a == dst: 27 | return True 28 | else: 29 | state[a.name] = state_visiting 30 | q.enqueue(a) 31 | 32 | state[v.name] = state_visited 33 | 34 | return False 35 | 36 | def has_route_dfs(g, src, dst): 37 | if src == dst: return True 38 | 39 | state = {} 40 | for v in g.vertices: 41 | state[v.name] = state_unvisited 42 | 43 | stack = Stack() 44 | state[src.name] = state_visiting 45 | stack.push(src) 46 | 47 | while not stack.is_empty(): 48 | v = stack.pop() 49 | 50 | if v == dst: return True 51 | 52 | for a in g.get_adjacent(v): 53 | if state[a.name] == state_unvisited: 54 | if a == dst: 55 | return True 56 | else: 57 | state[a.name] = state_visiting 58 | stack.push(a) 59 | 60 | state[v.name] = state_visited 61 | 62 | return False 63 | 64 | def test_has_route(g, src, dst): 65 | has_bfs = str(has_route_bfs(g, src, dst)) 66 | has_dfs = str(has_route_dfs(g, src, dst)) 67 | print 'Found route from ' + src.to_string() + ' to ' + dst.to_string() + ', BFS: ' + has_bfs + ', DFS: ' + has_dfs 68 | 69 | g = Graph() 70 | v1 = g.add_vertex('A', 1) 71 | v2 = g.add_vertex('B', 2) 72 | v3 = g.add_vertex('C', 3) 73 | v4 = g.add_vertex('D', 4) 74 | v5 = g.add_vertex('E', 5) 75 | v6 = g.add_vertex('F', 6) 76 | v7 = g.add_vertex('G', 7) 77 | v8 = g.add_vertex('H', 8) 78 | 79 | g.add_edge(v1, v2); 80 | g.add_edge(v1, v3); 81 | g.add_edge(v2, v4); 82 | g.add_edge(v2, v5); 83 | g.add_edge(v3, v6); 84 | g.add_edge(v3, v7); 85 | g.add_edge(v5, v8); 86 | 87 | print g.to_string() 88 | 89 | test_has_route(g, v1, v8) 90 | test_has_route(g, v3, v8) 91 | -------------------------------------------------------------------------------- /4.2_x_dijkstra.py: -------------------------------------------------------------------------------- 1 | from graph import * 2 | import sys 3 | 4 | state_unvisited = 'unvisited' 5 | state_visiting = 'visiting' 6 | state_visited = 'visited' 7 | 8 | def dijkstra(g, src, dst): 9 | if src == dst: return 0 10 | 11 | dist = {} 12 | prev = {} 13 | unvisited = [] 14 | for v in g.vertices: 15 | dist[v.name] = sys.maxint 16 | prev[v.name] = None 17 | unvisited.append(v) 18 | 19 | dist[src.name] = 0 20 | 21 | while len(unvisited) > 0: 22 | n = extract_cheapest(unvisited, dist) 23 | for child in g.get_adjacent(n): 24 | w = g.get_weight(n, child) 25 | if dist[n.name] + w < dist[child.name]: 26 | dist[child.name] = dist[n.name] + w 27 | prev[child.name] = n.name 28 | 29 | p = dst.name 30 | path = [] 31 | while True: 32 | path.append(p) 33 | if p == src.name: 34 | break 35 | p = prev[p] 36 | 37 | return dist[dst.name], path 38 | 39 | def extract_cheapest(unvisited, dist): 40 | best_dist = None 41 | best_ix = 0 42 | for i in range(len(unvisited)): 43 | if best_dist == None or dist[unvisited[i].name] < best_dist: 44 | best_dist = dist[unvisited[i].name] 45 | best_ix = i 46 | 47 | best = unvisited.pop(best_ix) 48 | return best 49 | 50 | def test_dijkstra(g, src, dst): 51 | print 'Shortest route from ' + src.to_string() + ' to ' + dst.to_string() + ': ' + str(dijkstra(g, src, dst)) 52 | 53 | g = Graph() 54 | v = [] 55 | for i in range(11): 56 | v.append(g.add_vertex('V' + str(i), i)) 57 | 58 | g.add_edge(v[1], v[2]); 59 | g.add_edge(v[1], v[3]); 60 | g.add_edge(v[2], v[4]); 61 | g.add_edge(v[2], v[5]); 62 | g.add_edge(v[3], v[6]); 63 | g.add_edge(v[3], v[7]); 64 | g.add_edge(v[5], v[8]); 65 | 66 | print g.to_string() 67 | 68 | test_dijkstra(g, v[1], v[8]) 69 | -------------------------------------------------------------------------------- /4.3_build_minimal_tree.py: -------------------------------------------------------------------------------- 1 | from binary_tree import * 2 | 3 | def create_minimal_tree(a): 4 | return add_to_tree(a, 0, len(a) - 1) 5 | 6 | def add_to_tree(a, l, r): 7 | if l > r: return None 8 | 9 | m = l + (r - l) / 2 10 | 11 | n = Node(a[m]) 12 | n.left = add_to_tree(a, l, m - 1) 13 | n.right = add_to_tree(a, m + 1, r) 14 | 15 | return n 16 | 17 | t = create_minimal_tree(range(0, 11)) 18 | print t.to_string() -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | cracking 2 | ======== 3 | 4 | Problems from "Cracking the programming interview" book solved in Python -------------------------------------------------------------------------------- /binary_tree.py: -------------------------------------------------------------------------------- 1 | class Node: 2 | data = None 3 | left = None 4 | right = None 5 | 6 | def __init__(self, data): 7 | self.data = data 8 | 9 | def add_left(self, n): 10 | if self.left == None: 11 | self.left = n 12 | else: 13 | self.left.add_left(n) 14 | return n 15 | 16 | def add_right(self, n): 17 | if self.right == None: 18 | self.right = n 19 | else: 20 | self.right.add_right(n) 21 | return n 22 | 23 | def to_string(self): 24 | s = '[' + str(self.data) + ' => [' 25 | 26 | if self.left != None: s += str(self.left.data) 27 | else: s += 'None' 28 | 29 | s += ', ' 30 | 31 | if self.right != None: s += str(self.right.data) 32 | else: s += 'None' 33 | 34 | s += "]]\n" 35 | 36 | if self.left != None: s += self.left.to_string() 37 | if self.right != None: s += self.right.to_string() 38 | 39 | return s 40 | 41 | class BinarySearchTree: 42 | 43 | root = None 44 | 45 | def insert(self, node, parent = None): 46 | 47 | if self.root is None: 48 | self.root = node 49 | return self.root 50 | 51 | if parent is None: parent = self.root 52 | 53 | if node.data < parent.data: 54 | if parent.left is None: 55 | parent.left = node 56 | return parent.left 57 | else: 58 | return self.insert(node, parent.left) 59 | else: 60 | if parent.right is None: 61 | parent.right = node 62 | return parent.right 63 | else: 64 | return self.insert(node, parent.right) 65 | 66 | def to_string(self): 67 | if self.root is None: 68 | return '[]' 69 | return self.root.to_string() 70 | -------------------------------------------------------------------------------- /binary_tree.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j-bennet/cracking/d03e2350dac23989189cb97a770b1f5493babda5/binary_tree.pyc -------------------------------------------------------------------------------- /binary_tree_add_delete.py: -------------------------------------------------------------------------------- 1 | from binary_tree import * 2 | 3 | bst = BinarySearchTree() 4 | 5 | #n = Node(10) 6 | #r = n.add_right(Node(12)) 7 | #rr = r.add_right(Node(13)) 8 | #rl = r.add_left(Node(11)) 9 | 10 | #l = n.add_left(Node(8)) 11 | #ll = l.add_left(Node(7)) 12 | #lr = l.add_right(Node(9)) 13 | 14 | bst.insert(Node(10)) 15 | bst.insert(Node(8)) 16 | bst.insert(Node(7)) 17 | bst.insert(Node(9)) 18 | 19 | print bst.to_string() -------------------------------------------------------------------------------- /binary_tree_deserialize.py: -------------------------------------------------------------------------------- 1 | from binary_tree import * 2 | 3 | def deserialize_nf(nodes): 4 | if nodes == None: return None 5 | if len(nodes) == 0: return None 6 | 7 | root = Node(nodes[0]) 8 | t = (len(nodes) - 1) / 2 9 | 10 | lnodes = nodes[1:t + 1] 11 | rnodes = nodes[t + 1:] 12 | 13 | read_tree_nf(root, lnodes, rnodes) 14 | return root 15 | 16 | def deserialize_lr(nodes): 17 | if nodes == None: return None 18 | if len(nodes) == 0: return None 19 | 20 | t = (len(nodes) - 1) / 2 21 | root = Node(nodes[t]) 22 | 23 | lnodes = nodes[0:t] 24 | rnodes = nodes[t + 1:] 25 | 26 | read_tree_lr(root, lnodes, rnodes) 27 | return root 28 | 29 | def read_tree_lr(current, lnodes, rnodes): 30 | if current == None: return 31 | 32 | if len(rnodes) == 1: 33 | if (rnodes[0] != None): 34 | current.add_right(Node(rnodes[0])) 35 | else: 36 | t = (len(rnodes) - 1) / 2 37 | r = Node(rnodes[t]) 38 | read_tree_lr(r, rnodes[0:t], rnodes[t + 1:]) 39 | current.add_right(r) 40 | 41 | if len(lnodes) == 1: 42 | if (lnodes[0] != None): 43 | current.add_left(Node(lnodes[0])) 44 | else: 45 | t = (len(lnodes) - 1) / 2 46 | l = Node(lnodes[t]) 47 | read_tree_lr(l, lnodes[0:t], lnodes[t+1:]) 48 | current.add_left(l) 49 | 50 | def read_tree_nf(current, lnodes, rnodes): 51 | if current == None: return 52 | 53 | if len(rnodes) == 1: 54 | if (rnodes[0] != None): 55 | current.add_right(Node(rnodes[0])) 56 | else: 57 | t = (len(rnodes) - 1) / 2 58 | r = Node(rnodes[0]) 59 | read_tree_nf(r, rnodes[1:t + 1], rnodes[t + 1:]) 60 | current.add_right(r) 61 | 62 | if len(lnodes) == 1: 63 | if (lnodes[0] != None): 64 | current.add_left(Node(lnodes[0])) 65 | else: 66 | t = (len(lnodes) - 1) / 2 67 | l = Node(lnodes[0]) 68 | read_tree_nf(l, lnodes[1:t + 1], lnodes[t + 1:]) 69 | current.add_left(l) 70 | 71 | root = deserialize_nf(['A', 'B', 'D', 'E', 'C', 'F', None]) 72 | print root.to_string() 73 | 74 | root = deserialize_lr(['D', 'B', 'E', 'A', 'F', 'C', None]) 75 | print root.to_string() 76 | -------------------------------------------------------------------------------- /binary_tree_traverse.py: -------------------------------------------------------------------------------- 1 | from binary_tree import * 2 | 3 | def traverse_inorder(n): 4 | if n.left is not None: 5 | traverse_inorder(n.left) 6 | print str(n.data) + ' ' 7 | if n.right is not None: 8 | traverse_inorder(n.right) 9 | 10 | def traverse_preorder(n): 11 | print str(n.data) + ' ' 12 | if n.left is not None: 13 | traverse_inorder(n.left) 14 | if n.right is not None: 15 | traverse_inorder(n.right) 16 | 17 | def traverse_postorder(n): 18 | if n.left is not None: 19 | traverse_inorder(n.left) 20 | if n.right is not None: 21 | traverse_inorder(n.right) 22 | print str(n.data) + ' ' 23 | 24 | n = Node(10) 25 | r = n.add_right(Node(12)) 26 | rr = r.add_right(Node(13)) 27 | rl = r.add_left(Node(11)) 28 | 29 | l = n.add_left(Node(8)) 30 | ll = l.add_left(Node(7)) 31 | lr = l.add_right(Node(9)) 32 | 33 | print n.to_string() 34 | 35 | print 'In-order:' 36 | traverse_inorder(n) 37 | 38 | print 'Pre-order:' 39 | traverse_preorder(n) 40 | 41 | print 'Post-order:' 42 | traverse_postorder(n) 43 | -------------------------------------------------------------------------------- /birthday_paradox.py: -------------------------------------------------------------------------------- 1 | import math 2 | 3 | def birthdays(k): 4 | n = 365 5 | p_exist = 1. - (1. - 1. / n) ** k #1. - math.factorial(n) / math.factorial(n-k) / n ** k 6 | return p_exist 7 | 8 | for i in range(10, 100, 10): 9 | print '%d: %.2f' % (i, 100 * birthdays(i)) -------------------------------------------------------------------------------- /fibonacci.py: -------------------------------------------------------------------------------- 1 | def fact(n): 2 | print 'n =', n 3 | if n == 0: 4 | return 1 5 | return n * fact(n - 1) 6 | 7 | def rabbits(n): 8 | if n == 0: 9 | return 0 10 | if n == 1: 11 | return 1 12 | if n >= 2 and n <= 5: 13 | return rabbits(n - 1) + rabbits(n - 2) 14 | return rabbits(n - 1) + rabbits(n - 2) - rabbits(n - 5) 15 | 16 | def fast_rabbits(n): 17 | current = 0 18 | after = 1 19 | dead = [] 20 | for i in range(0, n): 21 | 22 | dead.append(current) 23 | if len(dead) > 4: dead.pop(0) 24 | 25 | if len(dead) < 4: 26 | current, after = after, current + after 27 | else: 28 | current, after = after, current + after - dead[0] 29 | return current 30 | 31 | def fibonacci(n): 32 | if n == 0: 33 | return 0 34 | if n == 1: 35 | return 1 36 | return fibonacci(n - 1) + fibonacci(n - 2) 37 | 38 | def fast_fibonacci(n): 39 | current = 0 40 | after = 1 41 | for i in range(0, n): 42 | current, after = after, current + after 43 | return current 44 | 45 | fact(6) 46 | 47 | #print fibonacci(0) 48 | #print fibonacci(5) 49 | #print fibonacci(8) 50 | #print fibonacci(24) 51 | #print fibonacci(36) 52 | 53 | #print fast_fibonacci(6) 54 | #print fast_fibonacci(20) 55 | #print fast_fibonacci(8) 56 | #print fast_fibonacci(24) 57 | #print fast_fibonacci(36) 58 | 59 | #print rabbits(10) 60 | #print rabbits(15) 61 | #print rabbits(20) 62 | 63 | #print fast_rabbits(10) 64 | #print fast_rabbits(15) 65 | #print fast_rabbits(20) 66 | -------------------------------------------------------------------------------- /graph.py: -------------------------------------------------------------------------------- 1 | class Vertex: 2 | name = None 3 | data = None 4 | 5 | def __init__(self, name, data): 6 | self.name = name 7 | self.data = data 8 | 9 | def __eq__(self, other): 10 | if isinstance(other, Vertex): 11 | return self.name == other.name 12 | return False 13 | 14 | def __ne__(self, other): 15 | if isinstance(other, Vertex): 16 | return self.name != other.name 17 | return False 18 | 19 | def to_string(self): 20 | s = '(' + str(self.name) + ', ' + str(self.data) + ')' 21 | return s 22 | 23 | class Edge: 24 | src = None 25 | dst = None 26 | weight = None 27 | 28 | def __init__(self, src, dst, weight = 1): 29 | self.src = src 30 | self.dst = dst 31 | self.weight = weight 32 | 33 | def __eq__(self, other): 34 | if isinstance(other, Edge): 35 | return (self.src == other.src) and (self.dst == other.dst) 36 | return False 37 | 38 | def __ne__(self, other): 39 | if isinstance(other, Edge): 40 | return (self.src != other.src) or (self.dst != other.dst) 41 | return False 42 | 43 | class Graph: 44 | 45 | vertices = None 46 | edges = None 47 | 48 | def __init__(self): 49 | self.vertices = [] 50 | self.edges = [] 51 | 52 | def add_vertex(self, name, data): 53 | v = Vertex(name, data) 54 | if v not in self.vertices: 55 | self.vertices.append(v) 56 | return v 57 | 58 | def add_edge(self, src, dst, weight = 1): 59 | e = Edge(src, dst, weight) 60 | if e not in self.edges: 61 | self.edges.append(e) 62 | return e 63 | 64 | def get_adjacent(self, src): 65 | adj = [] 66 | for e in self.edges: 67 | if (e.src.name == src.name): 68 | adj.append(e.dst) 69 | return adj 70 | 71 | def get_weight(self, src, dst): 72 | for e in self.edges: 73 | if e.src.name == src.name and e.dst.name == dst.name: 74 | return e.weight 75 | return None 76 | 77 | def to_string(self): 78 | s = '[' 79 | for i in range(len(self.vertices)): 80 | v = self.vertices[i] 81 | s += "\n" + v.to_string() + ' => [' 82 | se = '' 83 | for a in self.get_adjacent(v): 84 | if len(se) > 0: se += ', ' 85 | se += a.to_string() 86 | s += se 87 | s += ']' 88 | if i < (len(self.vertices) - 1): 89 | s += ', ' 90 | s += "\n]" 91 | return s 92 | -------------------------------------------------------------------------------- /graph.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j-bennet/cracking/d03e2350dac23989189cb97a770b1f5493babda5/graph.pyc -------------------------------------------------------------------------------- /heap.py: -------------------------------------------------------------------------------- 1 | class Heap: 2 | q = [] 3 | 4 | def parent(self, i): 5 | if i == 0: 6 | return None 7 | return (i + 1) / 2 - 1 8 | 9 | def young_child(self, i): 10 | return (i + 1) * 2 - 1 11 | 12 | def insert(self, n): 13 | self.q.append(n) 14 | self.bubble_up(len(self.q) - 1) 15 | 16 | def bubble_up(self, i): 17 | pi = self.parent(i) 18 | if pi is None: 19 | return 20 | 21 | if self.q[pi] > self.q[i]: 22 | self.q[pi], self.q[i] = self.q[i], self.q[pi] 23 | self.bubble_up(pi) 24 | 25 | def bubble_down(self, i): 26 | ci = self.young_child(i) 27 | min_ix = i 28 | for j in range(0, 2): 29 | if (ci + j) < len(self.q): 30 | if self.q[min_ix] > self.q[ci + j]: 31 | min_ix = ci + j 32 | 33 | if min_ix != i: 34 | self.q[i], self.q[min_ix] = self.q[min_ix], self.q[i] 35 | self.bubble_down(min_ix) 36 | 37 | def make_heap(self, nodes): 38 | self.q = [] 39 | for n in nodes: 40 | self.insert(n) 41 | 42 | def extract_min(self): 43 | if len(self.q) == 0: 44 | return None 45 | n = None 46 | if len(self.q) > 1: 47 | n = self.q[0] 48 | self.q[0] = self.q.pop(len(self.q) - 1) 49 | self.bubble_down(0) 50 | else: 51 | n = self.q.pop() 52 | return n -------------------------------------------------------------------------------- /heap.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j-bennet/cracking/d03e2350dac23989189cb97a770b1f5493babda5/heap.pyc -------------------------------------------------------------------------------- /knapsack.py: -------------------------------------------------------------------------------- 1 | def knapsack_cost(items, costs, max_count): 2 | maxcost = [] 3 | 4 | total_items = 0 5 | 6 | for i in range(len(items)): 7 | total_items += items[i] 8 | 9 | for i in range(total_items + 1): 10 | maxcost.append(-1) 11 | 12 | maxcost[0] = 0 13 | 14 | for i in range(1, len(maxcost)): 15 | i_max_thing = -1 16 | max_thing_cost = -1 17 | for j in range(len(costs)): 18 | if items[j] > 0 and max_thing_cost < costs[j]: 19 | max_thing_cost = costs[j] 20 | i_max_thing = j 21 | if i_max_thing != -1: 22 | maxcost[i] = maxcost[i - 1] + max_thing_cost 23 | items[i_max_thing] -= 1 24 | print 'Took item at ' + str(costs[i_max_thing]) + ', items left:', items 25 | 26 | print 'Max set costs:', maxcost 27 | return maxcost[max_count] 28 | 29 | items = [2, 3, 4, 1] 30 | costs = [1., 5., 2., 10.] 31 | max_count = 8 32 | 33 | print 'Max at ' + str(max_count) + ' is ' + str(knapsack_cost(items, costs, max_count)) -------------------------------------------------------------------------------- /linked_list.py: -------------------------------------------------------------------------------- 1 | class Node: 2 | 3 | data = 0 4 | next = None 5 | 6 | def __init__(self, data): 7 | self.data = data 8 | 9 | def append(self, data): 10 | tailnode = Node(data) 11 | 12 | n = self 13 | while n.next is not None: 14 | n = n.next 15 | 16 | n.next = tailnode 17 | 18 | class LinkedList: 19 | 20 | head = None 21 | 22 | def __init__(self): 23 | self.head = None 24 | 25 | def __init__(self, from_list): 26 | if from_list is None: 27 | self.head = None 28 | return 29 | 30 | for data in from_list: 31 | self.append(data) 32 | 33 | def append(self, data): 34 | if self.head is None: 35 | self.head = Node(data) 36 | else: 37 | self.head.append(data) 38 | 39 | def remove(self, data): 40 | if self.head is None: 41 | return None 42 | 43 | if self.head.data == data: 44 | self.head = self.head.next 45 | else: 46 | p = self.head 47 | n = self.head.next 48 | while n is not None: 49 | if n.data == data: 50 | p.next = n.next 51 | break 52 | else: 53 | p = n 54 | n = n.next 55 | 56 | return self.head 57 | 58 | def to_string(self): 59 | s = '[' 60 | 61 | n = self.head 62 | 63 | while n is not None: 64 | s = s + str(n.data) 65 | if n.next is not None: 66 | s = s + ', ' 67 | n = n.next 68 | 69 | s = s + ']' 70 | return s 71 | 72 | def output(self): 73 | import sys 74 | sys.stdout.write(self.to_string()) 75 | print '' 76 | -------------------------------------------------------------------------------- /linked_list.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j-bennet/cracking/d03e2350dac23989189cb97a770b1f5493babda5/linked_list.pyc -------------------------------------------------------------------------------- /regex.py: -------------------------------------------------------------------------------- 1 | import re 2 | 3 | s = 'name @ domain1 .domain2.domain3.com' 4 | 5 | m = re.match(r'([A-Za-z0-9]+)\s*@\s*(\s*(?:[A-Za-z0-9\s.-]+)\s*\.?\s*)+', s) 6 | print m.groups() 7 | -------------------------------------------------------------------------------- /sorting_tests.py: -------------------------------------------------------------------------------- 1 | from heap import * 2 | 3 | def heap_sort(a): 4 | h = Heap() 5 | h.make_heap(a) 6 | for i in range(len(a)): 7 | a[i] = h.extract_min() 8 | return a 9 | 10 | def selection_sort(a): 11 | ix_min = 0 12 | for i in range(len(a)): 13 | ix_min = i 14 | for j in range(i + 1, len(a)): 15 | if a[j] < a[ix_min]: 16 | ix_min = j 17 | if ix_min != i: 18 | a[ix_min], a[i] = a[i], a[ix_min] 19 | 20 | return a 21 | 22 | def insertion_sort(a): 23 | for i in range(1, len(a)): 24 | j = i 25 | while (j > 0) and (a[j] < a[j - 1]): 26 | a[j], a[j - 1] = a[j - 1], a[j] 27 | j -= 1 28 | 29 | return a 30 | 31 | def quick_sort(a): 32 | if len(a) <= 1: return a 33 | 34 | m = (len(a) - 1) / 2 35 | l = [] 36 | r = [] 37 | 38 | for i in range(len(a)): 39 | if i != m: 40 | if a[i] <= a[m]: 41 | l.append(a[i]) 42 | else: 43 | r.append(a[i]) 44 | 45 | l = quick_sort(l) 46 | r = quick_sort(r) 47 | 48 | l.append(a[m]) 49 | l.extend(r) 50 | 51 | return l 52 | 53 | def quick_sort_in_place(a): 54 | quick_sort_in_place_r(a, 0, len(a) - 1) 55 | return a 56 | 57 | def quick_sort_in_place_r(a, l, r): 58 | if l < r: 59 | pi = l + (r - l) / 2; 60 | pi = quick_sort_partition(a, l, r, pi) 61 | quick_sort_in_place_r(a, l, pi - 1) 62 | quick_sort_in_place_r(a, pi + 1, r) 63 | 64 | def quick_sort_partition(a, l, r, m): 65 | pivot = a[m] 66 | a[m], a[r] = a[r], a[m] 67 | ix = l 68 | 69 | for i in range(l, r): 70 | if a[i] < pivot: 71 | a[i], a[ix] = a[ix], a[i] 72 | ix += 1 73 | 74 | a[ix], a[r] = a[r], a[ix] 75 | return ix 76 | 77 | def merge_sort(a): 78 | if len(a) <= 1: return a 79 | 80 | m = (len(a) - 1) / 2 81 | l = merge_sort(a[:m + 1]) 82 | r = merge_sort(a[m + 1:]) 83 | a = merge(l, r) 84 | return a 85 | 86 | def merge(l, r): 87 | t = [] 88 | i = 0 89 | j = 0 90 | while i < len(l) or j < len(r): 91 | if i < len(l) and j < len(r): 92 | if l[i] < r[j]: 93 | t.append(l[i]) 94 | i += 1 95 | else: 96 | t.append(r[j]) 97 | j += 1 98 | else: 99 | if i < len(l): 100 | t.append(l[i]) 101 | i += 1 102 | else: 103 | t.append(r[j]) 104 | 105 | j += 1 106 | return t 107 | 108 | print 'Selection:' 109 | print selection_sort([12, 11, 10, 2, 9, 1, 8, 5, 7, 15, 4, 3, 13, 14]) 110 | 111 | print 'Insertion:' 112 | print insertion_sort([12, 11, 10, 2, 9, 1, 8, 5, 7, 15, 4, 3, 13, 14]) 113 | 114 | print 'Merge:' 115 | print merge_sort([12, 11, 10, 2, 9, 1, 8, 5, 7, 15, 4, 3, 13, 14]) 116 | 117 | print 'Quick:' 118 | print quick_sort([12, 11, 10, 2, 9, 1, 8, 5, 7, 15, 4, 3, 13, 14]) 119 | 120 | print 'Quick in-place:' 121 | print quick_sort_in_place([12, 11, 10, 2, 9, 1, 8, 5, 7, 15, 4, 3, 13, 14]) 122 | 123 | print 'Heap:' 124 | print heap_sort([12, 11, 10, 2, 9, 1, 8, 5, 7, 15, 4, 3, 13, 14]) -------------------------------------------------------------------------------- /stack_queue.py: -------------------------------------------------------------------------------- 1 | class Node: 2 | next = None 3 | data = 0 4 | 5 | def __init__(self, data): 6 | self.data = data 7 | 8 | def to_string(self): 9 | s = '[' 10 | n = self 11 | while n is not None: 12 | s += str(n.data) 13 | n = n.next 14 | if n is not None: s += ', ' 15 | s += ']' 16 | return s 17 | 18 | class Stack: 19 | 20 | top = None 21 | length = 0 22 | 23 | def push(self, data): 24 | t = Node(data) 25 | t.next = self.top 26 | self.top = t 27 | self.length += 1 28 | 29 | def pop(self): 30 | if self.top is not None: 31 | data = self.top.data 32 | self.top = self.top.next 33 | self.length -= 1 34 | return data 35 | return None 36 | 37 | def to_string(self): 38 | if self.top is None: 39 | return '[]' 40 | return self.top.to_string() 41 | 42 | def is_empty(self): 43 | return self.top is None 44 | 45 | class Queue: 46 | first = None 47 | last = None 48 | length = 0 49 | 50 | def enqueue(self, data): 51 | n = Node(data) 52 | if self.first is None: 53 | self.first = self.last = n 54 | else: 55 | if self.length == 1: 56 | self.first.next = n 57 | else: 58 | self.last.next = n 59 | self.last = n 60 | self.length += 1 61 | 62 | def dequeue(self): 63 | if self.first is not None: 64 | data = self.first.data 65 | self.first = self.first.next 66 | self.length -= 1 67 | if self.first is None: self.last = None 68 | return data 69 | return None 70 | 71 | def debug(self, message = None): 72 | if (message): print message 73 | if self.first is None: 74 | print 'First: None' 75 | else: 76 | print 'First: ' + str(self.first.data.name) 77 | if self.last is None: 78 | print 'Last: None' 79 | else: 80 | print 'Last: ' + str(self.last.data.name) 81 | 82 | def to_string(self): 83 | if self.first is None: 84 | return '[]' 85 | return self.first.to_string() 86 | 87 | def is_empty(self): 88 | return self.first is None 89 | -------------------------------------------------------------------------------- /stack_queue.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j-bennet/cracking/d03e2350dac23989189cb97a770b1f5493babda5/stack_queue.pyc --------------------------------------------------------------------------------