├── 1_2_reverse.py ├── 1_3_duplicate_characters.py ├── 1_4_anagrams.py ├── 1_5_spaces.py ├── 1_7_matrix_0.py ├── 1_8_substring_rotation.py ├── 20_1_custom_add.py ├── 3_2_stack_with_minimum.py ├── 3_3_set_of_stacks.py ├── 3_4_hanoi.py ├── 3_5_myqueue.py ├── 3_6_sorted_stack.py ├── 7_1_deck_of_cards.py ├── README.md ├── files └── word_list.txt ├── non_repeating_character.py ├── reversed_words.py └── tally_word_count.py /1_2_reverse.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | 4 | def reverse(string): 5 | """Reverse a given string.""" 6 | return string[::-1] 7 | 8 | 9 | def main(): 10 | print reverse('a') 11 | print reverse('abcd') 12 | print reverse('hello world') 13 | 14 | if __name__ == '__main__': 15 | main() 16 | -------------------------------------------------------------------------------- /1_3_duplicate_characters.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | 4 | def remove_duplicates(string): 5 | """Remove duplicate characters in a string.""" 6 | return set(string) 7 | 8 | 9 | def remove_with_dict(string): 10 | """Implement own set function as dict keys.""" 11 | string_dict = {} 12 | for letter in string: 13 | if letter not in string_dict: 14 | string_dict[letter] = True 15 | return string_dict.keys() 16 | 17 | 18 | def main(): 19 | # Sets. 20 | print remove_duplicates('a') 21 | print remove_duplicates('abb') 22 | print remove_duplicates('abcd') 23 | print remove_duplicates('abcda') 24 | # List of dictionay keys. 25 | print remove_with_dict('a') 26 | print remove_with_dict('abb') 27 | print remove_with_dict('abcd') 28 | print remove_with_dict('abcda') 29 | 30 | if __name__ == '__main__': 31 | main() 32 | -------------------------------------------------------------------------------- /1_4_anagrams.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | 4 | def anagram(first, second): 5 | """Decide if two strings are anagrams of one another.""" 6 | return sorted(first) == sorted(second) 7 | 8 | 9 | def main(): 10 | print anagram('a', 'b') 11 | print anagram('a', 'aa') 12 | print anagram('hi', 'hi') 13 | print anagram('hello there', 'there hello') 14 | 15 | if __name__ == '__main__': 16 | main() 17 | -------------------------------------------------------------------------------- /1_5_spaces.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import re 4 | 5 | 6 | def replace_space(string): 7 | """Replace all spaces in a word with `%20`.""" 8 | return re.sub(' ', '%20', string) 9 | 10 | 11 | def main(): 12 | print replace_space('abcd') 13 | print replace_space('hello world') 14 | print replace_space('another working example') 15 | 16 | if __name__ == '__main__': 17 | main() 18 | -------------------------------------------------------------------------------- /1_7_matrix_0.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """If an element in an MxN matrix is 0, it's row and column are set to 0.""" 4 | 5 | 6 | def adjust_matrix(matrix): 7 | """ 8 | Given a matrix of size MxN, if an element is zero, set it's row and 9 | column to zeros. 10 | """ 11 | zero_rows = {} 12 | zero_columns = {} 13 | # Get location of all the zeros. 14 | for i, row in enumerate(matrix): 15 | for j, num in enumerate(row): 16 | if num is 0: 17 | zero_rows[i] = True 18 | zero_columns[j] = True 19 | # Adjust the matrix accordingly. 20 | for i, row in enumerate(matrix): 21 | for j, num in enumerate(row): 22 | # Dictionary lookup is O(1). 23 | if i in zero_rows or j in zero_columns: 24 | matrix[i][j] = 0 25 | return matrix 26 | 27 | 28 | def main(): 29 | matrix = [[1],[2],[3]] 30 | print adjust_matrix(matrix) 31 | 32 | matrix = [[1, 2], [1, 0]] 33 | print adjust_matrix(matrix) 34 | 35 | matrix = [[1, 2, 3], [1, 2, 0], [1, 2, 3]] 36 | print adjust_matrix(matrix) 37 | 38 | matrix = [[1, 2, 3, 4], [1, 2, 3, 4], 39 | [1, 2, 0, 4], [1, 2, 3, 4]] 40 | print adjust_matrix(matrix) 41 | 42 | if __name__ == '__main__': 43 | main() 44 | -------------------------------------------------------------------------------- /1_8_substring_rotation.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | 4 | def is_rotation(first, second): 5 | """Given two strings, is one a rotation of the other.""" 6 | if len(first) != len(second): 7 | return False 8 | double_second = second + second 9 | return first in double_second 10 | 11 | 12 | def main(): 13 | print is_rotation('apple', 'pleap') # True 14 | print is_rotation('apple', 'ppale') # False 15 | print is_rotation('zach', 'chza') # True 16 | 17 | 18 | if __name__ == '__main__': 19 | main() 20 | -------------------------------------------------------------------------------- /20_1_custom_add.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | Write a function that adds two numbers -- but no arithmetic operators can be 5 | used. 6 | """ 7 | 8 | def sum_add(first, second): 9 | """Kind of cheating to use Python's sum function.""" 10 | return sum([first, second]) 11 | 12 | 13 | def binary_add(first, second): 14 | """Binary voodoo magic.""" 15 | if second == 0: 16 | return first 17 | elif first == 0: 18 | return second 19 | xor = first ^ second 20 | carry = (first & second) << 1 21 | return binary_add(xor, carry) 22 | 23 | 24 | def array_add(first, second): 25 | """ 26 | Addition with bytearrays. Since arrays allocate a specific amount of 27 | memory, this way is somewhat inefficient -- but about twice as fast as 28 | using Python's range function. 29 | """ 30 | first_array = bytearray(first) 31 | second_array = bytearray(second) 32 | first_array.extend(second_array) 33 | return len(first_array) 34 | 35 | 36 | def main(): 37 | # Sum way. 38 | print sum_add(0, 1) # 1 39 | print sum_add(2, 3) # 5 40 | print sum_add(20, 12) # 32 41 | print sum_add(50, 49) # 99 42 | # Binary way. 43 | print binary_add(0, 1) # 1 44 | print binary_add(2, 3) # 5 45 | print binary_add(20, 12) # 32 46 | print binary_add(50, 49) # 99 47 | # With bytearrays. 48 | print array_add(0, 1) # 1 49 | print array_add(2, 3) # 5 50 | print array_add(20, 12) # 32 51 | print array_add(50, 49) # 99 52 | 53 | 54 | if __name__ == '__main__': 55 | main() 56 | -------------------------------------------------------------------------------- /3_2_stack_with_minimum.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | Design a stack, which in addition to push and pop, also has a function to 5 | return the minimum element. 6 | """ 7 | 8 | class Stack(list): 9 | 10 | def push(self, number): 11 | """Push method -- similar to other languages.""" 12 | if len(self) > 0: 13 | last = self[-1] 14 | minimum = self._find_minimum(number, last) 15 | else: 16 | minimum = number 17 | self.minimum = minimum 18 | self.append(NodeWithMin(number, minimum)) 19 | 20 | def _find_minimum(self, number, last_number): 21 | """Internal method to compare two numbers.""" 22 | if number < last_number.minimum: 23 | return number 24 | return last_number.minimum 25 | 26 | def min(self): 27 | """Return the minimum element.""" 28 | return self.minimum 29 | 30 | 31 | class NodeWithMin(object): 32 | 33 | def __init__(self, number, minimum): 34 | self.number = number 35 | self.minimum = minimum 36 | 37 | def __repr__(self): 38 | return str(self.number) 39 | 40 | def min(self): 41 | return self.minimum 42 | 43 | 44 | def main(): 45 | stack = Stack() 46 | stack.push(1) 47 | stack.push(2) 48 | stack.push(3) 49 | node = stack.pop() 50 | print node.minimum 51 | stack.push(0) 52 | stack.push(4) 53 | node = stack.pop() 54 | print node.min() 55 | print stack.min() 56 | print stack 57 | 58 | if __name__ == '__main__': 59 | main() 60 | -------------------------------------------------------------------------------- /3_3_set_of_stacks.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | SetOfStacks should be composed of several stacks, and should create a new 5 | stack one the previous one exceeds capacity. SetOfStacks push and pop methods 6 | should behave identically to a single stack. 7 | """ 8 | 9 | class SetOfStacks(list): 10 | 11 | def __init__(self, capacity=4): 12 | self.stacks = [] 13 | self.last_stack = [] 14 | self.capacity = capacity 15 | self.stacks.append(self.last_stack) 16 | 17 | def __repr__(self): 18 | return str(self.stacks) 19 | 20 | def push(self, number): 21 | last_stack = self.last_stack 22 | if len(last_stack) is self.capacity: 23 | last_stack = [] 24 | self.last_stack = last_stack 25 | self.stacks.append(last_stack) 26 | last_stack.append(number) 27 | 28 | def pop(self): 29 | last_stack = self.last_stack 30 | number = last_stack.pop() 31 | if len(last_stack) is 0: 32 | self.stacks.pop() 33 | self.last_stack = self.stacks[-1] 34 | return number 35 | 36 | 37 | def main(): 38 | stack = SetOfStacks() 39 | stack.push(1) 40 | stack.push(2) 41 | stack.push(3) 42 | stack.push(4) 43 | stack.push(5) 44 | stack.push(6) 45 | print stack 46 | stack.pop() 47 | stack.pop() 48 | stack.pop() 49 | print stack 50 | 51 | if __name__ == '__main__': 52 | main() 53 | -------------------------------------------------------------------------------- /3_4_hanoi.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | Towers of Hanoi in Python. 5 | 6 | Originally from: http://codesnippets.joyent.com/posts/show/530 7 | 8 | Notice how it takes 2^n - 1 number of moves to complete. 9 | To see this for yourself, run the following from the commandline: 10 | python 3_4_hanoi.py | wc -l 11 | """ 12 | 13 | 14 | def hanoi(n, a='A', b='B', c='C'): 15 | """Move n discs from a to c using b as middle.""" 16 | if n == 0: 17 | return 18 | hanoi(n - 1, a, c, b) 19 | print a, '->', c 20 | hanoi(n - 1, b, a, c) 21 | 22 | 23 | def main(): 24 | hanoi(4) 25 | 26 | 27 | if __name__ == '__main__': 28 | main() 29 | -------------------------------------------------------------------------------- /3_5_myqueue.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | Implement a queue with two stacks in the MyQueue class. 5 | 6 | This should never be used, though -- the deque data structure from the 7 | standard library collections module should be used instead. 8 | """ 9 | 10 | 11 | class MyQueue(object): 12 | 13 | def __init__(self): 14 | self.first = [] 15 | self.second = [] 16 | 17 | def size(self): 18 | return len(self.first) + len(self.second) 19 | 20 | def add(self, number): 21 | self.first.append(number) 22 | 23 | def peek(self): 24 | first = self.first 25 | second = self.second 26 | if len(second): 27 | return second[-1] 28 | while len(first): 29 | second.append(first.pop()) 30 | return second[-1] 31 | 32 | def remove(self): 33 | first = self.first 34 | second = self.second 35 | if len(second): 36 | return second.pop() 37 | while len(first): 38 | second.append(first.pop()) 39 | return second.pop() 40 | 41 | 42 | def main(): 43 | queue = MyQueue() 44 | queue.add(1) 45 | queue.add(2) 46 | queue.add(3) 47 | print queue.size() # 3 48 | print queue.peek() # 1 49 | print queue.remove() # 1 50 | print queue.peek() # 2 51 | 52 | if __name__ == '__main__': 53 | main() 54 | -------------------------------------------------------------------------------- /3_6_sorted_stack.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | Write a program to sort a stack. 5 | 6 | This is O(N^2). 7 | """ 8 | 9 | 10 | def built_in_sort(stack): 11 | stack.sort() 12 | return stack 13 | 14 | 15 | def custom_sort(stack): 16 | """Custom version of list sort. This should never be used.""" 17 | new_stack = [] 18 | while len(stack): 19 | temp = stack.pop() 20 | while len(new_stack) and new_stack[-1] > temp: 21 | stack.append(new_stack.pop()) 22 | new_stack.append(temp) 23 | return new_stack 24 | 25 | 26 | def main(): 27 | stack = [1, 3, 2, 4, 6, 5] 28 | print built_in_sort(stack) 29 | print custom_sort(stack) 30 | 31 | 32 | if __name__ == '__main__': 33 | main() 34 | -------------------------------------------------------------------------------- /7_1_deck_of_cards.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | Design the data structure for a generic deck of cards. 5 | 6 | Python Docs: http://docs.python.org/reference/datamodel.html 7 | """ 8 | 9 | 10 | class Card(object): 11 | 12 | def __init__(self, card_value, suit=None, game_value=None): 13 | face_cards = {'J': 11, 'Q': 12, 14 | 'K': 13, 'A': 1} 15 | if game_value: 16 | self.game_value = game_value 17 | elif card_value in face_cards: 18 | self.game_value = face_cards[card_value] 19 | else: 20 | self.game_value = card_value 21 | self.card_value = str(card_value) 22 | self.suit = suit 23 | 24 | def __repr__(self): 25 | if self.suit: 26 | return ' '.join(['[', self.card_value, 'of', self.suit, ']']) 27 | return ' '.join(['[', self.card_value, ']']) 28 | 29 | def __cmp__(self, other): 30 | """Called by comparison operators.""" 31 | return self.game_value - other.game_value 32 | 33 | 34 | def main(): 35 | jack = Card('J', 'clubs') 36 | print jack 37 | 38 | king = Card('K', 'hearts') 39 | print king 40 | print 'K > J:', king > jack 41 | 42 | ten = Card(10, 'diamonds') 43 | print ten 44 | print '10 < J:', ten < jack 45 | 46 | queen = Card('Q', 'spades') 47 | print queen 48 | print 'J < Q < K:', jack < queen < king 49 | 50 | joker = Card('Joker', game_value=100) 51 | print joker 52 | print 'Joker > K:', joker > king 53 | 54 | 55 | if __name__ == '__main__': 56 | main() 57 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Cracking the Coding Interview - Python 2 | ====================================== 3 | 4 | I've been reading the book [Cracking the Coding 5 | Interview](http://amzn.to/crack_code), and decided to write the answers in 6 | Python (all of the book's solutions are in Java). 7 | -------------------------------------------------------------------------------- /non_repeating_character.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | You have a string and need to find the first non-repeating characters in the 5 | string. 6 | 7 | For earlier versions of Python, the OrderedDict data structure is available 8 | from the Python cookbook: http://code.activestate.com/recipes/576693/ 9 | 10 | NOTE: This approach goes through the string twice, but is still O(N). 11 | """ 12 | 13 | from collections import OrderedDict, deque 14 | 15 | 16 | def iterable_to_ordered_dict(iterable): 17 | """ 18 | Change from an iterable data structure (list, tuple, string) to an 19 | ordered dictionary data structure. 20 | """ 21 | ordered_dict = OrderedDict() 22 | for letter in iterable: 23 | if letter in ordered_dict and ordered_dict[letter] == 1: 24 | # No real need to += increment the value, 25 | # it no longer meets our requirements. 26 | ordered_dict[letter] = False 27 | else: 28 | ordered_dict[letter] = 1 29 | return ordered_dict 30 | 31 | 32 | def find_first_value(ordered_dict): 33 | """Find first non-repeating character.""" 34 | for letter in ordered_dict.keys(): 35 | if ordered_dict[letter] == 1: 36 | return letter 37 | return False 38 | 39 | 40 | def first_value_queue(ordered_dict): 41 | """ 42 | Return a queue of values that can then be popped to return the next 43 | occurence of a non-repeating character in a string. 44 | """ 45 | queue = deque(letter for letter in ordered_dict.keys() if 46 | ordered_dict[letter]) 47 | return queue 48 | 49 | 50 | def main(): 51 | d = iterable_to_ordered_dict('abacaddeea') 52 | print find_first_value(d) # b 53 | queue = first_value_queue(d) 54 | print queue.popleft() # b 55 | print queue.popleft() # c 56 | 57 | 58 | if __name__ == '__main__': 59 | main() 60 | -------------------------------------------------------------------------------- /reversed_words.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | Reverse the word order for the words in a sentence. 5 | 6 | Example: 7 | I like to write Python. 8 | 9 | Becomes: 10 | Python. write to like I 11 | """ 12 | 13 | 14 | def reverse_words(sentence): 15 | words = sentence.split() 16 | return ' '.join(reversed(words)) 17 | 18 | 19 | def main(): 20 | sentence = "I like to write Python." 21 | print reverse_words(sentence) 22 | 23 | 24 | if __name__ == '__main__': 25 | main() 26 | -------------------------------------------------------------------------------- /tally_word_count.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | Tally the length of words in the `word_list.txt` file. 5 | 6 | The Counter datatype became available in Python 2.7 and greater. 7 | 8 | Python 2.5 Counter: http://code.activestate.com/recipes/576611/ 9 | """ 10 | 11 | from collections import Counter 12 | 13 | 14 | def main(): 15 | with open('files/word_list.txt') as f: 16 | # Create a generator of word length. 17 | words = (len(word.strip()) for word in f) 18 | counter = Counter(words) 19 | for count, length in counter.items(): 20 | if len(str(count)) == 2: 21 | print "%d : %d" % (count, length) 22 | else: 23 | print "%d : %d" % (count, length) 24 | 25 | 26 | if __name__ == '__main__': 27 | main() 28 | --------------------------------------------------------------------------------