diff --git a/README.md b/README.md deleted file mode 100644 index dc51b4e..0000000 --- a/README.md +++ /dev/null @@ -1,4 +0,0 @@ -python_and_alg -============== - -This repository contains a comprehensive study of Algorithms and Python, including an "ebook" that I wrote. In the folder /src/examples_in_my_book/, I made available all the examples and cases I used in my ebook. In the folder /futher_examples/ you can find all the solutions for the book Cracking the Code, and many examples from the websites Project Euler and Topcoder. diff --git a/review_algorithms_in_python.pdf b/review_algorithms_in_python.pdf new file mode 100644 index 0000000..49bc67f Binary files /dev/null and b/review_algorithms_in_python.pdf differ diff --git a/src/examples_in_my_book/adt/heap/__init__.py b/src/examples_in_my_book/adt/heap/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/examples_in_my_book/adt/heap/find_N_largest_smallest_items_seq.py b/src/examples_in_my_book/adt/heap/find_N_largest_smallest_items_seq.py new file mode 100644 index 0000000..11bde95 --- /dev/null +++ b/src/examples_in_my_book/adt/heap/find_N_largest_smallest_items_seq.py @@ -0,0 +1,51 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + +import heapq + +def find_N_largest_items_seq(seq, N): + ''' find the N largest items in a sequence ''' + return heapq.nlargest(N,seq) + +def find_N_smallest_items_seq(seq, N): + ''' find the N smallest items in a sequence ''' + return heapq.nsmallest(N, seq) + +def find_smallest_items_seq_heap(seq): + ''' find the smallest items in a sequence using heapify first''' + ''' heap[0] is always the smallest item ''' + ''' pops the smallest item, O(logN) ''' + heapq.heapify(seq) + return heapq.heappop(seq) + +def find_smallest_items_seq(seq): + ''' if it is only one item, min() is faster ''' + return min(seq) + +def find_N_smallest_items_seq_sorted(seq, N): + ''' N ~ len(seq), better sort instead''' + return sorted(seq)[:N] + +def find_N_largest_items_seq_sorted(seq, N): + ''' N ~ len(seq), better sort instead''' + return sorted(seq)[len(seq)-N:] + + +def test_find_N_largest_smallest_items_seq(module_name='this module'): + seq = [1, 3, 2, 8, 6, 10, 9] + N = 3 + assert(find_N_largest_items_seq(seq, N) == [10, 9, 8]) + assert(find_N_largest_items_seq_sorted(seq, N) == [8, 9, 10]) + assert(find_N_smallest_items_seq(seq, N) == [1,2,3]) + assert(find_N_smallest_items_seq_sorted(seq, N) == [1,2,3]) + assert(find_smallest_items_seq(seq) == 1) + assert(find_smallest_items_seq_heap(seq) == 1) + + s = 'Tests in {name} have {con}!' + print(s.format(name=module_name, con='passed')) + + +if __name__ == '__main__': + test_find_N_largest_smallest_items_seq() + diff --git a/src/examples_in_my_book/adt/heap/heap.py~ b/src/examples_in_my_book/adt/heap/heap.py~ new file mode 100644 index 0000000..4e73b53 --- /dev/null +++ b/src/examples_in_my_book/adt/heap/heap.py~ @@ -0,0 +1,49 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + +class Heapify(object): + def __init__(self, data=None): + self.data = data or [] + for i in range(len(data)//2, -1, -1): + self.__max_heapify__(i) + + def __repr__(self): + return '{}'.format(self.data) + + def parent(self, i): + return i >> 1 + + def left_child(self, i): + return (i << 1) + 1 + + def right_child(self, i): + return (i << 1) + 2 # +2 instead of +1 because it's 0-indexed. + + def __max_heapify__(self, i): + largest = i + left = self.left_child(i) + right = self.right_child(i) + n = len(self.data) + largest = (left < n and self.data[left] > self.data[i]) and left or i + largest = (right < n and self.data[right] > self.data[largest]) and right or largest + if i is not largest: + self.data[i], self.data[largest] = self.data[largest], self.data[i] + self.__max_heapify__(largest) + + def extract_max(self): + n = len(self.data) + max_element = self.data[0] + self.data[0] = self.data[n - 1] + self.data = self.data[:n - 1] + self.__max_heapify__(0) + return max_element + + +def test_Heapify(): + l1 = [3, 2, 5, 1, 7, 8, 2] + h = Heapify(l1) + assert(h.extract_max() == 8) + +if __name__ == '__main__': + test_Heapify() diff --git a/src/examples_in_my_book/adt/heap/heapify.py b/src/examples_in_my_book/adt/heap/heapify.py new file mode 100644 index 0000000..8c39c0e --- /dev/null +++ b/src/examples_in_my_book/adt/heap/heapify.py @@ -0,0 +1,50 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + +class Heapify(object): + def __init__(self, data=None): + self.data = data or [] + for i in range(len(data)//2, -1, -1): + self.__max_heapify__(i) + + def __repr__(self): + return '{}'.format(self.data) + + def parent(self, i): + return i >> 1 + + def left_child(self, i): + return (i << 1) + 1 + + def right_child(self, i): + return (i << 1) + 2 # +2 instead of +1 because it's 0-indexed. + + def __max_heapify__(self, i): + largest = i + left = self.left_child(i) + right = self.right_child(i) + n = len(self.data) + largest = (left < n and self.data[left] > self.data[i]) and left or i + largest = (right < n and self.data[right] > self.data[largest]) and right or largest + if i is not largest: + self.data[i], self.data[largest] = self.data[largest], self.data[i] + self.__max_heapify__(largest) + + def extract_max(self): + n = len(self.data) + max_element = self.data[0] + self.data[0] = self.data[n - 1] + self.data = self.data[:n - 1] + self.__max_heapify__(0) + return max_element + + +def test_Heapify(): + l1 = [3, 2, 5, 1, 7, 8, 2] + h = Heapify(l1) + assert(h.extract_max() == 8) + print ("Tests Passed!") + +if __name__ == '__main__': + test_Heapify() diff --git a/src/examples_in_my_book/adt/heap/merge_sorted_seqs.py b/src/examples_in_my_book/adt/heap/merge_sorted_seqs.py new file mode 100644 index 0000000..861ca07 --- /dev/null +++ b/src/examples_in_my_book/adt/heap/merge_sorted_seqs.py @@ -0,0 +1,29 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + +import heapq + + +def merge_sorted_seq(seq1, seq2): + ''' merge two sorted sequences with little ovehead. the result + will be sorted, which is different of doing just +''' + result = [] + for c in heapq.merge(seq1, seq2): + result.append(c) + return result + + +def test_merge_sorted_seq(module_name='this module'): + seq1 = [1, 2, 3, 8, 9, 10] + seq2 = [2, 3, 4, 5, 6, 7, 9] + seq3 = seq1 + seq2 + assert(merge_sorted_seqseq1, seq2) == sorted(seq3)) + + s = 'Tests in {name} have {con}!' + print(s.format(name=module_name, con='passed')) + + +if __name__ == '__main__': + test_merge_sorted_seq() + diff --git a/src/examples_in_my_book/adt/heap/priority_queue.py b/src/examples_in_my_book/adt/heap/priority_queue.py new file mode 100644 index 0000000..605f78d --- /dev/null +++ b/src/examples_in_my_book/adt/heap/priority_queue.py @@ -0,0 +1,41 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + +import heapq + +class PriorityQueue(object): + ''' implements a priority queue class ''' + def __init__(self): + self._queue = [] + self._index = 0 # comparying same priority level + + def push(self, item, priority): + heapq.heappush(self._queue, (-priority, self._index, item)) + self._index += 1 + + def pop(self): + return heapq.heappop(self._queue)[-1] + + +class Item: + def __init__(self, name): + self.name = name + def __repr__(self): + return "Item({!r})".format(self.name) + + +def test_PriorityQueue(): + ''' push and pop are all O(logN) ''' + q = PriorityQueue() + q.push(Item('test1'), 1) + q.push(Item('test2'), 4) + q.push(Item('test3'), 3) + assert(str(q.pop()) == "Item('test2')") + print('Tests passed!'.center(20,'*')) + + +if __name__ == '__main__': + test_PriorityQueue() + + diff --git a/src/examples_in_my_book/adt/heap/priority_queue.py~ b/src/examples_in_my_book/adt/heap/priority_queue.py~ new file mode 100644 index 0000000..f853bf1 --- /dev/null +++ b/src/examples_in_my_book/adt/heap/priority_queue.py~ @@ -0,0 +1,41 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + +import heapq + +class PriorityQueue(object): + ''' implements a priority queue class ''' + def __init__(self): + self._queue = [] + self._index = 0 # index property order items with same priority level, good for comparisons + + def push(self, item, priority): + heapq.heappush(self._queue, (-priority, self._index, item)) # notice the tuple + self._index += 1 + + def pop(self): + return heapq.heappop(self._queue)[-1] + + +class Item: + def __init__(self, name): + self.name = name + def __repr__(self): + return "Item({!r})".format(self.name) + + +def test_PriorityQueue(): + ''' push and pop are all O(logN) ''' + q = PriorityQueue() + q.push(Item('test1'), 1) + q.push(Item('test2'), 4) + q.push(Item('test3'), 3) + assert(str(q.pop()) == "Item('test2')") + print('Tests passed!'.center(20,'*')) + + +if __name__ == '__main__': + test_PriorityQueue() + + diff --git a/src/examples_in_my_book/adt/linked_lists/Node.py~ b/src/examples_in_my_book/adt/linked_lists/Node.py~ new file mode 100644 index 0000000..f40a59e --- /dev/null +++ b/src/examples_in_my_book/adt/linked_lists/Node.py~ @@ -0,0 +1,44 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + +'''The structure of an unordered list is a collection of items where each item holds a relative position with respect to the others ''' + + + +class Node: + ''' The basic building block for the linked list implementation is the node. + Each node object must hold at least two pieces of information: + First, the node must contain the list item itself (data field), + second each node must hold a reference to the next node ''' + + def __init__(self,initdata): + self.data = initdata + self.next = None + + def getData(self): + return self.data + + def getNext(self): + return self.next + + def setData(self,newdata): + self.data = newdata + + def setNext(self,newnext): + self.next = newnext + + + +def test_Node(module_name='this module'): + temp = Node(40) + assert(temp.getData() == 40) + + s = 'Tests in {name} have {con}!' + print(s.format(name=module_name, con='passed')) + + +if __name__ == '__main__': + test_Node() + + diff --git a/src/examples_in_my_book/adt/linked_lists/__init__.py b/src/examples_in_my_book/adt/linked_lists/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/examples_in_my_book/adt/linked_lists/linked_list_from_stack.py b/src/examples_in_my_book/adt/linked_lists/linked_list_from_stack.py new file mode 100644 index 0000000..52efaf6 --- /dev/null +++ b/src/examples_in_my_book/adt/linked_lists/linked_list_from_stack.py @@ -0,0 +1,71 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + + + +class Node(object): + def __init__(self,data=None,next=None): + self.data = data + self.next = next + + def setnext(self,next): + self.next = next + + def __str__(self): + return "%s" % self.data + + +class LinkedListStack(object): + ''' linked list from stack ''' + def __init__(self, max=0): + self.max = max + self.head = None + self.z = None + self.size = 0 + + def push(self, data): + if self.size == 0: + self.head = Node(data=data) + self.size += 1 + else: + head = self.head + temp = Node(data = data) + self.head = temp + self.head = temp + temp.setnext(head) + + def pop(self): + temp = self.head.next + self.head = temp + + def isEmpty(self): + return self.size == 0 + + def __str__(self): + d = "" + if self.isEmpty(): return "" + else: + temp = self.head + d += "%s\n" % temp + while temp.next != None: + temp = temp.next + d += "%s\n" % temp + return d + + + + +def test_ll_from_stack(): + ll = LinkedListStack(max = 20) + ll.push("1") + ll.push("2") + ll.push("3") + ll.push("4") + print(ll) + ll.pop() + print(ll) + + +if __name__ == '__main__': + test_ll_from_stack() diff --git a/src/examples_in_my_book/adt/linked_lists/linkedlist.py b/src/examples_in_my_book/adt/linked_lists/linkedlist.py new file mode 100644 index 0000000..5a8aa6d --- /dev/null +++ b/src/examples_in_my_book/adt/linked_lists/linkedlist.py @@ -0,0 +1,65 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + +from node import Node + +class UnorderedList(object): + def __init__(self): + self.head = None + + def add(self, item): + temp = Node(item) + temp.setNext(self.head) + self.head = temp + + def length(self): + current = self.head + count = 0 + while current != None: + count = count + 1 + current = current.getNext() + return count + + def search(self, item): + current = self.head + found = False + while current != None and not found: + if current.getData() == item: + found = True + else: + current = current.getNext() + return found + + def remove(self, item): + current = self.head + previous = None + found = False + while not found: + if current.getData() == item: + found = True + else: + previous = current + current = current.getNext() + if previous == None: + self.head = current.getNext() + else: + previous.setNext(current.getNext()) + + +def test_UnorderedList(module_name='this module'): + llist = UnorderedList() + llist.add(31) + llist.add(22) + llist.add(10) + assert(llist.search(22) == True) + llist.remove(22) + assert(llist.search(22) == False) + s = 'Tests in {name} have {con}!' + print(s.format(name=module_name, con='passed')) + + +if __name__ == '__main__': + test_UnorderedList() + + diff --git a/src/examples_in_my_book/adt/linked_lists/linkedlist.py~ b/src/examples_in_my_book/adt/linked_lists/linkedlist.py~ new file mode 100644 index 0000000..4ebdb8e --- /dev/null +++ b/src/examples_in_my_book/adt/linked_lists/linkedlist.py~ @@ -0,0 +1,65 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + +from node import Node + +class UnorderedList(object): + def __init__(self): + self.head = None + + def add(self, item): + temp = Node(item) + temp.setNext(self.head) + self.head = temp + + def length(self): + current = self.head + count = 0 + while current != None: + count = count + 1 + current = current.getNext() + return count + + def search(self,item): + current = self.head + found = False + while current != None and not found: + if current.getData() == item: + found = True + else: + current = current.getNext() + return found + + def remove(self,item): + current = self.head + previous = None + found = False + while not found: + if current.getData() == item: + found = True + else: + previous = current + current = current.getNext() + if previous == None: + self.head = current.getNext() + else: + previous.setNext(current.getNext()) + + +def test_UnorderedList(module_name='this module'): + llist = UnorderedList() + llist.add(31) + llist.add(22) + llist.add(10) + assert(llist.search(22) == True) + llist.remove(22) + assert(llist.search(22) == False) + s = 'Tests in {name} have {con}!' + print(s.format(name=module_name, con='passed')) + + +if __name__ == '__main__': + test_UnorderedList() + + diff --git a/src/examples_in_my_book/adt/linked_lists/node.py b/src/examples_in_my_book/adt/linked_lists/node.py new file mode 100644 index 0000000..5b6caf9 --- /dev/null +++ b/src/examples_in_my_book/adt/linked_lists/node.py @@ -0,0 +1,23 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + + +class Node(object): + def __init__(self, value): + self.value = value + self.next = None + + def getData(self): + return self.value + + def getNext(self): + return self.next + + def setData(self, newdata): + self.value = newdata + + def setNext(self, newnext): + self.next = newnext + + diff --git a/src/examples_in_my_book/adt/linked_lists/node.py~ b/src/examples_in_my_book/adt/linked_lists/node.py~ new file mode 100644 index 0000000..ca70588 --- /dev/null +++ b/src/examples_in_my_book/adt/linked_lists/node.py~ @@ -0,0 +1,39 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + +'''The structure of an unordered list is a collection of items where each item holds a relative position with respect to the others ''' + + + +class Node: + def __init__(self,initdata): + self.data = initdata + self.next = None + + def getData(self): + return self.data + + def getNext(self): + return self.next + + def setData(self,newdata): + self.data = newdata + + def setNext(self,newnext): + self.next = newnext + + + +def test_Node(module_name='this module'): + temp = Node(40) + assert(temp.getData() == 40) + + s = 'Tests in {name} have {con}!' + print(s.format(name=module_name, con='passed')) + + +if __name__ == '__main__': + test_Node() + + diff --git a/src/examples_in_my_book/adt/linked_lists/ordered_list.py b/src/examples_in_my_book/adt/linked_lists/ordered_list.py new file mode 100644 index 0000000..50ab9ca --- /dev/null +++ b/src/examples_in_my_book/adt/linked_lists/ordered_list.py @@ -0,0 +1,97 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + + + +from Node import Node + +class OrderedList: + """ The structure of an ordered list is a collection of items where each item + holds a relative position that is based upon some underlying characteristic of + the item. The ordering is typically either ascending or descending and we assume + that list items have a meaningful comparison operation that is already defined. + Many of the ordered list operations are the same as those of the unordered list. + """ + def __init__(self): + self.head = None + + + def add(self,item): + ''' this method is different from linked list ''' + current = self.head + previous = None + stop = False + while current != None and not stop: + if current.getData() > item: + stop = True + else: + previous = current + current = current.getNext() + temp = Node(item) + if previous == None: + temp.setNext(self.head) + self.head = temp + else: + temp.setNext(current) + previous.setNext(temp) + + + def length(self): + current = self.head + count = 0 + while current != None: + count = count + 1 + current = current.getNext() + return count + + + def search(self,item): + ''' this method is different from linked list ''' + current = self.head + found = False + stop = False + while current != None and not found and not stop: + if current.getData() == item: + found = True + else: + if current.getData() > item: + stop = True + else: + current = current.getNext() + return found + + + def remove(self,item): + current = self.head + previous = None + found = False + while not found: + if current.getData() == item: + found = True + else: + previous = current + current = current.getNext() + if previous == None: + self.head = current.getNext() + else: + previous.setNext(current.getNext()) + + + +def test_OrderedList(module_name='this module'): + olist = OrderedList() + olist.add(31) + olist.add(22) + olist.add(10) + assert(olist.search(22) == True) + olist.remove(22) + assert(olist.search(22) == False) + s = 'Tests in {name} have {con}!' + print(s.format(name=module_name, con='passed')) + + +if __name__ == '__main__': + test_OrderedList() + + diff --git a/src/examples_in_my_book/adt/queues/__init__.py b/src/examples_in_my_book/adt/queues/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/examples_in_my_book/adt/queues/deque.py b/src/examples_in_my_book/adt/queues/deque.py new file mode 100644 index 0000000..86573bd --- /dev/null +++ b/src/examples_in_my_book/adt/queues/deque.py @@ -0,0 +1,46 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + + + +class Deque(object): + ''' a class for a double ended queue ''' + def __init__(self): + self.items = [] + + def is_empty(self): + return self.items == [] + + def add_front(self, item): + self.items.append(item) + + def add_rear(self, item): + self.items.insert(0, item) + + def remove_front(self): + return self.items.pop() + + def remove_rear(self): + return self.items.pop(0) + + def size(self): + return len(self.items) + + def __repr__(self): + return '{}'.format(self.items) + + +def main(): + dq = Deque() + dq.add_front(1) + dq.add_front(2) + dq.add_front(3) + dq.add_rear(40) + dq.add_rear(50) + print(dq.size()) + print(dq) + + +if __name__ == '__main__': + main() diff --git a/src/examples_in_my_book/adt/queues/deque.py~ b/src/examples_in_my_book/adt/queues/deque.py~ new file mode 100644 index 0000000..8e362c4 --- /dev/null +++ b/src/examples_in_my_book/adt/queues/deque.py~ @@ -0,0 +1,46 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + + + +class Deque(object): + ''' a class for a double ended queue ''' + def __init__(self): + self.items = [] + + def is_empty(self): + return self.items == [] + + def add_front(self, item): + self.items.append(item) + + def add_rear(self, item): + self.items.insert(0, item) + + def remove_front(self): + return self.items.pop() + + def remove_rear(self): + return self.items.pop(0) + + def size(self): + return len(self.items) + + def __repr__(self): + return '{}'.format(self.items) + + +def main(): + dq = Deque() + dq.add_front(1) + dq.add_front(2) + dq.add_front(3) + dq.add_rear(40) + dq.add_rear(50) + assert(dq.size() == 5) + assert(dq == [50, 40, 1, 2, 3]) + + +if __name__ == '__main__': + main() diff --git a/src/examples_in_my_book/adt/queues/linked_queue.py b/src/examples_in_my_book/adt/queues/linked_queue.py new file mode 100644 index 0000000..4aadc0a --- /dev/null +++ b/src/examples_in_my_book/adt/queues/linked_queue.py @@ -0,0 +1,61 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + +class Node(object): + def __init__(self, value): + self.value = value + self.next = None + + +class LinkedQueue(object): + ''' Queue acts as a container for nodes (objects) that are inserted and removed according FIFO''' + def __init__(self): + self.front = None + self.back = None + + def isEmpty(self): + return bool(self.front) + + def dequeue(self): + if self.front: + value = self.front.value + self.front = self.front.next + return value + raise Exception('Queue is empty, cannot dequeue.') + + def enqueue(self, value): + node = Node(value) + if self.front: + self.back.next = node + self.back = node + else: + self.front = node + self.back = node + return True + + def size(self): + node = self.front + num_nodes = 1 + while node.next: + num_nodes += 1 + node = node.next + return num_nodes + + def peek(self): + return self.front.value + + +def main(): + queue = LinkedQueue() + queue.enqueue(1) + queue.enqueue(2) + queue.enqueue(3) + print(queue.size()) + print(queue.peek()) + print(queue.dequeue()) + print(queue.peek()) + + +if __name__ == '__main__': + main() diff --git a/src/examples_in_my_book/adt/queues/linked_queue.py~ b/src/examples_in_my_book/adt/queues/linked_queue.py~ new file mode 100644 index 0000000..89741bd --- /dev/null +++ b/src/examples_in_my_book/adt/queues/linked_queue.py~ @@ -0,0 +1,61 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + +class Node(object): + def __init__(self, value): + self.value = value + self.next = None + + +class LinkedQueue(object): + ''' Queue acts as a container for nodes (objects) that are inserted and removed according FIFO''' + def __init__(self): + self.front = None + self.back = None + + def isEmpty(self): + return bool(self.front) + + def dequeue(self): + if self.front: + value = self.front.value + self.front = self.front.next + return value + raise Exception('Queue is empty, cannot dequeue.') + + def enqueue(self, value): + node = Node(value) + if self.front: + self.back.next = node + self.back = node + else: + self.front = node + self.back = node + return True + + def size(self): + node = self.front + num_nodes = 1 + while node.next: + num_nodes += 1 + node = node.next + return num_nodes + + def peek(self): + return self.front.value[-1] + + +def main(): + queue = LinkedQueue() + queue.enqueue(1) + queue.enqueue(2) + queue.enqueue(3) + print(queue.size()) + print(queue.peek()) + print(queue.dequeue()) + print(queue.peek()) + + +if __name__ == '__main__': + main() diff --git a/src/examples_in_my_book/adt/queues/palindrome_checker_with_deque.py b/src/examples_in_my_book/adt/queues/palindrome_checker_with_deque.py new file mode 100644 index 0000000..9591099 --- /dev/null +++ b/src/examples_in_my_book/adt/queues/palindrome_checker_with_deque.py @@ -0,0 +1,34 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + +import sys +import string +import collections + +def palindrome_checker_with_deque(str1): + d = collections.deque() + eq = True + strip = string.whitespace + string.punctuation + "\"'" + for s in str1.lower(): + if s not in strip: d.append(s) + while len(d) > 1 and eq: + first = d.pop() + last = d.popleft() + if first != last: + eq = False + return eq + + +def test_palindrome_checker_with_deque(): + str1 = 'Madam Im Adam' + str2 = 'Buffy is a Slayer' + assert(palindrome_checker_with_deque(str1) == True) + assert(palindrome_checker_with_deque(str2) == False) + print('Tests passed!') + + +if __name__ == '__main__': + test_palindrome_checker_with_deque() + + diff --git a/src/examples_in_my_book/adt/queues/queue.py b/src/examples_in_my_book/adt/queues/queue.py new file mode 100644 index 0000000..92c9fa9 --- /dev/null +++ b/src/examples_in_my_book/adt/queues/queue.py @@ -0,0 +1,39 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + + +class Queue(object): + ''' a class for a queue ''' + def __init__(self): + self.items = [] + + def isEmpty(self): + return self.items == [] + + def enqueue(self, item): + self.items.insert(0, item) + + def dequeue(self): + return self.items.pop() + + def size(self): + return len(self.items) + + def peek(self): + return self.items[-1] + + +def main(): + queue = Queue() + queue.enqueue(1) + queue.enqueue(2) + queue.enqueue(3) + print(queue.size()) + print(queue.peek()) + print(queue.dequeue()) + print(queue.peek()) + + +if __name__ == '__main__': + main() diff --git a/src/examples_in_my_book/adt/queues/queue.py~ b/src/examples_in_my_book/adt/queues/queue.py~ new file mode 100644 index 0000000..1822013 --- /dev/null +++ b/src/examples_in_my_book/adt/queues/queue.py~ @@ -0,0 +1,39 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + + +class Queue(object): + ''' a class for a queue ''' + def __init__(self): + self.items = [] + + def isEmpty(self): + return self.items == [] + + def enqueue(self, item): + self.items.insert(0, item) + + def dequeue(self): + return self.items.pop() + + def size(self): + return len(self.items) + + def size(self): + return self.items[-1] + + +def main(): + queue = Queue() + queue.enqueue(1) + queue.enqueue(2) + queue.enqueue(3) + print(queue.size()) + print(queue.peek()) + print(queue.dequeue()) + print(queue.peek()) + + +if __name__ == '__main__': + main() diff --git a/src/examples_in_my_book/adt/queues/queue_from_two_stacks.py b/src/examples_in_my_book/adt/queues/queue_from_two_stacks.py new file mode 100644 index 0000000..6af795d --- /dev/null +++ b/src/examples_in_my_book/adt/queues/queue_from_two_stacks.py @@ -0,0 +1,48 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + + +class Queue(object): + ''' an example of a queue implemented from 2 stacks ''' + def __init__(self): + self.in_stack = [] + self.out_stack = [] + + def enqueue(self, item): + return self.in_stack.append(item) + + def dequeue(self): + if self.out_stack: + return self.out_stack.pop() + while self.in_stack: + self.out_stack.append(self.in_stack.pop()) + if not self.out_stack: + return "Queue empty!" + return self.out_stack.pop() + + def size(self): + return len(self.in_stack) + len(self.out_stack) + + def peek(self): + if self.out_stack: + return self.out_stack[-1] + while self.in_stack: + self.out_stack.append(self.in_stack.pop()) + return self.out_stack[-1] + + + +def main(): + queue = Queue() + queue.enqueue(1) + queue.enqueue(2) + queue.enqueue(3) + print(queue.size()) + print(queue.peek()) + print(queue.dequeue()) + print(queue.peek()) + + +if __name__ == '__main__': + main() diff --git a/src/examples_in_my_book/adt/queues/queue_from_two_stacks.py~ b/src/examples_in_my_book/adt/queues/queue_from_two_stacks.py~ new file mode 100644 index 0000000..9b2ef5a --- /dev/null +++ b/src/examples_in_my_book/adt/queues/queue_from_two_stacks.py~ @@ -0,0 +1,48 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + + +class Queue(object): + ''' an example of a queue implemented from 2 stacks ''' + def __init__(self): + self.in_stack = [] + self.out_stack = [] + + def enqueue(self, item): + return self.in_stack.append(item) + + def dequeue(self): + if self.out_stack: + return self.out_stack.pop() + while self.in_stack: + self.out_stack.append(self.in_stack.pop()) + if not self.out_stack: + return "Queue empty!" + return self.out_stack.pop() + + def size(self): + return len(self.in_stack) + len(self.out_stack) + + def peek(self): + if self.out_stack: + return self.out_stack[-1] + while self.in_stack: + self.out_stack.append(self.in_stack.pop()) + return self.out_stack[-1] + + + +def main(): + queue = Queue() + queue.add(1) + queue.add(2) + queue.add(3) + print(queue.size()) + print(queue.peek()) + print(queue.remove()) + print(queue.peek()) + + +if __name__ == '__main__': + main() diff --git a/src/examples_in_my_book/adt/queues/queue_with_nodes.py~ b/src/examples_in_my_book/adt/queues/queue_with_nodes.py~ new file mode 100644 index 0000000..021e64d --- /dev/null +++ b/src/examples_in_my_book/adt/queues/queue_with_nodes.py~ @@ -0,0 +1,47 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + + + +class Node: + def __init__(self, value): + self.value = value + self.next = None + + +class Queue: + ''' Queue acts as a container for nodes (objects) that are inserted and removed according FIFO''' + def __init__(self): + self.first = None + self.last = None + + def dequeue(self): + if self.front: + value = self.first.value + self.first = self.first.next + return value + raise Exception('Queue is empty, cannot dequeue.') + + def enqueue(self, value): + node = Node(value) + if self.first: + self.last.next = node + self.last = node + else: + self.first = node + self.last = node + return True + + def isEmpty(self): + return bool(self.first) + + def size(self): + node = self.first + num_nodes = 0 + while node.next: + num_nodes += 1 + node = node.next + return num_nodes + + diff --git a/src/examples_in_my_book/adt/queues/rotating_array.py b/src/examples_in_my_book/adt/queues/rotating_array.py new file mode 100644 index 0000000..60b3834 --- /dev/null +++ b/src/examples_in_my_book/adt/queues/rotating_array.py @@ -0,0 +1,27 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + + +def rotating_array(seq, N): + ''' rotate an array from right to left for a given number''' + myqueue = [] + for i in range(N): + myqueue.append(seq.pop()) + myqueue.reverse() + return myqueue + seq + + + +def test_rotating_array(module_name='this module'): + seq = [1, 2, 3, 4, 5, 6, 7] + N = 4 + assert(rotating_array(seq, N) == [4, 5, 6, 7, 1, 2, 3]) + + s = 'Tests in {name} have {con}!' + print(s.format(name=module_name, con='passed')) + + +if __name__ == '__main__': + test_rotating_array() + diff --git a/src/examples_in_my_book/adt/stacks/__init__.py b/src/examples_in_my_book/adt/stacks/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/examples_in_my_book/adt/stacks/banlance_parenthesis_str_stack.py b/src/examples_in_my_book/adt/stacks/banlance_parenthesis_str_stack.py new file mode 100644 index 0000000..c285821 --- /dev/null +++ b/src/examples_in_my_book/adt/stacks/banlance_parenthesis_str_stack.py @@ -0,0 +1,40 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + +from stack import Stack + +def balance_par_str_with_stack(symbolString): + ''' use a stack to balance the parenteses of a string ''' + s = Stack() + balanced = True + index = 0 + while index < len(symbolString) and balanced: + symbol = symbolString[index] + if symbol == "(": + s.push(symbol) + else: + if s.isEmpty(): + balanced = False + else: + s.pop() + index = index + 1 + + if balanced and s.isEmpty(): + return True + else: + return False + + + + +def test_balance_par_str_with_stack(module_name='this module'): + print(balance_par_str_with_stack('((()))')) + print(balance_par_str_with_stack('(()')) + + s = 'Tests in {name} have {con}!' + print(s.format(name=module_name, con='passed')) + + +if __name__ == '__main__': + test_balance_par_str_with_stack() diff --git a/src/examples_in_my_book/adt/stacks/dec2bin_with_stack.py b/src/examples_in_my_book/adt/stacks/dec2bin_with_stack.py new file mode 100644 index 0000000..594ed93 --- /dev/null +++ b/src/examples_in_my_book/adt/stacks/dec2bin_with_stack.py @@ -0,0 +1,28 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + +from stack import Stack + +def dec2bin_with_stack(decnum): + '''transform a decimal number to a binary number with a stack ''' + s = Stack() + str_aux = '' + while decnum > 0: + dig = decnum % 2 + decnum = decnum//2 + s.push(dig) + while not s.isEmpty(): + str_aux += str(s.pop()) + return str_aux + + +def test_dec2bin_with_stack(module_name='this module'): + decnum = 9 + assert(dec2bin_with_stack(decnum) == '1001') + s = 'Tests in {name} have {con}!' + print(s.format(name=module_name, con='passed')) + + +if __name__ == '__main__': + test_dec2bin_with_stack() diff --git a/src/examples_in_my_book/adt/stacks/linked_stack.py b/src/examples_in_my_book/adt/stacks/linked_stack.py new file mode 100644 index 0000000..7f9b154 --- /dev/null +++ b/src/examples_in_my_book/adt/stacks/linked_stack.py @@ -0,0 +1,52 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + +class Node: + def __init__(self, value=None): + self.value = value + self.next = None + +class StackwithNodes: + ''' Define a Stack with nodes''' + def __init__(self): + self.top = None + + def isEmpty(self): + return bool(self.top) + + def pop(self): + node = self.top + self.top = node.next + return node.value + + def push(self, value): + node = Node(value) + node.next = self.top + self.top = node + + def size(self): + node = self.top + if node not None: num_nodes = 1 + else: return 0 + while node.next: + num_nodes += 1 + node = node.next + return num_nodes + + def peek(self): + return self.top.value + + +def main(): + stack = StackwithNodes() + stack.push(1) + stack.push(2) + stack.push(3) + print(stack.size()) + print(stack.peek()) + print(stack.pop()) + print(stack.peek()) + +if __name__ == '__main__': + main() diff --git a/src/examples_in_my_book/adt/stacks/linked_stack.py~ b/src/examples_in_my_book/adt/stacks/linked_stack.py~ new file mode 100644 index 0000000..d2d6abc --- /dev/null +++ b/src/examples_in_my_book/adt/stacks/linked_stack.py~ @@ -0,0 +1,51 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + +class Node: + def __init__(self, value=None): + self.value = value + self.next = None + +class StackwithNodes: + ''' Define a Stack with nodes''' + def __init__(self): + self.top = None + + def isEmpty(self): + return bool(self.top) + + def pop(self): + node = self.top + self.top = node.next + return node.value + + def push(self, value): + node = Node(value) + node.next = self.top + self.top = node + + def size(self): + node = self.top + num_nodes = 1 + while node.next: + num_nodes += 1 + node = node.next + return num_nodes + + def peek(self): + return self.top.value + + +def main(): + stack = StackwithNodes() + stack.push(1) + stack.push(2) + stack.push(3) + print(stack.size()) + print(stack.peek()) + print(stack.pop()) + print(stack.peek()) + +if __name__ == '__main__': + main() diff --git a/src/examples_in_my_book/adt/stacks/reverse_string_with_stack.py b/src/examples_in_my_book/adt/stacks/reverse_string_with_stack.py new file mode 100644 index 0000000..3f6ec43 --- /dev/null +++ b/src/examples_in_my_book/adt/stacks/reverse_string_with_stack.py @@ -0,0 +1,30 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + +import sys +import stack + +def reverse_string_with_stack(str1): + ''' Uses a stack to reverse a string ''' + s = stack.Stack() + revStr = '' + for c in str1: + s.push(c) + while not s.isEmpty(): + revStr += s.pop() + return revStr + + +def test_reverse_string_with_stack(): + str1 = 'Buffy is a Slayer!' + assert(reverse_string_with_stack(str1) == '!reyalS a si yffuB') + print('Tests passed!') + + +if __name__ == '__main__': + test_reverse_string_with_stack() + + + + diff --git a/src/examples_in_my_book/adt/stacks/reverse_string_with_stack.py~ b/src/examples_in_my_book/adt/stacks/reverse_string_with_stack.py~ new file mode 100644 index 0000000..00753b7 --- /dev/null +++ b/src/examples_in_my_book/adt/stacks/reverse_string_with_stack.py~ @@ -0,0 +1,30 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + +import sys +import stack + +def reverse_string_with_stack(str1): + ''' Uses a stack to reverse a string ''' + s = stack.Stack() + revStr = '' + for c in str1: + s.push(c) + while not s.isEmpty(): + revStr += s.pop() + return revStr + + +def test_reverse_string_with_stack(): + str1 = 'Buffy is a Slayer!' + assert(reverse_string_with_stack(str1) == '!reyalS a si yffuB') + print('Tests passed!') + + +if __name__ == '__main__': + test_reverse_string_with_stack() + + + + diff --git a/src/examples_in_my_book/adt/stacks/set_of_stacks.py b/src/examples_in_my_book/adt/stacks/set_of_stacks.py new file mode 100644 index 0000000..c58e8e7 --- /dev/null +++ b/src/examples_in_my_book/adt/stacks/set_of_stacks.py @@ -0,0 +1,47 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + +class SetOfStacks(list): + def __init__(self, capacity=4): + self.stacks = [] + self.last_stack = [] + self.capacity = capacity + self.stacks.append(self.last_stack) + + def __repr__(self): + return str(self.stacks) + + def push(self, value): + last_stack = self.last_stack + if len(last_stack) is self.capacity: + last_stack = [] + self.last_stack = last_stack + self.stacks.append(last_stack) + last_stack.append(value) + + def pop(self): + last_stack = self.last_stack + value = last_stack.pop() + if len(last_stack) is 0: + self.stacks.pop() + self.last_stack = self.stacks[-1] + return value + + +def main(): + stack = SetOfStacks() + stack.push(1) + stack.push(2) + stack.push(3) + stack.push(4) + stack.push(5) + stack.push(6) + print(stack) + stack.pop() + stack.pop() + stack.pop() + print(stack) + +if __name__ == '__main__': + main() diff --git a/src/examples_in_my_book/adt/stacks/set_of_stacks.py~ b/src/examples_in_my_book/adt/stacks/set_of_stacks.py~ new file mode 100644 index 0000000..e69b57c --- /dev/null +++ b/src/examples_in_my_book/adt/stacks/set_of_stacks.py~ @@ -0,0 +1,48 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + +class SetOfStacks(list): + + def __init__(self, capacity=4): + self.stacks = [] + self.last_stack = [] + self.capacity = capacity + self.stacks.append(self.last_stack) + + def __repr__(self): + return str(self.stacks) + + def push(self, value): + last_stack = self.last_stack + if len(last_stack) is self.capacity: + last_stack = [] + self.last_stack = last_stack + self.stacks.append(last_stack) + last_stack.append(value) + + def pop(self): + last_stack = self.last_stack + value = last_stack.pop() + if len(last_stack) is 0: + self.stacks.pop() + self.last_stack = self.stacks[-1] + return value + + +def main(): + stack = SetOfStacks() + stack.push(1) + stack.push(2) + stack.push(3) + stack.push(4) + stack.push(5) + stack.push(6) + print(stack) + stack.pop() + stack.pop() + stack.pop() + print(stack) + +if __name__ == '__main__': + main() diff --git a/src/examples_in_my_book/adt/stacks/stack.py b/src/examples_in_my_book/adt/stacks/stack.py new file mode 100644 index 0000000..0089f63 --- /dev/null +++ b/src/examples_in_my_book/adt/stacks/stack.py @@ -0,0 +1,40 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + +class Stack(object): + ''' define the stack class ''' + def __init__(self): + self.items = [] + + def isEmpty(self): + return self.items == [] + + def push(self, items): + self.items.append(items) + + def pop(self): + return self.items.pop() + + def peek(self): + return self.items[-1] + + def size(self): + return len(self.items) + + + + +def main(): + stack = Stack() + stack.push(1) + stack.push(2) + stack.push(3) + print(stack.size()) + print(stack.peek()) + print(stack.pop()) + print(stack.peek()) + + +if __name__ == '__main__': + main() diff --git a/src/examples_in_my_book/adt/stacks/stack.py~ b/src/examples_in_my_book/adt/stacks/stack.py~ new file mode 100644 index 0000000..0caf924 --- /dev/null +++ b/src/examples_in_my_book/adt/stacks/stack.py~ @@ -0,0 +1,24 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + +class Stack(object): + ''' define the stack class ''' + def __init__(self): + self.items = [] + + def isEmpty(self): + return self.items == [] + + def push(self, items): + self.items.append(items) + + def pop(self): + return self.items.pop() + + def peek(self): + return self.items[-1] + + def size(self): + return len(self.items) + diff --git a/src/examples_in_my_book/adt/stacks/stack_with_min.py b/src/examples_in_my_book/adt/stacks/stack_with_min.py new file mode 100644 index 0000000..405e9f7 --- /dev/null +++ b/src/examples_in_my_book/adt/stacks/stack_with_min.py @@ -0,0 +1,55 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + +class Stack(list): + def push(self, value): + if len(self) > 0: + last = self[-1] + minimum = self._find_minimum(value, last) + else: + minimum = value + self.minimum = minimum + self.append(NodeWithMin(value, minimum)) + + def _find_minimum(self, value, last_value): + if value < last_value.minimum: + return value + return last_value.minimum + + def min(self): + return self.minimum + + +class NodeWithMin(object): + def __init__(self, value, minimum): + self.value = value + self.minimum = minimum + + def __repr__(self): + return str(self.value) + + def min(self): + return self.minimum + + + +def main(): + stack = Stack() + stack.push(1) + stack.push(2) + stack.push(3) + node = stack.pop() + print(node.minimum) + stack.push(0) + stack.push(4) + node = stack.pop() + print(node.min()) + print(stack.min()) + print(stack) + + +if __name__ == '__main__': + main() + + diff --git a/src/examples_in_my_book/adt/stacks/stack_with_min.py~ b/src/examples_in_my_book/adt/stacks/stack_with_min.py~ new file mode 100644 index 0000000..ac03ba2 --- /dev/null +++ b/src/examples_in_my_book/adt/stacks/stack_with_min.py~ @@ -0,0 +1,54 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + +from linked_stack import StackwithNodes +from node import Node + + +class StackWithMins(Stack): + mins = StackwithNodes() + + def push(self, item): + node = Node(item) + node.next = self.top + self.top = node + if self.mins.top is not None: + if self.mins.top.data > item: + self.mins.push(item) + else: + self.mins.push(item) + + def pop(self): + if self.top is not None: + if self.peek() == self.mins.peek(): + self.mins.pop() + node = self.top + self.top = self.top.next + return node + return None + + def min(self): + return self.mins.peek() + + + +def test_(): + stack = StackWithMins() + stack.push(9) + stack.push(5) + stack.push(7) + stack.push(4) + stack.push(3) + stack.push(6) + stack.push(5) + stack.push(2) + stack.push(1) + stack.print_stack() + stack.mins.print_stack() + + +if __name__ == '__main__': + test_() + + diff --git a/src/examples_in_my_book/dynamic_programming/__init__.py b/src/examples_in_my_book/dynamic_programming/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/examples_in_my_book/dynamic_programming/do_benchmark.py~ b/src/examples_in_my_book/dynamic_programming/do_benchmark.py~ new file mode 100644 index 0000000..0ee6b19 --- /dev/null +++ b/src/examples_in_my_book/dynamic_programming/do_benchmark.py~ @@ -0,0 +1,16 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + +import random + +def benchmark(func): + import time + def wrapper(*args, **kwargs): + t = time.clock() + res = func(*args, **kwargs) + print("\t%s" % func.__name__, time.clock()-t) + return res + return wrapper + + diff --git a/src/examples_in_my_book/dynamic_programming/memo.py b/src/examples_in_my_book/dynamic_programming/memo.py new file mode 100644 index 0000000..7391a6c --- /dev/null +++ b/src/examples_in_my_book/dynamic_programming/memo.py @@ -0,0 +1,42 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + + +from functools import wraps +from do_benchmark import benchmark + +def memo(func): + ''' an example of dynamic programming using a memoizing decorator ''' + cache = {} + @wraps(func) + def wrap(*args): + if args not in cache: + cache[args] = func(*args) + return cache[args] + return wrap + +@memo +def find_fibonacci_seq_rec(n): + ''' implements the nth fibonacci value in a recursive exponential runtime ''' + if n < 2: return n + return find_fibonacci_seq_rec(n - 1) + find_fibonacci_seq_rec(n - 2) + +def test_memo(): + n = 50 + # find_fibonacci_seq_rec = memo(find_fibonacci_seq_rec) + # @benchmark + print(find_fibonacci_seq_rec(n)) + + +if __name__ == '__main__': + test_memo() + + + + + + + + + diff --git a/src/examples_in_my_book/dynamic_programming/memoized_longest_inc_subseq.py b/src/examples_in_my_book/dynamic_programming/memoized_longest_inc_subseq.py new file mode 100644 index 0000000..7547caa --- /dev/null +++ b/src/examples_in_my_book/dynamic_programming/memoized_longest_inc_subseq.py @@ -0,0 +1,86 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + + +from itertools import combinations +from bisect import bisect +from memo import memo +from do_benchmark import benchmark + +def naive_longest_inc_subseq(seq): + ''' naive (exponential) solution to the longest increasing subsequence problem ''' + for length in range(len(seq), 0, -1): + for sub in combinations(seq, length): + if list(sub) == sorted(sub): + return len(sub) + + +def longest_inc_subseq1(seq): + ''' an iterative algorithm for the longest increasing subsequence problem ''' + end = [] + for val in seq: + idx = bisect(end, val) + if idx == len(end): end.append(val) + else: end[idx] = val + return len(end) + + +def longest_inc_subseq2(seq): + ''' another iterative algorithm for the longest increasing subsequence problem ''' + L = [1] * len(seq) + for cur, val in enumerate(seq): + for pre in range(cur): + if seq[pre] <= val: + L[cur] = max(L[cur], 1 + L[pre]) + return max(L) + + +def memoized_longest_inc_subseq(seq): + ''' a memoized recursive solution to find the longest increasing subsequence problem ''' + @memo + def L(cur): + res = 1 + for pre in range(cur): + if seq[pre] <= seq[cur]: + res = max(res, 1 + L(pre)) + return res + return max(L(i) for i in range(len(seq))) + + +@benchmark +def test_naive_longest_inc_subseq(): + print(naive_longest_inc_subseq(s1)) + +benchmark +def test_longest_inc_subseq1(): + print(longest_inc_subseq1(s1)) + +@benchmark +def test_longest_inc_subseq2(): + print(longest_inc_subseq2(s1)) + +@benchmark +def test_memoized_longest_inc_subseq(): + print(memoized_longest_inc_subseq(s1)) + + +if __name__ == '__main__': + from random import randrange + s1 = [randrange(100) for i in range(25)] + print(s1) + test_naive_longest_inc_subseq() + test_longest_inc_subseq1() + test_longest_inc_subseq2() + test_memoized_longest_inc_subseq() + + + + + + + + + + + diff --git a/src/examples_in_my_book/general_problems/dicts/Counter_example.py b/src/examples_in_my_book/general_problems/dicts/Counter_example.py new file mode 100644 index 0000000..b0f3284 --- /dev/null +++ b/src/examples_in_my_book/general_problems/dicts/Counter_example.py @@ -0,0 +1,33 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + +from collections import Counter + +def Counter_example(): + ''' show some examples for Counter ''' + ''' it is a dictionary that maps the items to the number of occurences ''' + seq1 = [1, 2, 3, 5, 1, 2, 5, 5, 2, 5, 1, 4] + seq_counts = Counter(seq1) + print(seq_counts) + + ''' we can increment manually or use the update() method ''' + seq2 = [1, 2, 3] + seq_counts.update(seq2) + print(seq_counts) + + seq3 = [1, 4, 3] + for key in seq3: + seq_counts[key] += 1 + print(seq_counts) + + ''' also, we can use set operations such as a-b or a+b ''' + seq_counts_2 = Counter(seq3) + print(seq_counts_2) + print(seq_counts + seq_counts_2) + print(seq_counts - seq_counts_2) + +if __name__ == '__main__': + Counter_example() + + diff --git a/src/examples_in_my_book/general_problems/dicts/OrderedDict_example.py b/src/examples_in_my_book/general_problems/dicts/OrderedDict_example.py new file mode 100644 index 0000000..b7dbef1 --- /dev/null +++ b/src/examples_in_my_book/general_problems/dicts/OrderedDict_example.py @@ -0,0 +1,31 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + +from collections import OrderedDict + +def OrderedDict_example(): + ''' show some examples for OrderedDict ''' + ''' keep the order of insertion. + maintains a doubly linked list, so size is more than twice than normal dict''' + + + pairs = [('a', 1), ('b',2), ('c',3)] + + d1 = {} + for key, value in pairs: + if key not in d1: + d1[key] = [] + d1[key].append(value) + for key in d1: + print(key, d1[key]) + + d2 = OrderedDict(pairs) + for key in d2: + print(key, d2[key]) + + +if __name__ == '__main__': + OrderedDict_example() + + diff --git a/src/examples_in_my_book/general_problems/dicts/__init__.py b/src/examples_in_my_book/general_problems/dicts/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/examples_in_my_book/general_problems/dicts/count_unique_words_.py b/src/examples_in_my_book/general_problems/dicts/count_unique_words_.py new file mode 100644 index 0000000..fdf66c3 --- /dev/null +++ b/src/examples_in_my_book/general_problems/dicts/count_unique_words_.py @@ -0,0 +1,21 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + +import collections +import string +import sys + +def count_unique_word(): + words = collections.defaultdict(int) + strip = string.whitespace + string.punctuation + string.digits + "\"'" + for filename in sys.argv[1:]: + with open(filename) as file: + for line in file: + for word in line.lower().split(): + word = word.strip(strip) + if len(word) > 2: + words[word] = +1 + for word in sorted(words): + print("'{0}' occurs {1} times.".format(word, words[word])) + diff --git a/src/examples_in_my_book/general_problems/dicts/defaultdict_example.py b/src/examples_in_my_book/general_problems/dicts/defaultdict_example.py new file mode 100644 index 0000000..cea9d1c --- /dev/null +++ b/src/examples_in_my_book/general_problems/dicts/defaultdict_example.py @@ -0,0 +1,27 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + +from collections import defaultdict + +def defaultdict_example(): + ''' show some examples for defaultdicts ''' + pairs = {('a', 1), ('b',2), ('c',3)} + + d1 = {} + for key, value in pairs: + if key not in d1: + d1[key] = [] + d1[key].append(value) + print(d1) + + d2 = defaultdict(list) + for key, value in pairs: + d2[key].append(value) + print(d2) + + +if __name__ == '__main__': + defaultdict_example() + + diff --git a/src/examples_in_my_book/general_problems/dicts/delete_duplicate_char_str.py b/src/examples_in_my_book/general_problems/dicts/delete_duplicate_char_str.py new file mode 100644 index 0000000..b186f2b --- /dev/null +++ b/src/examples_in_my_book/general_problems/dicts/delete_duplicate_char_str.py @@ -0,0 +1,32 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + +import string + +def delete_unique_word(str1): + ''' find and delete all the duplicate characters in a string ''' + + # create ordered dict + table_c = { key : 0 for key in string.ascii_lowercase} + + # fill the table with the chars in the string + for i in str1: + table_c[i] += 1 + + # scan the table to find times chars > 1 + for key, value in table_c.items(): + if value > 1: + str1 = str1.replace(key, "") + + return str1 + + +def test_delete_unique_word(): + str1 = "google" + assert(delete_unique_word(str1) == 'le') + print('Tests passed!') + +if __name__ == '__main__': + test_delete_unique_word() + diff --git a/src/examples_in_my_book/general_problems/dicts/find_anagram_hash_function.py b/src/examples_in_my_book/general_problems/dicts/find_anagram_hash_function.py new file mode 100644 index 0000000..fb2a61b --- /dev/null +++ b/src/examples_in_my_book/general_problems/dicts/find_anagram_hash_function.py @@ -0,0 +1,34 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + + +def hash_func(astring, tablesize): + sum = 0 + for pos in range(len(astring)): + sum = sum + ord(astring[pos]) + return sum%tablesize + + +def find_anagram_hash_function(word1, word2): + ''' verify if words are anagrams by comparying hash functions''' + tablesize = 11 + return hash_func(word1, tablesize) == hash_func(word2, tablesize) + + + + +def test_find_anagram_hash_function(module_name='this module'): + word1 = 'buffy' + word2 = 'bffyu' + word3 = 'bffya' + assert(find_anagram_hash_function(word1, word2) == True) + assert(find_anagram_hash_function(word1, word3) == False) + + s = 'Tests in {name} have {con}!' + print(s.format(name=module_name, con='passed')) + + +if __name__ == '__main__': + test_find_anagram_hash_function() + diff --git a/src/examples_in_my_book/general_problems/dicts/find_dice_probabilities.py b/src/examples_in_my_book/general_problems/dicts/find_dice_probabilities.py new file mode 100644 index 0000000..10e2d48 --- /dev/null +++ b/src/examples_in_my_book/general_problems/dicts/find_dice_probabilities.py @@ -0,0 +1,33 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + +from collections import Counter, defaultdict + +def find_dice_probabilities(S, n_faces=6): + ''' given 2 dice, determine number of ways to sum S if all dice are rolled ''' + + if S > 2*n_faces or S < 2: return None + + cdict = Counter() + ddict = defaultdict(list) + + for dice1 in range(1, n_faces+1): + for dice2 in range(1, n_faces+1): + t = [dice1, dice2] + cdict[dice1+dice2] += 1 + ddict[dice1+dice2].append( t) + + return [cdict[S], ddict[S]] + + +def test_find_dice_probabilities(module_name='this module'): + n_faces = 6 + S = 5 + results = find_dice_probabilities(S, n_faces) + print(results) + assert(results[0] == len(results[1])) + + +if __name__ == '__main__': + test_find_dice_probabilities() diff --git a/src/examples_in_my_book/general_problems/dicts/find_top_N_recurring_words.py b/src/examples_in_my_book/general_problems/dicts/find_top_N_recurring_words.py new file mode 100644 index 0000000..d699fe7 --- /dev/null +++ b/src/examples_in_my_book/general_problems/dicts/find_top_N_recurring_words.py @@ -0,0 +1,31 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + +from collections import Counter + +def find_top_N_recurring_words(seq, N): + ''' find the top N recurring words in a file: + 1) use a hash table to find counts + 2) sort the list on base of the maximum counts + 3) return the last N words ''' + + dcounter = Counter() + for word in seq.split(): + dcounter[word] += 1 + return dcounter.most_common(N) + + + +def test_find_top_N_recurring_words(module_name='this module'): + seq = 'buffy angel monster xander a willow gg buffy the monster super buffy angel' + N = 3 + assert(find_top_N_recurring_words(seq, N) == [('buffy', 3), ('monster', 2), ('angel', 2)]) + + s = 'Tests in {name} have {con}!' + print(s.format(name=module_name, con='passed')) + + +if __name__ == '__main__': + test_find_top_N_recurring_words() + diff --git a/src/examples_in_my_book/general_problems/dicts/runtime_dicts_with_timeit_module.py b/src/examples_in_my_book/general_problems/dicts/runtime_dicts_with_timeit_module.py new file mode 100644 index 0000000..c8138fc --- /dev/null +++ b/src/examples_in_my_book/general_problems/dicts/runtime_dicts_with_timeit_module.py @@ -0,0 +1,51 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + + +'''To use timeit you create a Timer object whose parameters are two Python statements. The first parameter is a Python statement that you want to time; the second parameter is a statement that will run once to set up the test. The timeit module will then time how long it takes to execute the statement some number of times. By default timeit will try to run the statement one million times. When its done it returns the time as a floating point value representing the total number of seconds. However, since it executes the statement a million times you can read the result as the number of microseconds to execute the test one time. You can also pass timeit a named parameter called number that allows you to specify how many times the test statement is executed. The following session shows how long it takes to run each of our test functions 1000 times. ''' + + +import timeit +import random + +for i in range(10000,1000001,20000): + ''' this experiment confirm that the contains operator for lists is O(n) and for dict is O(1) ''' + t = timeit.Timer("random.randrange(%d) in x"%i, "from __main__ import random,x") + x = list(range(i)) + lst_time = t.timeit(number=1000) + x = {j:None for j in range(i)} + d_time = t.timeit(number=1000) + print("%d,%10.3f,%10.3f" % (i, lst_time, d_time)) + + +""" There rersults are: +10000, 0.192, 0.002 +30000, 0.600, 0.002 +50000, 1.000, 0.002 +70000, 1.348, 0.002 +90000, 1.755, 0.002 +110000, 2.194, 0.002 +130000, 2.635, 0.002 +150000, 2.951, 0.002 +170000, 3.405, 0.002 +190000, 3.743, 0.002 +210000, 4.142, 0.002 +230000, 4.577, 0.002 +250000, 4.797, 0.002 +270000, 5.371, 0.002 +290000, 5.690, 0.002 +310000, 5.977, 0.002 + +so we can see the linear tile for lists, and constant for dict! + +Big-O Efficiency of Python Dictionary Operations +Operation Big-O Efficiency +copy O(n) +get item O(1) +set item O(1) +delete item O(1) +contains (in) O(1) +iteration O(n) +""" + diff --git a/src/examples_in_my_book/general_problems/dicts/setdeault_example.py b/src/examples_in_my_book/general_problems/dicts/setdeault_example.py new file mode 100644 index 0000000..55dbfd4 --- /dev/null +++ b/src/examples_in_my_book/general_problems/dicts/setdeault_example.py @@ -0,0 +1,38 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + + +def usual_dict(dict_data): + newdata = {} + for k, v in dict_data: + if k in newdata: + newdata[k].append(v) + else: + newdata[k] = [v] + return newdata + + +def setdefault_dict(dict_data): + newdata = {} + for k, v in dict_data: + newdata.setdefault(k, []).append(v) + return newdata + + +def test_setdef(module_name='this module'): + dict_data = (('key1', 'value1'), + ('key1', 'value2'), + ('key2', 'value3'), + ('key2', 'value4'), + ('key2', 'value5'),) + print(usual_dict(dict_data)) + print(setdefault_dict(dict_data)) + + s = 'Tests in {name} have {con}!' + print(s.format(name=module_name, con='passed')) + + +if __name__ == '__main__': + test_setdef() + diff --git a/src/examples_in_my_book/general_problems/dicts/veirfy_two_strings_are_anagrams.py b/src/examples_in_my_book/general_problems/dicts/veirfy_two_strings_are_anagrams.py new file mode 100644 index 0000000..c10266c --- /dev/null +++ b/src/examples_in_my_book/general_problems/dicts/veirfy_two_strings_are_anagrams.py @@ -0,0 +1,45 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + +import string + + +def verify_two_strings_are_anagrams(str1, str2): + """ find whether two words are anagrams. Since sets do not count occurency, and sorting is O(nlogn) + we will use hash tables. We scan the first string and add all the character occurences. Then we + scan the second tring and decrease all the caracther occurences. If all the counts are zero, it is + an anagram""" + + # create the hash table + ana_table = {key:0 for key in string.ascii_lowercase} + + # scan first string + for i in str1: + ana_table[i] += 1 + + # scan second string + for i in str2: + ana_table[i] -= 1 + + # verify whether all the entries are 0 + if len(set(ana_table.values())) < 2: return True + else: return False + + +def test_verify_two_strings_are_anagrams(): + str1 = 'marina' + str2 = 'aniram' + assert(verify_two_strings_are_anagrams(str1, str2) == True) + str1 = 'google' + str2 = 'gouglo' + assert(verify_two_strings_are_anagrams(str1, str2) == False) + print('Tests passed!') + + +if __name__ == '__main__': + test_verify_two_strings_are_anagrams() + + + + diff --git a/src/examples_in_my_book/general_problems/lists/__init__.py b/src/examples_in_my_book/general_problems/lists/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/examples_in_my_book/general_problems/lists/find_closest_num_seq.py b/src/examples_in_my_book/general_problems/lists/find_closest_num_seq.py new file mode 100644 index 0000000..c3c587c --- /dev/null +++ b/src/examples_in_my_book/general_problems/lists/find_closest_num_seq.py @@ -0,0 +1,47 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + + + +def find_closest_num_seq_unsorted(seq): + ''' Find the Closest two Numbers in a Sequence. If we do this without sorting + first, the runtime will be O(n^2) ''' + dd = float("inf") + for x in seq: + for y in seq: + if x == y: continue + d = abs(x - y) + if d < dd: + xx, yy, dd = x, y, d + return xx, yy + + +def find_closest_num_seq_sorted(seq): + ''' However, if we sort first, we can achieve it with runtime O(n log n): ''' + seq.sort() + print(seq) + dd = float("inf") + for i in range(len(seq) - 1): + x, y = seq[i], seq[i+1] + if x == y: continue + d = abs(x-y) + if d < dd: + xx, yy, dd = x, y, d + return xx, yy + + +def test_find_closest_num_seq(module_name='this module'): + import random + seq = [random.randrange(100) for i in range(20)] + print(seq) + print(find_closest_num_seq_sorted(seq)) + print(find_closest_num_seq_unsorted(seq)) + + s = 'Tests in {name} have {con}!' + print(s.format(name=module_name, con='passed')) + + +if __name__ == '__main__': + test_find_closest_num_seq() + diff --git a/src/examples_in_my_book/general_problems/lists/find_duplicate_num_array.py b/src/examples_in_my_book/general_problems/lists/find_duplicate_num_array.py new file mode 100644 index 0000000..d9330ba --- /dev/null +++ b/src/examples_in_my_book/general_problems/lists/find_duplicate_num_array.py @@ -0,0 +1,44 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + +def find_duplicate_num_array(l1): + """ an array contains n numbers ranging from 0 to n-1. there are some numbers duplicated, but it is + not clear how many. this code find a duplicate number in the array. """ + + """ A naive solution is to sort the input array, costing O(nlogn). Another solution is the utilization of a hash set. When the number is scanned, it is either in or not. It costs O(n) auxiliary memory to accomodate a hash set. A third solution, that only costs O(1) is consider that indexes in an array with length n are in the range n-1. If there were no duplication in the n numbers from 0 to n-1, we could rearange them sorted, so that each i has its ith number. Since there are duplicates, some locations are occupied by multiple numbers, other are vacant. So every number is scanned one by one, if it the number is not in the right i, it is compared to that from i, and the duplicate can be found, or we swap. Continue until a duplicate is found.""" + + for i in range(len(l1)): + if l1[i] == i: continue + elif l1[i] < 0 or l1[i] > len(l1)-1: + return None + elif l1[i] == l1[l1[i]]: + return True + else: + aux = l1[l1[i]] + l1[l1[i]] = l1[i] + l1[i] = aux + else: + return False + +def test_find_duplicate_num_array(): + a = [1,3,5,2,4,0] + b = [1,3,5,2,1,0,4] + c = [0,0] + assert(find_duplicate_num_array(b) == True) + assert(find_duplicate_num_array(a) == False) + assert(find_duplicate_num_array(c) == True) + print('Tests passed!') + +if __name__ == '__main__': + test_find_duplicate_num_array() + + + + + + + + + + diff --git a/src/examples_in_my_book/general_problems/lists/find_long_con_inc_subseq.py b/src/examples_in_my_book/general_problems/lists/find_long_con_inc_subseq.py new file mode 100644 index 0000000..cb01c54 --- /dev/null +++ b/src/examples_in_my_book/general_problems/lists/find_long_con_inc_subseq.py @@ -0,0 +1,30 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + +def find_long_con_inc(seq): + ''' find the longest continuous increasing subsequence''' + one_seq = [] + result = [] + + for i in range(0, len(seq)-1): + pivot = seq[i] + if pivot <= seq[i+1]: + one_seq.append(pivot) + else: + one_seq.append(pivot) + if len(one_seq) > len(result): + result = one_seq + one_seq = [] + return result + + +def test_find_long_con_inc(module_name='this module'): + seq = [1, -2, 3, 5, 1, -1, 4, -1, 6] + long_con_inc = [-2,3,5] + + assert(find_long_con_inc(seq) == long_con_inc ) + +if __name__ == '__main__': + test_find_long_con_inc() + diff --git a/src/examples_in_my_book/general_problems/lists/find_long_con_inc_subseq.py~ b/src/examples_in_my_book/general_problems/lists/find_long_con_inc_subseq.py~ new file mode 100644 index 0000000..5412465 --- /dev/null +++ b/src/examples_in_my_book/general_problems/lists/find_long_con_inc_subseq.py~ @@ -0,0 +1,31 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + +def find_long_con_inc(seq): + ''' find the longest continuous increasing subsequence''' + one_seq = [] + result = [] + + for i in range(0, len(seq)-1): + pivot = seq[i] + if pivot <= seq[i+1]: + one_seq.append(pivot) + else: + one_seq.append(pivot) + if len(one_seq) > len(result): + result = one_seq + one_seq = [] + return result + + +def test_find_long_con_inc(module_name='this module'): + seq = [1, -2, 3, 5, 1, -1, 4, -1, 6] + long_con_inc = [-2,3,5] + + assert(find_long_con_inc(seq) == long_con_inc ) + + +if __name__ == '__main__': + test_find_long_con_inc() + diff --git a/src/examples_in_my_book/general_problems/lists/find_majority_in_seq.py b/src/examples_in_my_book/general_problems/lists/find_majority_in_seq.py new file mode 100644 index 0000000..da38c11 --- /dev/null +++ b/src/examples_in_my_book/general_problems/lists/find_majority_in_seq.py @@ -0,0 +1,58 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + +def find_majority_in_seq(seq): + ''' find value which occurrence is greater than the total occurrence of all other elements ''' + times = 1 + result = seq[0] + for i in range(len(seq)): + if times == 0: + result = seq[i] + times = 1 + elif seq[i] == result: + times +=1 + else: + times -=1 + + if times == 0: return None + else: + count = 0 + for i, c in enumerate(seq): + if c == result: + count += 1 + return result, count + + +def test_find_majority_in_seq(): + seq = [1, 1, 2, 3, 3, 3, 4, 4, 4, 4, 5, 6] + seq2 = [1, 2, 3] + assert(find_majority_in_seq(seq) == (4, 4)) + assert(find_majority_in_seq(seq2) == None) + print('Tests passed!') + +if __name__ == '__main__': + test_find_majority_in_seq() + + + + + + + + + +""" +>>> A = [1, 2, 3, 2, 2, 4, 2, 5, 2] +>>> find_majority(A) +(2, 5) +>>> A = [1] +>>> find_majority(A) +(1, 1) +>>> A = [1, 2, 3, 2, 5, 6, 7] +>>> find_majority(A) +No Majority Element. +""" + + + diff --git a/src/examples_in_my_book/general_problems/lists/find_max_profit.py b/src/examples_in_my_book/general_problems/lists/find_max_profit.py new file mode 100644 index 0000000..9b5d583 --- /dev/null +++ b/src/examples_in_my_book/general_problems/lists/find_max_profit.py @@ -0,0 +1,44 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + + +def find_max_profit_On(seq): + ''' find the most profit from a seq with O(n) ''' + max_profit = 0 + min_value = seq[0] + for i in range(1, len(seq)): + profit_here = seq[i]- min_value + if profit_here > max_profit: + max_profit = profit_here + else: + if min_value > seq[i]: + min_value = seq[i] + + return max_profit + + +def find_max_profit_On2(seq): + ''' find the most profit from a seq with O(n2) ''' + max_profit = 0 + for i in range(len(seq)-1): + for j in range (i, len(seq)-1): + if seq[j] - seq[i] > max_profit: + max_profit = seq[j] - seq[i] + return max_profit + + +def test_find_max_profit(): + seq = [9,11,5,7,16,1] + assert(find_max_profit_On(seq) == 11) + assert(find_max_profit_On2(seq) == 11) + seq = [1,15,2,3,4,3] + assert(find_max_profit_On(seq) == 14) + assert(find_max_profit_On2(seq) == 14) + print('Tests passed!') + + +if __name__ == '__main__': + test_find_max_profit() + + diff --git a/src/examples_in_my_book/general_problems/lists/find_max_subarray.py b/src/examples_in_my_book/general_problems/lists/find_max_subarray.py new file mode 100644 index 0000000..36a9328 --- /dev/null +++ b/src/examples_in_my_book/general_problems/lists/find_max_subarray.py @@ -0,0 +1,44 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + +def find_max_subarray1(l1): + ''' calculate the greatest sum of subarrays from an array. + An array with n elements has n(n+1)/2 subarrays so force brute cost O(n^2). + What we can do is to check when a sum becomes a negative number or zero, and then discard, since + this will not "add" anything to the new event... When the sum decreases, it gets the previous sum. ''' + sum_new, result = 0, 0 + for c in l1: + result = max(result, sum_new) + sum_new += c + if sum_new <= 0: sum_new = 0 + return result + + + +def find_max_subarray2(l1): + ''' find the contiguous subarray which has the largest sum (Kadane's algorithm in O(n)) + with extra O(n) space ''' + sum_old = [l1[0]] + for c in l1: + sum_old.append(max(c, sum_old [-1] + c)) + return max(sum_old) + + +def test_find_max_subarray(): + l1 = [-2, 1, -3, 4, -1, 2, 1, -5, 4] + l2 = [-1, 3, -5, 4, 6, -1, 2, -7, 13, -3] + assert(find_max_subarray1(l1)) == 6) + assert(find_max_subarray1(l2)) == 17) + assert(find_max_subarray2(l1) == 6) + assert(find_max_subarray2(l2) == 17) + print('Tests passed!') + +if __name__ == '__main__': + test_find_max_subarray() + + + + + + diff --git a/src/examples_in_my_book/general_problems/lists/find_max_subarray.py~ b/src/examples_in_my_book/general_problems/lists/find_max_subarray.py~ new file mode 100644 index 0000000..36a9328 --- /dev/null +++ b/src/examples_in_my_book/general_problems/lists/find_max_subarray.py~ @@ -0,0 +1,44 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + +def find_max_subarray1(l1): + ''' calculate the greatest sum of subarrays from an array. + An array with n elements has n(n+1)/2 subarrays so force brute cost O(n^2). + What we can do is to check when a sum becomes a negative number or zero, and then discard, since + this will not "add" anything to the new event... When the sum decreases, it gets the previous sum. ''' + sum_new, result = 0, 0 + for c in l1: + result = max(result, sum_new) + sum_new += c + if sum_new <= 0: sum_new = 0 + return result + + + +def find_max_subarray2(l1): + ''' find the contiguous subarray which has the largest sum (Kadane's algorithm in O(n)) + with extra O(n) space ''' + sum_old = [l1[0]] + for c in l1: + sum_old.append(max(c, sum_old [-1] + c)) + return max(sum_old) + + +def test_find_max_subarray(): + l1 = [-2, 1, -3, 4, -1, 2, 1, -5, 4] + l2 = [-1, 3, -5, 4, 6, -1, 2, -7, 13, -3] + assert(find_max_subarray1(l1)) == 6) + assert(find_max_subarray1(l2)) == 17) + assert(find_max_subarray2(l1) == 6) + assert(find_max_subarray2(l2) == 17) + print('Tests passed!') + +if __name__ == '__main__': + test_find_max_subarray() + + + + + + diff --git a/src/examples_in_my_book/general_problems/lists/find_product_without_division.py b/src/examples_in_my_book/general_problems/lists/find_product_without_division.py new file mode 100644 index 0000000..82bcf0d --- /dev/null +++ b/src/examples_in_my_book/general_problems/lists/find_product_without_division.py @@ -0,0 +1,33 @@ +def find_product_without_division(seq): + '''Given an array of numbers, replace each number with the product of all the numbers in the array except the number itself *without* using division ''' + forw = [] + bacw = [] + + for i in range(len(seq)): + prod_f = 1 + prod_b = 1 + for next in range(i+1, len(seq)): + prod_f *= seq[next] + for before in range(0, i): + prod_b *= seq[before] + forw.append(prod_f) + bacw.append(prod_b) + + print(bacw) + print(forw) + for i in range(len(seq)): + seq[i] = forw[i]*bacw[i] + + return seq + + + +def test_find_product_without_division(): + seq = [2,3,4] + result = [12, 8, 6] + print(find_product_without_division(seq)) + + + +if __name__ == '__main__': + test_find_product_without_division() diff --git a/src/examples_in_my_book/general_problems/lists/find_two_missing_numbers_in_sequence.py b/src/examples_in_my_book/general_problems/lists/find_two_missing_numbers_in_sequence.py new file mode 100644 index 0000000..24beab5 --- /dev/null +++ b/src/examples_in_my_book/general_problems/lists/find_two_missing_numbers_in_sequence.py @@ -0,0 +1,55 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + + +import math + +def find_two_missing_numbers(l1): + """ Two numbers out of n numbers from 1 to n are missing. The remaining n-2 numbers are in the + array but not sorted. Find the missing numbers The sum1 is the sum of all the elements in n. The + sum2 is the sum of all the elements in n-2. sum1 - sum2 = num1 + num2 = s. The prod1 is the prod of + all the elements in n. The prod2 is the prod of all the elements in n-2. prod1/prod2 = num1*num2 = + p. Runtime is O(n), because it scan 3 times. Space is O(1) + + - In case of finding one integer, Let the missing number be M. We know that the sum of first N + natural numbers is N*(N+1)/2. Traverse through the array once and calculate the sum. This is the + sum of first N natural numbers – M or S=N*(N+1)/2 – M. Therefore M = N*(N+1)/2 – S. + """ + + n_min_2 = len(l1) + n = n_min_2 + 2 + sum1, sum2, prod1, prod2 = 0,0,1,1 + sum2 = sum(l1[:]) + sum1 = sum(range(1,n+1)) + s = sum1 - sum2 + + for i in range(1, n-1): + prod1 = prod1*i + prod2 = prod2*l1[i-1] + + prod1 = prod1*n*(n-1) + p = prod1/prod2 + num1 = (s + math.sqrt(s*s - 4*p))/2 + num2 = (s - math.sqrt(s*s - 4*p))/2 + + return num1, num2 + + + +def test_find_two_missing_numbers(): + l1 = [1, 3, 5] + result = find_two_missing_numbers(l1) + assert(result[0] == 2.0 or result[0] == 4.0) + print('Tests passed!') + + +if __name__ == '__main__': + test_find_two_missing_numbers() + + + + + + + diff --git a/src/examples_in_my_book/general_problems/lists/greatest_sum_sub_array.py b/src/examples_in_my_book/general_problems/lists/greatest_sum_sub_array.py new file mode 100644 index 0000000..10bf2f1 --- /dev/null +++ b/src/examples_in_my_book/general_problems/lists/greatest_sum_sub_array.py @@ -0,0 +1,27 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + + +def greatest_sum_sub_array(l1): + sum_new = 0 + results = [] + for i, c in enumerate(l1): + sum_old = sum_new + sum_new = sum_old + c + if sum_new <= 0 or sum_new < sum_old: + sum_new = 0 + results.append(sum_old) + continue + results.append(sum_new) + results.sort() + return results.pop() + +def test_greatest_sum_sub_array(): + l1 = [1, -4, 20, -4, 5, 15, 3] + assert(greatest_sum_sub_array(l1) == 23) + print('Tests passed!') + +if __name__ == '__main__': + test_greatest_sum_sub_array() + diff --git a/src/examples_in_my_book/general_problems/lists/greatest_sum_sub_array.py~ b/src/examples_in_my_book/general_problems/lists/greatest_sum_sub_array.py~ new file mode 100644 index 0000000..c3c587c --- /dev/null +++ b/src/examples_in_my_book/general_problems/lists/greatest_sum_sub_array.py~ @@ -0,0 +1,47 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + + + +def find_closest_num_seq_unsorted(seq): + ''' Find the Closest two Numbers in a Sequence. If we do this without sorting + first, the runtime will be O(n^2) ''' + dd = float("inf") + for x in seq: + for y in seq: + if x == y: continue + d = abs(x - y) + if d < dd: + xx, yy, dd = x, y, d + return xx, yy + + +def find_closest_num_seq_sorted(seq): + ''' However, if we sort first, we can achieve it with runtime O(n log n): ''' + seq.sort() + print(seq) + dd = float("inf") + for i in range(len(seq) - 1): + x, y = seq[i], seq[i+1] + if x == y: continue + d = abs(x-y) + if d < dd: + xx, yy, dd = x, y, d + return xx, yy + + +def test_find_closest_num_seq(module_name='this module'): + import random + seq = [random.randrange(100) for i in range(20)] + print(seq) + print(find_closest_num_seq_sorted(seq)) + print(find_closest_num_seq_unsorted(seq)) + + s = 'Tests in {name} have {con}!' + print(s.format(name=module_name, con='passed')) + + +if __name__ == '__main__': + test_find_closest_num_seq() + diff --git a/src/examples_in_my_book/general_problems/lists/merge_two_sorted_arrays.py b/src/examples_in_my_book/general_problems/lists/merge_two_sorted_arrays.py new file mode 100644 index 0000000..617d183 --- /dev/null +++ b/src/examples_in_my_book/general_problems/lists/merge_two_sorted_arrays.py @@ -0,0 +1,38 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + +def merge_two_sorted_arrays(a1, a2): + """ merge two sorted arrays, keeping the final sorted """ + if len(a1) >= len(a2): + biga = a1 + smalla = a2 + else: + biga = a2 + smalla = a1 + final = [] + count = 0 + for i in range(len(biga)): + if count < len(smalla) and smalla[count] < biga[i]: + final.append(smalla[count]) + count+=1 + final.append(biga[i]) + return final + +def test_merge_two_sorted_arrays(): + a1 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] + a2 = [3, 6, 7] + assert(merge_two_sorted_arrays(a1, a2) == [0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 7, 8, 9, 10]) + print('Tests passed!') + +if __name__ == '__main__': + test_merge_two_sorted_arrays() + + + + + + + + + diff --git a/src/examples_in_my_book/general_problems/lists/print_all_seq_with_cont_num.py b/src/examples_in_my_book/general_problems/lists/print_all_seq_with_cont_num.py new file mode 100644 index 0000000..1bfa771 --- /dev/null +++ b/src/examples_in_my_book/general_problems/lists/print_all_seq_with_cont_num.py @@ -0,0 +1,39 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + + +def print_all_seq_with_cont_num(s): + ''' print all sequences with cont. numbers (2 at least) whose sum is a given s ''' + if s < 3: return s + small = 1 + big = 2 + sum_here = big + small + result = [] + + while small < (1+s)/2: + sum_here = sum(range(small, big)) + if sum_here < s: + big += 1 + elif sum_here > s: + small +=1 + else: + result.append(list(range(small, big))) + big += 1 + + return result + +def test_print_all_seq_with_cont_num(): + s = 15 + sum_set_for_s = [[1,2,3,4,5], [4,5,6], [7,8]] + assert(print_all_seq_with_cont_num(s) == sum_set_for_s) + s = 1 + assert(print_all_seq_with_cont_num(s)== 1) + s = 0 + assert(print_all_seq_with_cont_num(s) == 0) + print('Tests passed!') + + +if __name__ == '__main__': + test_print_all_seq_with_cont_num() + diff --git a/src/examples_in_my_book/general_problems/lists/removing_duplicates_seq.py b/src/examples_in_my_book/general_problems/lists/removing_duplicates_seq.py new file mode 100644 index 0000000..9399ae3 --- /dev/null +++ b/src/examples_in_my_book/general_problems/lists/removing_duplicates_seq.py @@ -0,0 +1,37 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + + +def removing_duplicates_seq(seq): + ''' if the values are hashable, we can use set and generators to remove duplicates + in a sequence ''' + seen = set() + for item in seq: + if item not in seen: + yield item + seen.add(item) + +def removing_duplicates_seq_not_hash(seq, key= None): + ''' if the item is not hashable, such as dictionaries ''' + seen = set() + for item in seq: + val = item if key is None else key[item] + if item not in seen: + yield item + seen.add(val) + + + +def test_removing_duplicates_seq(): + seq = [1, 2, 2, 2, 3, 3, 4, 4, 4] + dict = {'a':1, 'b':2, 'a':2, 'a':1} + assert(list(removing_duplicates_seq(seq)) == [1,2,3,4]) + assert(list(removing_duplicates_seq_not_hash(dict)) == ['a', 'b']) + print('Tests passed!'.center(20, '*')) + + +if __name__ == '__main__': + test_removing_duplicates_seq() + + diff --git a/src/examples_in_my_book/general_problems/lists/runtime_lists_with_timeit_module.py b/src/examples_in_my_book/general_problems/lists/runtime_lists_with_timeit_module.py new file mode 100644 index 0000000..c9841bc --- /dev/null +++ b/src/examples_in_my_book/general_problems/lists/runtime_lists_with_timeit_module.py @@ -0,0 +1,67 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + + +'''To use timeit you create a Timer object whose parameters are two Python statements. The first parameter is a Python statement that you want to time; the second parameter is a statement that will run once to set up the test. The timeit module will then time how long it takes to execute the statement some number of times. By default timeit will try to run the statement one million times. When its done it returns the time as a floating point value representing the total number of seconds. However, since it executes the statement a million times you can read the result as the number of microseconds to execute the test one time. You can also pass timeit a named parameter called number that allows you to specify how many times the test statement is executed. The following session shows how long it takes to run each of our test functions 1000 times. ''' + + +def test1(): + l = [] + for i in range(1000): + l = l + [i] + +def test2(): + l = [] + for i in range(1000): + l.append(i) + +def test3(): + l = [i for i in range(1000)] + +def test4(): + l = list(range(1000)) + + + +if __name__ == '__main__': + import timeit + t1 = timeit.Timer("test1()", "from __main__ import test1") + print("concat ",t1.timeit(number=1000), "milliseconds") + t2 = timeit.Timer("test2()", "from __main__ import test2") + print("append ",t2.timeit(number=1000), "milliseconds") + t3 = timeit.Timer("test3()", "from __main__ import test3") + print("comprehension ",t3.timeit(number=1000), "milliseconds") + t4 = timeit.Timer("test4()", "from __main__ import test4") + print("list range ",t4.timeit(number=1000), "milliseconds") + + + +""" The results are: +('concat ', 2.366791009902954, 'milliseconds') +('append ', 0.16743111610412598, 'milliseconds') +('comprehension ', 0.06446194648742676, 'milliseconds') +('list range ', 0.021029949188232422, 'milliseconds') + + +So we see the following pattern for lists: + +Operation Big-O Efficiency +index [] O(1) +index assignment O(1) +append O(1) +pop() O(1) +pop(i) O(n) +insert(i,item) O(n) +del operator O(n) +iteration O(n) +contains (in) O(n) +get slice [x:y] O(k) +del slice O(n) +set slice O(n+k) +reverse O(n) +concatenate O(k) +sort O(n log n) +multiply O(nk) +""" + diff --git a/src/examples_in_my_book/general_problems/lists/sum_two_numbers_sequence.py b/src/examples_in_my_book/general_problems/lists/sum_two_numbers_sequence.py new file mode 100644 index 0000000..bee6a8d --- /dev/null +++ b/src/examples_in_my_book/general_problems/lists/sum_two_numbers_sequence.py @@ -0,0 +1,36 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + + +def sum_two_numbers_sequence(seq, s): + """ given an increasing sorted array and an integer s, find if there is a pair of two numbers in the array whose sum is s. It takes O(n). """ + l1 = seq[:] + l2 = seq[:] + l2.reverse() + n1 = l1.pop() + n2 = l2.pop() + while l2 and l1: + sum_here = n1 + n2 + if sum_here > s: + n1 = l1.pop() + elif sum_here < s: + n2 = l2.pop() + else: + return True + return False + + + +def test_sum_two_numbers_sequence(): + l1 = [1,2,3,4,5,6,7,8] + s = 7 + assert(sum_two_numbers_sequence(l1, s) == True) + print('Tests passed!') + + +if __name__ == '__main__': + test_sum_two_numbers_sequence() + + + diff --git a/src/examples_in_my_book/general_problems/modules/__init__.py b/src/examples_in_my_book/general_problems/modules/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/examples_in_my_book/general_problems/modules/change_ext_file.py b/src/examples_in_my_book/general_problems/modules/change_ext_file.py new file mode 100644 index 0000000..e5b9d7a --- /dev/null +++ b/src/examples_in_my_book/general_problems/modules/change_ext_file.py @@ -0,0 +1,28 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + +import os +import sys +import shutil + +def change_file_ext(): + """ read a file and an extension from the command line and produces a copy with its extension changed""" + if len(sys.argv) < 2: + print("Usage: change_ext.py filename.old_ext 'new_ext'") + sys.exit() + + name = os.path.splitext(sys.argv[1])[0] + "." + sys.argv[2] + print (name) + + try: + shutil.copyfile(sys.argv[1], name) + except OSError as err: + print (err) + + + +if __name__ == '__main__': + change_file_ext() + + diff --git a/src/examples_in_my_book/general_problems/modules/export_pickle.py b/src/examples_in_my_book/general_problems/modules/export_pickle.py new file mode 100644 index 0000000..b26bde8 --- /dev/null +++ b/src/examples_in_my_book/general_problems/modules/export_pickle.py @@ -0,0 +1,33 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + +import pickle + +def export_pickle(data, filename='test.dat', compress=False): + """ simple example of how to use pickle to export files """ + fh = None + try: + if compress: + fh = gzip.open(filename, "wb") # write binary + else: + fh = open(filename, "wb") # compact binary pickle format + pickle.dump(data, fh, pickle.HIGHEST_PROTOCOL) + + except(EnvironmentError, pickle.PickingError) as err: + print("{0}: export error: {1}".format(os.path.basename(sys.argv[0], err))) + return False + + finally: + if fh is not None: + fh.close() + + +def test_export_pickle(): + mydict = {'a': 1, 'b': 2, 'c': 3} + export_pickle(mydict) + + + +if __name__ == '__main__': + test_export_pickle() diff --git a/src/examples_in_my_book/general_problems/modules/fib_generator.py b/src/examples_in_my_book/general_problems/modules/fib_generator.py new file mode 100644 index 0000000..b4b812f --- /dev/null +++ b/src/examples_in_my_book/general_problems/modules/fib_generator.py @@ -0,0 +1,18 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + + +def fib_generator(): + a, b = 0, 1 + while True: + yield b + a, b = b, a+b + + +if __name__ == '__main__': + fib = fib_generator() + print(next(fib)) + print(next(fib)) + print(next(fib)) + print(next(fib)) diff --git a/src/examples_in_my_book/general_problems/modules/grep_word_from_files.py b/src/examples_in_my_book/general_problems/modules/grep_word_from_files.py new file mode 100644 index 0000000..6ef2a81 --- /dev/null +++ b/src/examples_in_my_book/general_problems/modules/grep_word_from_files.py @@ -0,0 +1,26 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + +import sys + +def grep_word_from_files(): + ''' using iterator enumerate to create a grep command ''' + word = sys.argv[1] + for filename in sys.argv[2:]: + with open(filename) as file: + for lino, line in enumerate(file, start=1): + if word in line: + print("{0}:{1}:{2:.40}".format(filename, lino, line.rstrip())) + + +if __name__ == '__main__': + if len(sys.argv) < 2: + print("Usage: grep_word_from_files.py word infile1 [infile2...]") + sys.exit() + else: + grep_word_from_files() + + + + diff --git a/src/examples_in_my_book/general_problems/modules/import_pickle.py b/src/examples_in_my_book/general_problems/modules/import_pickle.py new file mode 100644 index 0000000..9aa3ce5 --- /dev/null +++ b/src/examples_in_my_book/general_problems/modules/import_pickle.py @@ -0,0 +1,31 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + +import pickle + +def import_pickle(filename): + """ an example of using pickle for importing data from files """ + fh = None + try: + fh = open(filename, "rb") + mydict2 = pickle.load(fh) + return mydict2 + + except (EnvironmentError) as err: + print ("{0}: import error: {0}".format(os.path.basename(sys.arg[0]), err)) + return false + + finally: + if fh is not None: + fh.close() + + +def test_import_pickle(): + pkl_file = 'test.dat' + mydict = import_pickle(pkl_file) + print(mydict) + + +if __name__ == '__main__': + test_import_pickle() diff --git a/src/examples_in_my_book/general_problems/modules/passing_cmd_line_args.py b/src/examples_in_my_book/general_problems/modules/passing_cmd_line_args.py new file mode 100644 index 0000000..4a05b66 --- /dev/null +++ b/src/examples_in_my_book/general_problems/modules/passing_cmd_line_args.py @@ -0,0 +1,18 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + + +import sys + +def main(): + ''' print command line arguments ''' + for arg in sys.argv[1:]: + print arg + +if __name__ == "__main__": + main() + + + + diff --git a/src/examples_in_my_book/general_problems/modules/remove_blank_lines.py b/src/examples_in_my_book/general_problems/modules/remove_blank_lines.py new file mode 100644 index 0000000..4576434 --- /dev/null +++ b/src/examples_in_my_book/general_problems/modules/remove_blank_lines.py @@ -0,0 +1,53 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + + + +import os +import sys + +def read_data(filename): + lines = [] + fh = None + try: + fh = open(filename) + for line in fh: + if line.strip(): + lines.append(line) + except (IOError, OSError) as err: + print(err) + finally: + if fh is not None: + fh.close() + return lines + + +def write_data(lines, filename): + fh = None + try: + fh = open(filename, "w") + for line in lines: + fh.write(line) + except (EnvironmentError) as err: + print(err) + finally: + if fh is not None: + fh.close() + + +def remove_blank_lines(): + """ read a list of filenames on the command line and for each one produces another file with the same content but with no blank lines """ + + if len(sys.argv) < 2: + print ("Usage: noblank.py infile1 [infile2...]") + + for filename in sys.argv[1:]: + lines = read_data(filename) + if lines: + write_data(lines, filename) + + +if __name__ == '__main__': + remove_blank_lines() + diff --git a/src/examples_in_my_book/general_problems/modules/using_time_module.py b/src/examples_in_my_book/general_problems/modules/using_time_module.py new file mode 100644 index 0000000..027bbfe --- /dev/null +++ b/src/examples_in_my_book/general_problems/modules/using_time_module.py @@ -0,0 +1,23 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + +import time + +def sumOfN2(n): + ''' a simple example of how to time a function ''' + start = time.time() + theSum = 0 + for i in range(1,n+1): + theSum = theSum + i + end = time.time() + return theSum,end-start + + + +if __name__ == '__main__': + n = 5 + print("Sum is %d and required %10.7f seconds"%sumOfN2(n)) + n = 200 + print("Sum is %d and required %10.7f seconds"%sumOfN2(n)) + diff --git a/src/examples_in_my_book/general_problems/numbers/__init__.py b/src/examples_in_my_book/general_problems/numbers/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/examples_in_my_book/general_problems/numbers/convert_dec_to_any_base_rec.py b/src/examples_in_my_book/general_problems/numbers/convert_dec_to_any_base_rec.py new file mode 100644 index 0000000..63240b8 --- /dev/null +++ b/src/examples_in_my_book/general_problems/numbers/convert_dec_to_any_base_rec.py @@ -0,0 +1,27 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + + +def convert_dec_to_any_base_rec(number, base): + ''' convert an integer to a string in any base''' + convertString = '012345679ABCDEF' + if number < base: return convertString[number] + else: + return convert_dec_to_any_base_rec(number//base, base) + convertString[number%base] + + + + +def test_convert_dec_to_any_base_rec(module_name='this module'): + number = 9 + base = 2 + assert(convert_dec_to_any_base_rec(number, base) == '1001') + + s = 'Tests in {name} have {con}!' + print(s.format(name=module_name, con='passed')) + + +if __name__ == '__main__': + test_convert_dec_to_any_base_rec() + diff --git a/src/examples_in_my_book/general_problems/numbers/convert_from_decimal.py b/src/examples_in_my_book/general_problems/numbers/convert_from_decimal.py new file mode 100644 index 0000000..6c2c8ed --- /dev/null +++ b/src/examples_in_my_book/general_problems/numbers/convert_from_decimal.py @@ -0,0 +1,24 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + +def convert_from_decimal(number, base): + ''' convert any decimal number to another base. ''' + multiplier, result = 1, 0 + while number > 0: + result += number%base*multiplier + multiplier *= 10 + number = number//base + return result + + +def test_convert_from_decimal(): + number, base = 9, 2 + assert(convert_from_decimal(number, base) == 1001) + print('Tests passed!') + + +if __name__ == '__main__': + test_convert_from_decimal() + + diff --git a/src/examples_in_my_book/general_problems/numbers/convert_from_decimal_larger_bases.py b/src/examples_in_my_book/general_problems/numbers/convert_from_decimal_larger_bases.py new file mode 100644 index 0000000..f8a7d71 --- /dev/null +++ b/src/examples_in_my_book/general_problems/numbers/convert_from_decimal_larger_bases.py @@ -0,0 +1,24 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + + +def convert_from_decimal_larger_bases(number, base): + ''' convert any decimal number to a number in a base up to 20''' + strings = "0123456789ABCDEFGHIJ" + result = "" + while number > 0: + digit = number%base + result = strings[digit] + result + number = number//base + return result + +def test_convert_from_decimal_larger_bases(): + number, base = 31, 16 + assert(convert_from_decimal_larger_bases(number, base) == '1F') + print('Tests passed!') + +if __name__ == '__main__': + test_convert_from_decimal_larger_bases() + + diff --git a/src/examples_in_my_book/general_problems/numbers/convert_to_decimal.py b/src/examples_in_my_book/general_problems/numbers/convert_to_decimal.py new file mode 100644 index 0000000..6c7af35 --- /dev/null +++ b/src/examples_in_my_book/general_problems/numbers/convert_to_decimal.py @@ -0,0 +1,25 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + + +def convert_to_decimal(number, base): + ''' convert any number in another base to the decimal base''' + multiplier, result = 1, 0 + while number > 0: + result += number%10*multiplier + multiplier *= base + number = number//10 + return result + + +def test_convert_to_decimal(): + number, base = 1001, 2 + assert(convert_to_decimal(number, base) == 9) + print('Tests passed!') + + +if __name__ == '__main__': + test_convert_to_decimal() + + diff --git a/src/examples_in_my_book/general_problems/numbers/find_fibonacci_seq.py b/src/examples_in_my_book/general_problems/numbers/find_fibonacci_seq.py new file mode 100644 index 0000000..911714d --- /dev/null +++ b/src/examples_in_my_book/general_problems/numbers/find_fibonacci_seq.py @@ -0,0 +1,44 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + +import math + +def find_fibonacci_seq_rec(n): + ''' implements the nth fibonacci value in a recursive exponential runtime ''' + if n < 2: return n + return find_fibonacci_seq_rec(n - 1) + find_fibonacci_seq_rec(n - 2) + + + +def find_fibonacci_seq_iter(n): + ''' return the nth fibonacci value in a iterative O(n^2) runtime ''' + if n < 2: return n + a, b = 0, 1 + for i in range(n): + a, b = b, a + b + return a + + +def find_fibonacci_seq_form(n): + ''' return the nth fibonacci value implemented by the formula, nearly constant-time algorithm, + but, it has a poor precise (after 72 it starts to become wrong) ''' + sq5 = math.sqrt(5) + phi = (1 + sq5) / 2 + return int(math.floor(phi ** n / sq5)) + + + +def test_find_fib(): + n = 10 + assert(find_fibonacci_seq_rec(n) == 55) + assert(find_fibonacci_seq_iter(n) == 55) + assert(find_fibonacci_seq_form(n) == 55) + print('Tests passed!') + + + +if __name__ == '__main__': + test_find_fib() + + diff --git a/src/examples_in_my_book/general_problems/numbers/finding_gcd.py b/src/examples_in_my_book/general_problems/numbers/finding_gcd.py new file mode 100644 index 0000000..dd7cb82 --- /dev/null +++ b/src/examples_in_my_book/general_problems/numbers/finding_gcd.py @@ -0,0 +1,28 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + + +def finding_gcd(a, b): + ''' implements the greatest common divider algorithm ''' + while(b != 0): + result = b + a, b = b, a % b + return result + + +def test_finding_gcd(): + number1 = 21 + number2 = 12 + assert(finding_gcd(number1, number2) == 3) + print('Tests passed!') + +if __name__ == '__main__': + test_finding_gcd() + + + + + + + diff --git a/src/examples_in_my_book/general_problems/numbers/finding_if_prime.py b/src/examples_in_my_book/general_problems/numbers/finding_if_prime.py new file mode 100644 index 0000000..2c2c447 --- /dev/null +++ b/src/examples_in_my_book/general_problems/numbers/finding_if_prime.py @@ -0,0 +1,59 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + +import math +import random + +def finding_prime(number): + ''' find whether a number is prime in a simple way''' + num = abs(number) + if num < 4 : return True + for x in range(2, num): + if num % x == 0: + return False + return True + + +def finding_prime_sqrt(number): + ''' find whether a number is prime as soon as it rejects all candidates up to sqrt(n) ''' + num = abs(number) + if num < 4 : return True + for x in range(2, int(math.sqrt(num)) + 1): + if number % x == 0: + return False + return True + + +def finding_prime_fermat(number): + ''' find whether a number is prime with Fermat's theorem, using probabilistic tests ''' + if number <= 102: + for a in range(2, number): + if pow(a, number- 1, number) != 1: + return False + return True + else: + for i in range(100): + a = random.randint(2, number - 1) + if pow(a, number - 1, number) != 1: + return False + return True + + + +def test_finding_prime(): + number1 = 17 + number2 = 20 + assert(finding_prime(number1) == True) + assert(finding_prime(number2) == False) + assert(finding_prime_sqrt(number1) == True) + assert(finding_prime_sqrt(number2) == False) + assert(finding_prime_fermat(number1) == True) + assert(finding_prime_fermat(number2) == False) + print('Tests passed!') + + +if __name__ == '__main__': + test_finding_prime() + + diff --git a/src/examples_in_my_book/general_problems/numbers/generate_prime.py b/src/examples_in_my_book/general_problems/numbers/generate_prime.py new file mode 100644 index 0000000..a008b4c --- /dev/null +++ b/src/examples_in_my_book/general_problems/numbers/generate_prime.py @@ -0,0 +1,35 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + +import math +import random +import sys +from finding_prime import finding_prime_sqrt + + +def generate_prime(number=3): + ''' return a n-bit prime ''' + while 1: + p = random.randint(pow(2, number-2), pow(2, number-1)-1) + p = 2 * p + 1 + if finding_prime_sqrt(p): + return p + + +if __name__ == '__main__': + if len(sys.argv) < 2: + print ("Usage: generate_prime.py number") + sys.exit() + else: + number = int(sys.argv[1]) + print(generate_prime(number)) + + + + + + + + + diff --git a/src/examples_in_my_book/general_problems/numbers/search_entry_matrix.py b/src/examples_in_my_book/general_problems/numbers/search_entry_matrix.py new file mode 100644 index 0000000..0ddd73b --- /dev/null +++ b/src/examples_in_my_book/general_problems/numbers/search_entry_matrix.py @@ -0,0 +1,40 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + + + +def find_elem_matrix_bool(m1, value): + ''' Search an Entry in a Matrix where the Rows and columns are Sorted + In this 2D matrix, every row is increasingly sorted from left to right, + and every column is increasingly sorted from top to bottom. + The runtime is O(m+n). ''' + found = False + row = 0 + col = len(m1[0]) - 1 + while row < len(m1) and col >= 0: + if m1[row][col] == value: + found = True + break + elif m1[row][col] > value: + col-=1 + else: + row+=1 + return found + + + +def test_find_elem_matrix_bool(module_name='this module'): + m1 = [[1,2,8,9], [2,4,9,12], [4,7,10,13], [6,8,11,15]] + assert(find_elem_matrix_bool(m1,8) == True) + assert(find_elem_matrix_bool(m1,3) == False) + m2 = [[0]] + assert(find_elem_matrix_bool(m2,0) == True) + + s = 'Tests in {name} have {con}!' + print(s.format(name=module_name, con='passed')) + + +if __name__ == '__main__': + test_find_elem_matrix_bool() + diff --git a/src/examples_in_my_book/general_problems/numbers/testing_floats.py b/src/examples_in_my_book/general_problems/numbers/testing_floats.py new file mode 100644 index 0000000..5734170 --- /dev/null +++ b/src/examples_in_my_book/general_problems/numbers/testing_floats.py @@ -0,0 +1,45 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + +from fractions import Fraction + +def rounding_floats(number1, places): + ''' some operations with float()''' + return round(number1, places) + + +def float_to_fractions(number): + return Fraction(*number.as_integer_ratio()) + + +def get_denominator(number1, number2): + a = Fraction(number1, number2) + return a.denominator + + +def get_numerator(number1, number2): + a = Fraction(number1, number2) + return a.numerator + + +def test_testing_floats(module_name='this module'): + number1 = 1.25 + number2 = 1 + number3 = -1 + number4 = 5/4 + number6 = 6 + assert(rounding_floats(number1, number2) == 1.2) + assert(rounding_floats(number1*10, number3) == 10) + assert(float_to_fractions(number1) == number4) + assert(get_denominator(number2, number6) == number6) + assert(get_numerator(number2, number6) == number2) + + s = 'Tests in {name} have {con}!' + print(s.format(name=module_name, con='passed')) + + +if __name__ == '__main__': + test_testing_floats() + + diff --git a/src/examples_in_my_book/general_problems/numbers/testing_numpy.py b/src/examples_in_my_book/general_problems/numbers/testing_numpy.py new file mode 100644 index 0000000..bbd3fae --- /dev/null +++ b/src/examples_in_my_book/general_problems/numbers/testing_numpy.py @@ -0,0 +1,32 @@ +#!/usr/bin/python +# mari von steinkirch @2013 +# steinkirch at gmail + +import numpy as np + +def testing_numpy(): + ''' tests many features of numpy ''' + ax = np.array([1,2,3]) + ay = np.array([3,4,5]) + print(ax) + print(ax*2) + print(ax+10) + print(np.sqrt(ax)) + print(np.cos(ax)) + print(ax-ay) + print(np.where(ax<2, ax, 10)) + + m = np.matrix([ax, ay, ax]) + print(m) + print(m.T) + + grid1 = np.zeros(shape=(10,10), dtype=float) + grid2 = np.ones(shape=(10,10), dtype=float) + print(grid1) + print(grid2) + print(grid1[1]+10) + print(grid2[:,2]*2) + +if __name__ == '__main__': + testing_numpy() + diff --git a/src/examples_in_my_book/general_problems/numbers/testing_numpy_speed.py b/src/examples_in_my_book/general_problems/numbers/testing_numpy_speed.py new file mode 100644 index 0000000..714b3b4 --- /dev/null +++ b/src/examples_in_my_book/general_problems/numbers/testing_numpy_speed.py @@ -0,0 +1,32 @@ +#!/usr/bin/python +# mari von steinkirch @2013 +# steinkirch at gmail + +import numpy +import time + +def trad_version(): + t1 = time.time() + X = range(10000000) + Y = range(10000000) + Z = [] + for i in range(len(X)): + Z.append(X[i] + Y[i]) + return time.time() - t1 + +def numpy_version(): + t1 = time.time() + X = numpy.arange(10000000) + Y = numpy.arange(10000000) + Z = X + Y + return time.time() - t1 + +if __name__ == '__main__': + print(trad_version()) + print(numpy_version()) + + +''' +3.23564291 +0.0714290142059 +''' diff --git a/src/examples_in_my_book/general_problems/numbers/testing_random.py b/src/examples_in_my_book/general_problems/numbers/testing_random.py new file mode 100644 index 0000000..dae8767 --- /dev/null +++ b/src/examples_in_my_book/general_problems/numbers/testing_random.py @@ -0,0 +1,27 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + +import random + +def testing_random(): + ''' testing the module random''' + values = [1, 2, 3, 4] + print(random.choice(values)) + print(random.choice(values)) + print(random.choice(values)) + print(random.sample(values, 2)) + print(random.sample(values, 3)) + + ''' shuffle in place ''' + random.shuffle(values) + print(values) + + ''' create random integers ''' + print(random.randint(0,10)) + print(random.randint(0,10)) + + +if __name__ == '__main__': + testing_random() + diff --git a/src/examples_in_my_book/general_problems/oop/HashTable.py b/src/examples_in_my_book/general_problems/oop/HashTable.py new file mode 100644 index 0000000..073b4b1 --- /dev/null +++ b/src/examples_in_my_book/general_problems/oop/HashTable.py @@ -0,0 +1,81 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + + +class HashTable: + ''' HashTable class that implements the Map abstract data type with 2 lists''' + def __init__(self): + self.size = 11 + self.slots = [None] * self.size + self.data = [None] * self.size + + def put(self,key,data): + hashvalue = self.hashfunction(key,len(self.slots)) + + if self.slots[hashvalue] == None: + self.slots[hashvalue] = key + self.data[hashvalue] = data + else: + if self.slots[hashvalue] == key: + self.data[hashvalue] = data + else: + nextslot = self.rehash(hashvalue,len(self.slots)) + while self.slots[nextslot] != None and \ + self.slots[nextslot] != key: + nextslot = self.rehash(nextslot,len(self.slots)) + + if self.slots[nextslot] == None: + self.slots[nextslot]=key + self.data[nextslot]=data + else: + self.data[nextslot] = data + + def hashfunction(self,key,size): + return key%size + + def rehash(self,oldhash,size): + return (oldhash+1)%size + + def get(self,key): + startslot = self.hashfunction(key,len(self.slots)) + + data = None + stop = False + found = False + position = startslot + while self.slots[position] != None and \ + not found and not stop: + if self.slots[position] == key: + found = True + data = self.data[position] + else: + position=self.rehash(position,len(self.slots)) + if position == startslot: + stop = True + return data + + + def __getitem__(self,key): + return self.get(key) + + def __setitem__(self,key,data): + self.put(key,data) + + + +def test_HashTable(module_name='this module'): + H = HashTable() + H[54]="buffy" + H[26]="xander" + H[17]="giles" + print(H.slots) + print(H.data) + + s = 'Tests in {name} have {con}!' + print(s.format(name=module_name, con='passed')) + + +if __name__ == '__main__': + test_HashTable() + diff --git a/src/examples_in_my_book/general_problems/oop/ShapeClass.py b/src/examples_in_my_book/general_problems/oop/ShapeClass.py new file mode 100644 index 0000000..055b726 --- /dev/null +++ b/src/examples_in_my_book/general_problems/oop/ShapeClass.py @@ -0,0 +1,62 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + + +import math + +class Point(object): + def __init__(self, x=0, y=0): # self: object reference to the object itself + self.x = x # data attribute + self.y = y + + def distance_from_origin(self): + return math.hypot(self.x, self.y) + + def __eq__(self, other): + return self.x == other.x and self.y == other.y + + def __repr__(self): + return "point ({0.x!r}, {0.y!r})".format(self) + + def __str__(self): # cannot be passed to eval + return "({0.x!r}, {0.y!r})".format(self) + + +class Circle(Point): + + def __init__(self, radius, x=0, y=0): + super().__init__(x,y) # creates and initializes self.x and self.y + self.radius = radius + + def edge_distance_from_origin(self): + return abs(self.distance_from_origin() - self.radius) + + def area(self): + return math.pi*(self.radius**2) + + def circumference(self): + return 2*math.pi*self.radius + + def __eq__(self, other): # let us avoid infinite recursion + return self.radius == other.radius and super().__eq__(other) + + def __repr__(self): + return "circle ({0.radius!r}, {0.x!r})".format(self) + + def __str__(self): + return repr(self) + + + + +if __name__ == '__main__': + a = Point(3,4) + print(a.distance_from_origin()) + c = Circle(3,2,1) + print(c) + print(c.circumference()) + print(c. edge_distance_from_origin()) + + + diff --git a/src/examples_in_my_book/general_problems/oop/__init__.py b/src/examples_in_my_book/general_problems/oop/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/examples_in_my_book/general_problems/oop/do_benchmark.py b/src/examples_in_my_book/general_problems/oop/do_benchmark.py new file mode 100644 index 0000000..bfe97a5 --- /dev/null +++ b/src/examples_in_my_book/general_problems/oop/do_benchmark.py @@ -0,0 +1,25 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + +import random +def benchmark(func): + import time + def wrapper(*args, **kwargs): + t = time.clock() + res = func(*args, **kwargs) + print("\t%s" % func.__name__, time.clock()-t) + return res + return wrapper + +@benchmark +def random_tree(n): + temp = [n for n in range(n)] + for i in range(n+1): + temp[random.choice(temp)] = random.choice(temp) + return temp + + +if __name__ == '__main__': + random_tree(10000) + diff --git a/src/examples_in_my_book/general_problems/oop/do_benchmark.py~ b/src/examples_in_my_book/general_problems/oop/do_benchmark.py~ new file mode 100644 index 0000000..b090009 --- /dev/null +++ b/src/examples_in_my_book/general_problems/oop/do_benchmark.py~ @@ -0,0 +1,25 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + +import random +def benchmark(func): + import time + def wrapper(*args, **kwargs): + t = time.clock() + res = func(*args, **kwargs) + print("\t%s" % func.__name__, time.clock()-t) + return res + return wrapper + +@benchmark +def random_tree(n): + temp = [n for n in range(n)] + for i in range(n+1): + temp[random.choice(temp)] = random.choice(temp) + return temp + + +if __name__ == '__main__': + random_tree(1000) + diff --git a/src/examples_in_my_book/general_problems/sets/__init__.py b/src/examples_in_my_book/general_problems/sets/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/examples_in_my_book/general_problems/sets/removing_duplicates_seq_.py b/src/examples_in_my_book/general_problems/sets/removing_duplicates_seq_.py new file mode 100644 index 0000000..9399ae3 --- /dev/null +++ b/src/examples_in_my_book/general_problems/sets/removing_duplicates_seq_.py @@ -0,0 +1,37 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + + +def removing_duplicates_seq(seq): + ''' if the values are hashable, we can use set and generators to remove duplicates + in a sequence ''' + seen = set() + for item in seq: + if item not in seen: + yield item + seen.add(item) + +def removing_duplicates_seq_not_hash(seq, key= None): + ''' if the item is not hashable, such as dictionaries ''' + seen = set() + for item in seq: + val = item if key is None else key[item] + if item not in seen: + yield item + seen.add(val) + + + +def test_removing_duplicates_seq(): + seq = [1, 2, 2, 2, 3, 3, 4, 4, 4] + dict = {'a':1, 'b':2, 'a':2, 'a':1} + assert(list(removing_duplicates_seq(seq)) == [1,2,3,4]) + assert(list(removing_duplicates_seq_not_hash(dict)) == ['a', 'b']) + print('Tests passed!'.center(20, '*')) + + +if __name__ == '__main__': + test_removing_duplicates_seq() + + diff --git a/src/examples_in_my_book/general_problems/sets/set_operations_dict.py b/src/examples_in_my_book/general_problems/sets/set_operations_dict.py new file mode 100644 index 0000000..af68b31 --- /dev/null +++ b/src/examples_in_my_book/general_problems/sets/set_operations_dict.py @@ -0,0 +1,39 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + +from collections import OrderedDict + +def set_operations_with_dict(): + ''' find common in 2 dictionaries ''' + ''' values() do not support set operations!''' + + pairs = [('a', 1), ('b',2), ('c',3)] + d1 = OrderedDict(pairs) + print(d1) # ('a', 1), ('b', 2), ('c', 3) + + d2 = {'a':1, 'c':2, 'd':3, 'e':4} + print(d2) # {'a': 1, 'c': 2, 'e': 4, 'd': 3} + + union = d1.keys() & d2.keys() + print(union) # {'a', 'c'} + + union_items = d1.items() & d2.items() + print(union_items) # {('a', 1)} + + subtraction1 = d1.keys() - d2.keys() + print(subtraction1) # {'b'} + + subtraction2 = d2.keys() - d1.keys() + print(subtraction2) # {'d', 'e'} + + subtraction_items = d1.items() - d2.items() + print(subtraction_items) # {('b', 2), ('c', 3)} + + ''' we can remove keys from a dict doing: ''' + d3 = {key:d2[key] for key in d2.keys() - {'c', 'd'}} + print(d3) {'a': 1, 'e': 4} + +if __name__ == '__main__': + set_operations_with_dict() + diff --git a/src/examples_in_my_book/general_problems/sets/set_operations_with_dict.py b/src/examples_in_my_book/general_problems/sets/set_operations_with_dict.py new file mode 100644 index 0000000..af68b31 --- /dev/null +++ b/src/examples_in_my_book/general_problems/sets/set_operations_with_dict.py @@ -0,0 +1,39 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + +from collections import OrderedDict + +def set_operations_with_dict(): + ''' find common in 2 dictionaries ''' + ''' values() do not support set operations!''' + + pairs = [('a', 1), ('b',2), ('c',3)] + d1 = OrderedDict(pairs) + print(d1) # ('a', 1), ('b', 2), ('c', 3) + + d2 = {'a':1, 'c':2, 'd':3, 'e':4} + print(d2) # {'a': 1, 'c': 2, 'e': 4, 'd': 3} + + union = d1.keys() & d2.keys() + print(union) # {'a', 'c'} + + union_items = d1.items() & d2.items() + print(union_items) # {('a', 1)} + + subtraction1 = d1.keys() - d2.keys() + print(subtraction1) # {'b'} + + subtraction2 = d2.keys() - d1.keys() + print(subtraction2) # {'d', 'e'} + + subtraction_items = d1.items() - d2.items() + print(subtraction_items) # {('b', 2), ('c', 3)} + + ''' we can remove keys from a dict doing: ''' + d3 = {key:d2[key] for key in d2.keys() - {'c', 'd'}} + print(d3) {'a': 1, 'e': 4} + +if __name__ == '__main__': + set_operations_with_dict() + diff --git a/src/examples_in_my_book/general_problems/sets/set_operations_with_lists.py b/src/examples_in_my_book/general_problems/sets/set_operations_with_lists.py new file mode 100644 index 0000000..f836d21 --- /dev/null +++ b/src/examples_in_my_book/general_problems/sets/set_operations_with_lists.py @@ -0,0 +1,37 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + +def difference(l1): + """ return the list with duplicate elements removed """ + return list(set(l1)) + +def intersection(l1, l2): + """ return the intersection of two lists """ + return list(set(l1) & set(l2)) + +def union(l1, l2): + """ return the union of two lists """ + return list(set(l1) | set(l2)) + + +def test_sets_operations_with_lists(): + l1 = [1,2,3,4,5,9,11,15] + l2 = [4,5,6,7,8] + l3 = [] + assert(difference(l1) == [1, 2, 3, 4, 5, 9, 11, 15]) + assert(difference(l2) == [8, 4, 5, 6, 7]) + assert(intersection(l1, l2) == [4,5]) + assert(union(l1, l2) == [1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 15]) + assert(difference(l3) == []) + assert(intersection(l3, l2) == l3) + assert(sorted(union(l3, l2)) == sorted(l2)) + print('Tests passed!') + + +if __name__ == '__main__': + test_sets_operations_with_lists() + + + + diff --git a/src/examples_in_my_book/general_problems/strings/__init__.py b/src/examples_in_my_book/general_problems/strings/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/examples_in_my_book/general_problems/strings/count_unique_words.py b/src/examples_in_my_book/general_problems/strings/count_unique_words.py new file mode 100644 index 0000000..9ab81a2 --- /dev/null +++ b/src/examples_in_my_book/general_problems/strings/count_unique_words.py @@ -0,0 +1,24 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + +import string +import sys + +def count_unique_word(): + ''' list every word and number of times in alphabetical order for input files ''' + words = {} # create an empty dictionary + strip = string.whitespace + string.punctuation + string.digits + "\"'" + for filename in sys.argv[1:]: + with open(filename) as file: + for line in file: + for word in line.lower().split(): + word = word.strip(strip) + if len(word) > 2: + words[word] = words.get(word,0) +1 + for word in sorted(words): + print("'{0}' occurs {1} times.".format(word, words[word])) + + +count_unique_word() + diff --git a/src/examples_in_my_book/general_problems/strings/find_all_permutations_string.py b/src/examples_in_my_book/general_problems/strings/find_all_permutations_string.py new file mode 100644 index 0000000..4c90e6f --- /dev/null +++ b/src/examples_in_my_book/general_problems/strings/find_all_permutations_string.py @@ -0,0 +1,47 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + + + +def find_all_permutations_string(str1): + ''' print all the permutations of a given string, recursive so runtime is O(n*(n-1)) ''' + res = [] + if len(str1) == 1: + res = [str1] + else: + for i, c in enumerate(str1): + for perm in find_all_permutations_string(str1[:i] + str1[i+1:]): + res += [c + perm] + return res + + +def find_all_permutations_string_crazy(str1): + ''' crazy simple way of find all the permutations of a string, also using recursion''' + return [str1] if len(str1) == 1 else [c + perm for i, c in enumerate(str1) for perm in find_all_permutations_string_crazy(str1[:i]+str1[i+1:])] + + +def find_all_permutations_string_stdlib(str1): + ''' find all the permutations of a string just using the available packages ''' + from itertools import permutations + perms = [''.join(p) for p in permutations(str1)] + return perms + + +def test_find_all_permutations_string(): + str1 = "abc" + perm_set = {'abc', 'bac', 'cab', 'acb', 'cba', 'bca'} + assert(set(find_all_permutations_string(str1)) == perm_set) + assert(set(find_all_permutations_string_crazy(str1)) == perm_set) + assert(set(find_all_permutations_string_stdlib(str1)) == perm_set) + print('Tests passed!') + + +if __name__ == '__main__': + test_find_all_permutations_string() + + + + + + diff --git a/src/examples_in_my_book/general_problems/strings/find_edit_distance.py b/src/examples_in_my_book/general_problems/strings/find_edit_distance.py new file mode 100644 index 0000000..f709424 --- /dev/null +++ b/src/examples_in_my_book/general_problems/strings/find_edit_distance.py @@ -0,0 +1,34 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + + +def find_edit_distance(str1, str2): + ''' computes the edit distance between two strings ''' + m = len(str1) + n = len(str2) + diff = lambda c1, c2: 0 if c1 == c2 else 1 + E = [[0] * (n + 1) for i in range(m + 1)] + for i in range(m + 1): + E[i][0] = i + for j in range(1, n + 1): + E[0][j] = j + for i in range(1, m + 1): + for j in range(1, n + 1): + E[i][j] = min(E[i-1][j] + 1, E[i][j-1] + 1, E[i-1][j-1] + diff(str1[i-1], str2[j-1])) + return E[m][n] + + +def test_find_edit_distance(): + s = 'sunday' + t = 'saturday' + assert(find_edit_distance(s, t) == 3) + print('Tests passed!') + + +if __name__ == '__main__': + test_find_edit_distance() + + + + diff --git a/src/examples_in_my_book/general_problems/strings/find_palindrome_rec.py b/src/examples_in_my_book/general_problems/strings/find_palindrome_rec.py new file mode 100644 index 0000000..ec79fa0 --- /dev/null +++ b/src/examples_in_my_book/general_problems/strings/find_palindrome_rec.py @@ -0,0 +1,29 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + + +def find_palindrome_rec(s): + ''' recursive way of checking whether a str is a palindrome ''' + if len(s) > 1: + if s[0] != s[-1]: return False + else: find_palindrome_rec(s[1:-1]) + return True + + +def test_find_palindrome_rec(module_name='this module'): + str1 = 'radar' + str2 = "" + str3 = 'x' + str4 = 'hello' + assert(find_palindrome_rec(str1) == True) + assert(find_palindrome_rec(str2) == True) + assert(find_palindrome_rec(str3) == True) + assert(find_palindrome_rec(str4) == False) + s = 'Tests in {name} have {con}!' + print(s.format(name=module_name, con='passed')) + + +if __name__ == '__main__': + test_find_palindrome_rec() + diff --git a/src/examples_in_my_book/general_problems/strings/find_subst_in_str.py b/src/examples_in_my_book/general_problems/strings/find_subst_in_str.py new file mode 100644 index 0000000..6caff9b --- /dev/null +++ b/src/examples_in_my_book/general_problems/strings/find_subst_in_str.py @@ -0,0 +1,41 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + + +def find_subst_in_str(str1, set1): + sub_str1 = '' + found = False + + while set1: + for c in str1: + if c in set1: + set1.remove(c) + found = True + if found == True: + sub_str1 += c + if len(set1) == 0: found = False + return sub_str1 + + + +def test_find_subst_in_str(module_name='this module'): + str1 = 'ydxahbcscdk' + + set1 = {'a','b','c','d'} + result = 'dxahbc' + + assert( find_subst_in_str(str1, set1)==result) + + set2 = {'a','b','c'} + result2 = 'ahbc' + assert( find_subst_in_str(str1, set2)==result2) + + + s = 'Tests in {name} have {con}!' + print(s.format(name=module_name, con='passed')) + + +if __name__ == '__main__': + test_find_subst_in_str() + diff --git a/src/examples_in_my_book/general_problems/strings/find_subst_in_str.py~ b/src/examples_in_my_book/general_problems/strings/find_subst_in_str.py~ new file mode 100644 index 0000000..2b0294a --- /dev/null +++ b/src/examples_in_my_book/general_problems/strings/find_subst_in_str.py~ @@ -0,0 +1,41 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + + +def find_subst_in_str(str1, set1): + sub_str1 = '' + found = False + + while set1: + for c in str1): + if c in set1: + set1.remove(c) + found = True + if found == True: + sub_str1 += c + if len(set1) == 0: found = False + return sub_str1 + + + +def test_find_subst_in_str(module_name='this module'): + str1 = 'ydxahbcscdk' + + set1 = {'a','b','c','d'} + result = 'dxahbc' + + assert( find_subst_in_str(str1, set1)==result) + + set2 = {'a','b','c'} + result2 = 'ahbc' + assert( find_subst_in_str(str1, set2)==result2) + + + s = 'Tests in {name} have {con}!' + print(s.format(name=module_name, con='passed')) + + +if __name__ == '__main__': + test_find_subst_in_str() + diff --git a/src/examples_in_my_book/general_problems/strings/longest_common_substring.py b/src/examples_in_my_book/general_problems/strings/longest_common_substring.py new file mode 100644 index 0000000..13aa0af --- /dev/null +++ b/src/examples_in_my_book/general_problems/strings/longest_common_substring.py @@ -0,0 +1,32 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + + + +def longest_common_substring(str1, str2): + ''' find the largest commom substring from 2 strings ''' + m = [[0 for i in range(len(str2) + 1)] for k in range(len(str1) + 1)] + lcs = None + max_len = 0 + for y in range(1, len(str1) + 1): + for x in range(1, len(str2) + 1): + m[y][x] = m[y - 1][x - 1] + 1 if (str1[y - 1] == str2[x - 1]) else 0 + + if m[y][x] > max_len: + max_len = m[y][x] + lcs = str1[(y - max_len):y] + return max_len, lcs + + +def test_longest_common_substring(): + str1 = 'buffy is a vampire slayer' + str2 = 'aaas bampires vslay' + assert(longest_common_substring(str1, str2) == (6, 'ampire')) + print('Tests passed!') + + +if __name__ == '__main__': + test_longest_common_substring() + + diff --git a/src/examples_in_my_book/general_problems/strings/reverse_string_inplace_rec.py b/src/examples_in_my_book/general_problems/strings/reverse_string_inplace_rec.py new file mode 100644 index 0000000..3157a50 --- /dev/null +++ b/src/examples_in_my_book/general_problems/strings/reverse_string_inplace_rec.py @@ -0,0 +1,33 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + + +def reverse_string_inplace_rec(s): + ''' takes a string and returns its reverse''' + if s: + s = s[-1] + reverse_string_inplace_rec(s[:-1]) + return s + +def reverse_string_inplace(s): + s = s[::-1] + if s[0] == '\0': + s = s[1:] + s += '\0' + return s + + + +def test_reverse_string_inplace_rec(module_name='this module'): + s = 'hello' + s2 = 'buffy\0' + assert(reverse_string_inplace(s) == 'olleh') + assert(reverse_string_inplace(s2) == 'yffub\0') + assert(reverse_string_inplace_rec(s) == 'olleh') + + s = 'Tests in {name} have {con}!' + print(s.format(name=module_name, con='passed')) + +if __name__ == '__main__': + test_reverse_string_inplace_rec() + diff --git a/src/examples_in_my_book/general_problems/strings/reverse_string_inplace_rec.py~ b/src/examples_in_my_book/general_problems/strings/reverse_string_inplace_rec.py~ new file mode 100644 index 0000000..06ed13d --- /dev/null +++ b/src/examples_in_my_book/general_problems/strings/reverse_string_inplace_rec.py~ @@ -0,0 +1,34 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + + +def reverse_string_inplace_rec(s): + ''' takes a string and returns its reverse''' + if s: + s = s[-1] + reverse_string_inplace_rec(s[:-1]) + return s + +def reverse_string_inplace(s): + s = s[::-1] + if s[0] == '\0': + s = s[1:] + s += '\0' + print(s) + return s + + + +def test_reverse_string_inplace_rec(module_name='this module'): + s = 'hello' + s2 = 'buffy\0' + assert(reverse_string_inplace(s) == 'olleh') + assert(reverse_string_inplace(s2) == 'yffub\0') + assert(reverse_string_inplace_rec(s) == 'olleh') + + s = 'Tests in {name} have {con}!' + print(s.format(name=module_name, con='passed')) + +if __name__ == '__main__': + test_reverse_string_inplace_rec() + diff --git a/src/examples_in_my_book/general_problems/strings/reversing_words_setence.py b/src/examples_in_my_book/general_problems/strings/reversing_words_setence.py new file mode 100644 index 0000000..cb392c1 --- /dev/null +++ b/src/examples_in_my_book/general_problems/strings/reversing_words_setence.py @@ -0,0 +1,23 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + + +def reversing_words_setence(str1): + ''' reverse the words in a sentence''' + words = str1.split() + rev_set = " ".join(reversed(words)) + return rev_set + + +def test_reversing_words_setence(module_name='this module'): + str1 = "Buffy is a Vampire Slayer" + assert(reversing_words_setence(str1) == "Slayer Vampire a is Buffy") + + s = 'Tests in {name} have {con}!' + print(s.format(name=module_name, con='passed')) + + +if __name__ == '__main__': + test_reversing_words_setence() + diff --git a/src/examples_in_my_book/general_problems/strings/reversing_words_setence.py~ b/src/examples_in_my_book/general_problems/strings/reversing_words_setence.py~ new file mode 100644 index 0000000..fb3c014 --- /dev/null +++ b/src/examples_in_my_book/general_problems/strings/reversing_words_setence.py~ @@ -0,0 +1,23 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + + +def reversing_words_setence(str1): + ''' reverse the words in a setence in a string''' + words = str1.split() + rev_set = " ".join(reversed(words)) + return rev_set + + +def test_reversing_words_setence(module_name='this module'): + str1 = "Buffy is a Vampire Slayer" + assert(reversing_words_setence(str1) == "Slayer Vampire a is Buffy") + + s = 'Tests in {name} have {con}!' + print(s.format(name=module_name, con='passed')) + + +if __name__ == '__main__': + test_reversing_words_setence() + diff --git a/src/examples_in_my_book/general_problems/tuples/namedtuple_example.py b/src/examples_in_my_book/general_problems/tuples/namedtuple_example.py new file mode 100644 index 0000000..c2b23d1 --- /dev/null +++ b/src/examples_in_my_book/general_problems/tuples/namedtuple_example.py @@ -0,0 +1,17 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + +from collections import namedtuple + +def namedtuple_example(): + ''' show some examples for namedtuple ''' + sunnydale = namedtuple('name', ['job', 'age']) + buffy = sunnydale('slayer', '17') + print(buffy.job) + + +if __name__ == '__main__': + namedtuple_example() + + diff --git a/src/examples_in_my_book/searching/__init__.py b/src/examples_in_my_book/searching/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/examples_in_my_book/searching/binary_search.py b/src/examples_in_my_book/searching/binary_search.py new file mode 100644 index 0000000..404a59e --- /dev/null +++ b/src/examples_in_my_book/searching/binary_search.py @@ -0,0 +1,49 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + + + +def binary_search(seq, key): + ''' binary search iterative algorithm ''' + ''' observe that the index is returned ''' + hi = len(seq) + lo = 0 + while lo < hi: + mid = (hi+lo) // 2 + if seq[mid] == key: + return mid + elif key < seq[mid]: + hi = mid + else: + lo = mid + 1 + return None + + +def binary_search_rec(seq, key, lo=0, hi=None): + ''' binary search recursive algorithm ''' + hi = hi or len(seq) + if hi < lo: return None + mid = (hi + lo) // 2 + if seq[mid] == key: + return mid + elif seq[mid] < key: + return binary_search_rec(seq, key, mid + 1, hi) + else: + return binary_search_rec(seq, key, lo, mid - 1) + + +def test_binary_search(): + seq = [1,2,5,6,7,10,12,12,14,15] + key = 6 + assert(binary_search(seq, key) == 3) + assert(binary_search_rec(seq, key) == 3) + print('Tests passed!') + + +if __name__ == '__main__': + test_binary_search() + + + + diff --git a/src/examples_in_my_book/searching/binary_search.py~ b/src/examples_in_my_book/searching/binary_search.py~ new file mode 100644 index 0000000..055e3ba --- /dev/null +++ b/src/examples_in_my_book/searching/binary_search.py~ @@ -0,0 +1,47 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + + + +def binary_search(seq, key, lo=0, hi=None): + ''' binary search iterative algorithm ''' + hi = hi or len(seq) + while lo < hi: + mid = (hi+lo) // 2 + if seq[mid] == key: + return mid + elif key < seq[mid]: + hi = mid + else: + lo = mid + 1 + return None + + +def binary_search_rec(seq, key, lo=0, hi=None): + ''' binary search recursive algorithm ''' + hi = hi or len(seq) + if (hi - lo) < 0: return None + mid = lo + ((hi - lo) // 2) + if seq[mid] == key: + return mid + elif seq[mid] < key: + return binary_search_rec(seq, key, mid + 1, hi) + else: + return binary_search_rec(seq, key, lo, mid - 1) + + +def test_binary_search(): + seq = [1,2,5,6,7,10,12,12,14,15] + key = 6 + assert(binary_search(seq, key) == 3) + assert(binary_search_rec(seq, key) == 3) + print('Tests passed!') + + +if __name__ == '__main__': + test_binary_search() + + + + diff --git a/src/examples_in_my_book/searching/find_max_unimodal_array.py b/src/examples_in_my_book/searching/find_max_unimodal_array.py new file mode 100644 index 0000000..04c07c5 --- /dev/null +++ b/src/examples_in_my_book/searching/find_max_unimodal_array.py @@ -0,0 +1,32 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + + +def find_max_unimodal_array(A): + if len(A) <= 2 : return None + left = 0 + right = len(A)-1 + while right > left +1: + mid = (left + right)//2 + if A[mid] > A[mid-1] and A[mid] > A[mid+1]: + return A[mid] + elif A[mid] > A[mid-1] and A[mid] < A[mid+1]: + left = mid + else: + right = mid + return None + + +def test_find_max_unimodal_array(): + seq = [1, 2, 5, 6, 7, 10, 12, 9, 8, 7, 6] + assert(find_max_unimodal_array(seq) == 12) + print('Tests passed!') + + +if __name__ == '__main__': + test_find_max_unimodal_array() + + + + diff --git a/src/examples_in_my_book/searching/find_sqrt_bin_search.py b/src/examples_in_my_book/searching/find_sqrt_bin_search.py new file mode 100644 index 0000000..99fec1c --- /dev/null +++ b/src/examples_in_my_book/searching/find_sqrt_bin_search.py @@ -0,0 +1,35 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + + + +def find_sqrt_bin_search(n, error=0.001): + ''' implement square root using binary search ''' + lower = n < 1 and n or 1 + upper = n < 1 and 1 or n + mid = lower + (upper - lower) / 2.0 + square = mid * mid + while abs(square - n) > error: + if square < n: + lower = mid + else: + upper = mid + mid = lower + (upper - lower) / 2.0 + square = mid * mid + return mid + + +def test_ind_sqrt_bin_search(): + number = 9 + assert(find_sqrt_bin_search(number) == 3) + print('Tests passed!') + + +if __name__ == '__main__': + test_ind_sqrt_bin_search() + + + + + diff --git a/src/examples_in_my_book/searching/find_time_occurence_list.py b/src/examples_in_my_book/searching/find_time_occurence_list.py new file mode 100644 index 0000000..17c3137 --- /dev/null +++ b/src/examples_in_my_book/searching/find_time_occurence_list.py @@ -0,0 +1,50 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + + +def binary_serch_counting(lst1, k, lo=0, hi=None): + if hi is None: hi = len(lst1) + while lo < hi: + mid = (lo+hi)//2 + midval = lst1[mid] + if midval < k: + lo = mid +1 + elif midval > k: + hi = mid + else: + return mid + return -1 + + +def find_time_occurrence_list(seq, k): + """ find how many times a k element appears in a sorted list. One way of doing this is using + collections.OrderedDict to no mess with the sorting, and add entries for every count. This + should be O(n). It has a O(1) space complexity since the size of the dict is fixed. + Another way, since the array is sorted, it to use binary search, since this is only O(logn). + """ + index_some_k = binary_serch_counting(seq, k) + count = 1 + sizet = len(seq) + + for i in range(index_some_k+1, sizet): # go up + if seq[i] == k: count +=1 + else: break + + for i in range(index_some_k-1, -1, -1): # go down + if seq[i] == k: count +=1 + else: break + + return count + + +def test_find_time_occurrence_list(): + seq = [1,2,2,2,2,2,2,5,6,6,7,8,9] + k = 2 + assert(find_time_occurrence_list(seq, k) == 6) + print('Tests passed!') + + +if __name__ == '__main__': + test_find_time_occurrence_list() + diff --git a/src/examples_in_my_book/searching/interserction_two_arrays.py b/src/examples_in_my_book/searching/interserction_two_arrays.py new file mode 100644 index 0000000..0fa91cf --- /dev/null +++ b/src/examples_in_my_book/searching/interserction_two_arrays.py @@ -0,0 +1,77 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + +''' using sets ''' + +def intersection_two_arrays_sets(seq1, seq2): + ''' find the intersection of two arrays using set proprieties ''' + set1 = set(seq1) + set2 = set(seq2) + return set1.intersection(set2) #same as list(set1 & set2 + + + +''' using merge sort ''' + +def intersection_two_arrays_ms(seq1, seq2): + ''' find the intersection of two arrays using merge sort ''' + res = [] + while seq1 and seq2: + if seq1[-1] == seq2[-1]: + res.append(seq1.pop()) + seq2.pop() + elif seq1[-1] > seq2[-1]: + seq1.pop() + else: + seq2.pop() + res.reverse() + return res + + + + +''' using binary search ''' + +def binary_search(seq, key, lo=0, hi=None): + ''' binary search iterative algorithm ''' + hi = hi or len(seq) + while lo < hi: + mid = (hi+lo) // 2 + if seq[mid] == key: + return True + elif key > seq[mid]: + lo = mid + 1 + else: + hi = mid + return None + +def intersection_two_arrays_bs(seq1, seq2): + ''' if A small and B is too large, we can do a binary search on each entry in B ''' + ''' only works if sorted and the small sequence has not larger nmbers!!!''' + if len(seq1) > len(seq2): seq, key = seq1, seq2 + else: seq, key = seq2, seq1 + + intersec = [] + for item in key: + if binary_search(seq, item): + intersec.append(item) + return intersec + + + +def test_intersection_two_arrays(module_name='this module'): + seq1 = [1,2,3,5,7,8] + seq2 = [3,5,6] + + assert(set(intersection_two_arrays_sets(seq1,seq2)) == set([3,5])) + assert(intersection_two_arrays_bs(seq1,seq2) == [3,5]) + assert(intersection_two_arrays_ms(seq1,seq2) == [3,5]) + + s = 'Tests in {name} have {con}!' + print(s.format(name=module_name, con='passed')) + + +if __name__ == '__main__': + test_intersection_two_arrays() + diff --git a/src/examples_in_my_book/searching/ordered_sequential_search.py b/src/examples_in_my_book/searching/ordered_sequential_search.py new file mode 100644 index 0000000..a252986 --- /dev/null +++ b/src/examples_in_my_book/searching/ordered_sequential_search.py @@ -0,0 +1,35 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + + +def ordered_sequential_search(seq, n): + ''' an example of sequential search in an ordered seq: + it improves the performance if the item is not present ''' + item = 0 + for item in seq: + if item > n: return False + if item == n: return True + return False + + +def test_ordered_sequential_search(module_name='this module'): + seq = [1, 2, 4, 5, 6, 8, 10] + n1 = 10 + n2 = 7 + assert(ordered_sequential_search(seq, n1) == True) + assert(ordered_sequential_search(seq, n2) == False) + + s = 'Tests in {name} have {con}!' + print(s.format(name=module_name, con='passed')) + + +if __name__ == '__main__': + test_ordered_sequential_search() + + +""" +Case Best Case Worst Case Average Case +item is present 1 n n/2 +item not present 1 n n/2 +""" diff --git a/src/examples_in_my_book/searching/searching_in_a_matrix.py b/src/examples_in_my_book/searching/searching_in_a_matrix.py new file mode 100644 index 0000000..d3cdfbd --- /dev/null +++ b/src/examples_in_my_book/searching/searching_in_a_matrix.py @@ -0,0 +1,49 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + +import numpy + +def searching_in_a_matrix(m1, value): + """ 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. + The naive brute force solution scan all numbers and cost O(nm). However, since the numbers are + already sorted, the matrix can be viewed as a 1D sorted array. The binary search algorithm is + suitable. The efficience is O(logmn).""" + + rows = len(m1) + cols = len(m1[0]) + lo = 0 + hi = rows*cols + while lo < hi: + mid = (lo + hi)//2 + row = mid//cols + col = mid%cols + v = m1[row][col] + if v == value: return True + elif v > value: hi = mid + else: lo = mid+1 + return False + + + +def test_searching_in_a_matrix(): + a = [[1,3,5],[7,9,11],[13,15,17]] + b = numpy.array([(1,2),(3,4)]) + assert(searching_in_a_matrix(a, 13) == True) + assert(searching_in_a_matrix(a, 14) == False) + assert(searching_in_a_matrix(b, 3) == True) + assert(searching_in_a_matrix(b, 5) == False) + print('Tests passed!') + + +if __name__ == '__main__': + test_searching_in_a_matrix() + + + + + + + + diff --git a/src/examples_in_my_book/searching/sequential_search.py b/src/examples_in_my_book/searching/sequential_search.py new file mode 100644 index 0000000..9cc2947 --- /dev/null +++ b/src/examples_in_my_book/searching/sequential_search.py @@ -0,0 +1,32 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + + +def sequential_search(seq, n): + ''' an example of sequential search (for items stored in a collection) ''' + for item in seq: + if item == n: return True + return False + + +def test_sequential_search(module_name='this module'): + seq = [1, 5, 6, 8, 3] + n1 = 5 + n2 = 7 + assert(sequential_search(seq, n1) == True) + assert(sequential_search(seq, n2) == False) + + s = 'Tests in {name} have {con}!' + print(s.format(name=module_name, con='passed')) + + +if __name__ == '__main__': + test_sequential_search() + + +""" +Case Best Case Worst Case Average Case +item is present 1 n n2 +item is not present n n n +"""" diff --git a/src/examples_in_my_book/sorting/__init__.py b/src/examples_in_my_book/sorting/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/examples_in_my_book/sorting/bubble_sort.py b/src/examples_in_my_book/sorting/bubble_sort.py new file mode 100644 index 0000000..c48fb7b --- /dev/null +++ b/src/examples_in_my_book/sorting/bubble_sort.py @@ -0,0 +1,29 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + + +def bubble_sort(seq): + ''' implement bubble sort, a O(n^2) not efficient algorithm''' + size = len(seq) -1 + for num in range(size, 0, -1): + for i in range(num): + if seq[i] > seq[i+1]: + temp = seq[i] + seq[i] = seq[i+1] + seq[i+1] = temp + return seq + + + +def test_bubble_sort(module_name='this module'): + seq = [4, 5, 2, 1, 6, 2, 7, 10, 13, 8] + assert(bubble_sort(seq) == sorted(seq)) + + s = 'Tests in {name} have {con}!' + print(s.format(name=module_name, con='passed')) + + +if __name__ == '__main__': + test_bubble_sort() + diff --git a/src/examples_in_my_book/sorting/count_sort.py b/src/examples_in_my_book/sorting/count_sort.py new file mode 100644 index 0000000..8288237 --- /dev/null +++ b/src/examples_in_my_book/sorting/count_sort.py @@ -0,0 +1,27 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + + +from collections import defaultdict + +def count_sort_dict(a): + ''' an example of counting sort using default dictionaries ''' + b, c = [], defaultdict(list) + for x in a: + c[x].append(x) # we could have used key = lambda x:x + for k in range(min(c), max(c) + 1): + b.extend(c[k]) + return b + + +def test_count_sort(): + seq = [3, 5, 2, 6, 8, 1, 0, 3, 5, 6, 2, 5, 4, 1, 5, 3] + assert(count_sort_dict(seq) == sorted(seq)) + print('Tests passed!') + + +if __name__ == '__main__': + test_count_sort() + + diff --git a/src/examples_in_my_book/sorting/find_k_largest_seq_quickselect.py b/src/examples_in_my_book/sorting/find_k_largest_seq_quickselect.py new file mode 100644 index 0000000..820a8d7 --- /dev/null +++ b/src/examples_in_my_book/sorting/find_k_largest_seq_quickselect.py @@ -0,0 +1,61 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + +import random + +def swap(A, x, y): + tmp = A[x] + A[x] = A[y] + A[y] = tmp + + +def qselect(A, k, left=None, right=None): + left = left or 0 + right = right or len(A) - 1 + pivot = random.randint(left, right) + pivotVal = A[pivot] + + # Move pivot out of the sorting range + swap(A, pivot, right) + swapIndex, i = left, left + while i <= right - 1: + if A[i] < pivotVal: + swap(A, i, swapIndex) + swapIndex += 1 + i += 1 + + # Move pivot to final position + swap(A, right, swapIndex) + + # Check if pivot matches, else recurse on the correct half + rank = len(A) - swapIndex + if k == rank: + return A[swapIndex] + elif k < rank: + return qselect(A, k, left=swapIndex+1, right=right) + else: + return qselect(A, k, left=left, right=swapIndex-1) + + + +def find_k_largest_seq_quickselect(seq, k): + ''' perform quick select to get kth element, and find all elements larger ''' + kth_largest = qselect(seq, k) + result = [] + for item in seq: + if item >= kth_largest: + result.append(item) + return result + + + +def test_find_k_largest_seq_quickselect(): + seq = [3, 10, 4, 5, 1, 8, 9, 11, 5] + k = 2 + assert(find_k_largest_seq_quickselect(seq,k) == [10, 11]) + + +if __name__ == '__main__': + test_find_k_largest_seq_quickselect() + diff --git a/src/examples_in_my_book/sorting/gnome_sort.py b/src/examples_in_my_book/sorting/gnome_sort.py new file mode 100644 index 0000000..a9f4b41 --- /dev/null +++ b/src/examples_in_my_book/sorting/gnome_sort.py @@ -0,0 +1,35 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + + +from do_benchmark import benchmark + +@benchmark +def gnome_sort(seq): + ''' sort a sequence using the gnome sort alg ''' + i = 0 + while i < len(seq): + if i ==0 or seq[i-1] <= seq[i]: + i += 1 + else: + seq[i], seq[i-1] = seq[i-1], seq[i] + i -= 1 + return seq + + +def test_gnome_sort(): + seq = [3, 5, 2, 6, 8, 1, 0, 3, 5, 6, 2, 5, 4, 1, 5, 3] + assert(gnome_sort(seq) == sorted(seq)) + print('Tests passed!') + + +if __name__ == '__main__': + test_gnome_sort() + + + + + + + diff --git a/src/examples_in_my_book/sorting/heap.py b/src/examples_in_my_book/sorting/heap.py new file mode 100644 index 0000000..cf1d890 --- /dev/null +++ b/src/examples_in_my_book/sorting/heap.py @@ -0,0 +1,44 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + +class Heap(object): + def __init__(self, data): + self.data = data + for i in range(len(data)/2, -1, -1): + self.__max_heapify__(i) + + + def parent(self, i): + return i >> 1 + + + def left_child(self, i): + return (i << 1) + 1 + + + def right_child(self, i): + return (i << 1) + 2 # +2 instead of +1 because it's 0-indexed. + + + def __max_heapify__(self, i): + largest = i + left = self.left_child(i) + right = self.right_child(i) + n = len(self.data) + largest = (left < n and self.data[left] > self.data[i]) and left or i + largest = (right < n and self.data[right] > self.data[largest]) and right or largest + if i != largest: + self.data[i], self.data[largest] = self.data[largest], self.data[i] + self.__max_heapify__(largest) + + + def extract_max(self): + n = len(self.data) + max_element = self.data[0] + self.data[0] = self.data[n - 1] + self.data = self.data[:n - 1] + self.__max_heapify__(0) + return max_element + + diff --git a/src/examples_in_my_book/sorting/heap_sort.py~ b/src/examples_in_my_book/sorting/heap_sort.py~ new file mode 100644 index 0000000..d6f9e54 --- /dev/null +++ b/src/examples_in_my_book/sorting/heap_sort.py~ @@ -0,0 +1,48 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + +import heapq + +def heap_sort_api(seq): + ''' heap sort with Python's heapq ''' + h = [] + for value in seq: + heapq.heappush(h, value) + return [heapq.heappop(h) for i in range(len(h))] + + +def heap_sort(seq): + ''' heap sort explicitly ''' + for start in range((len(seq)-2)//2, -1, -1): + siftdown(seq, start, len(seq)-1) + for end in range(len(seq)-1, 0, -1): + seq[end], seq[0] = seq[0], seq[end] + siftdown(seq, 0, end - 1) + return seq + +def siftdown(seq, start, end): + root = start + while True: + child = root * 2 + 1 + if child > end: break + if child + 1 <= end and seq[child] < seq[child + 1]: + child += 1 + if seq[root] < seq[child]: + seq[root], seq[child] = seq[child], seq[root] + root = child + else: + break + + + +def test_heap_sort(): + seq = [3, 5, 2, 6, 8, 1, 0, 3, 5, 6, 2] + assert(heap_sort_api(seq) == sorted(seq)) + assert(heap_sort(seq) == sorted(seq)) + print('Tests passed!') + + +if __name__ == '__main__': + test_heap_sort() + diff --git a/src/examples_in_my_book/sorting/heap_sort1.py b/src/examples_in_my_book/sorting/heap_sort1.py new file mode 100644 index 0000000..7f174bb --- /dev/null +++ b/src/examples_in_my_book/sorting/heap_sort1.py @@ -0,0 +1,23 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + +import heapq + +def heap_sort1(seq): + ''' heap sort with Python's heapq ''' + h = [] + for value in seq: + heapq.heappush(h, value) + return [heapq.heappop(h) for i in range(len(h))] + + +def test_heap_sort1(): + seq = [3, 5, 2, 6, 8, 1, 0, 3, 5, 6, 2] + assert(heap_sort1(seq) == sorted(seq)) + print('Tests passed!') + + +if __name__ == '__main__': + test_heap_sort1() + diff --git a/src/examples_in_my_book/sorting/heap_sort2.py b/src/examples_in_my_book/sorting/heap_sort2.py new file mode 100644 index 0000000..e7df361 --- /dev/null +++ b/src/examples_in_my_book/sorting/heap_sort2.py @@ -0,0 +1,24 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + +from heap import Heap + +def heap_sort2(seq): + heap = Heap(seq) + + res = [] + for i in range(len(seq)): + res.insert(0, heap.extract_max()) + + return res + + +def test_heap_sort2(): + seq = [3, 5, 2, 6, 8, 1, 0, 3, 5, 6, 2] + assert(heap_sort2(seq) == sorted(seq)) + print('Tests passed!') + + +if __name__ == '__main__': + test_heap_sort2() diff --git a/src/examples_in_my_book/sorting/heap_sort3.py b/src/examples_in_my_book/sorting/heap_sort3.py new file mode 100644 index 0000000..9e4ff2a --- /dev/null +++ b/src/examples_in_my_book/sorting/heap_sort3.py @@ -0,0 +1,36 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + +def heap_sort3(seq): + for start in range((len(seq)-2)//2, -1, -1): + siftdown(seq, start, len(seq)-1) + for end in range(len(seq)-1, 0, -1): + seq[end], seq[0] = seq[0], seq[end] + siftdown(seq, 0, end - 1) + return seq + +def siftdown(seq, start, end): + root = start + while True: + child = root * 2 + 1 + if child > end: break + if child + 1 <= end and seq[child] < seq[child + 1]: + child += 1 + if seq[root] < seq[child]: + seq[root], seq[child] = seq[child], seq[root] + root = child + else: + break + + + +def test_heap_sort(): + seq = [3, 5, 2, 6, 8, 1, 0, 3, 5, 6, 2] + assert(heap_sort3(seq) == sorted(seq)) + print('Tests passed!') + + +if __name__ == '__main__': + test_heap_sort3() + diff --git a/src/examples_in_my_book/sorting/heap_sort_1.py~ b/src/examples_in_my_book/sorting/heap_sort_1.py~ new file mode 100644 index 0000000..d6f9e54 --- /dev/null +++ b/src/examples_in_my_book/sorting/heap_sort_1.py~ @@ -0,0 +1,48 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + +import heapq + +def heap_sort_api(seq): + ''' heap sort with Python's heapq ''' + h = [] + for value in seq: + heapq.heappush(h, value) + return [heapq.heappop(h) for i in range(len(h))] + + +def heap_sort(seq): + ''' heap sort explicitly ''' + for start in range((len(seq)-2)//2, -1, -1): + siftdown(seq, start, len(seq)-1) + for end in range(len(seq)-1, 0, -1): + seq[end], seq[0] = seq[0], seq[end] + siftdown(seq, 0, end - 1) + return seq + +def siftdown(seq, start, end): + root = start + while True: + child = root * 2 + 1 + if child > end: break + if child + 1 <= end and seq[child] < seq[child + 1]: + child += 1 + if seq[root] < seq[child]: + seq[root], seq[child] = seq[child], seq[root] + root = child + else: + break + + + +def test_heap_sort(): + seq = [3, 5, 2, 6, 8, 1, 0, 3, 5, 6, 2] + assert(heap_sort_api(seq) == sorted(seq)) + assert(heap_sort(seq) == sorted(seq)) + print('Tests passed!') + + +if __name__ == '__main__': + test_heap_sort() + diff --git a/src/examples_in_my_book/sorting/heap_sort_2.py~ b/src/examples_in_my_book/sorting/heap_sort_2.py~ new file mode 100644 index 0000000..de663cf --- /dev/null +++ b/src/examples_in_my_book/sorting/heap_sort_2.py~ @@ -0,0 +1,8 @@ +def heapsort(seq): + heap = Heap(seq) + + res = [] + for i in range(len(seq)): + res.insert(0, heap.extract_max()) + + return res diff --git a/src/examples_in_my_book/sorting/insertion_sort.py b/src/examples_in_my_book/sorting/insertion_sort.py new file mode 100644 index 0000000..3dd522e --- /dev/null +++ b/src/examples_in_my_book/sorting/insertion_sort.py @@ -0,0 +1,44 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + + + +def insertion_sort(seq): + ''' sort a sequence using the insertion sort alg ''' + for i in range(1, len(seq)): + j = i + while j > 0 and seq[j-1] > seq[j]: + seq[j-1], seq[j] = seq[j], seq[j-1] + j -= 1 + return seq + + +def insertion_sort_rec(seq, i = None): + ''' sort a sequence using the recursive insertion sort alg ''' + if i == None: i = len(seq) -1 + if i == 0: return i + insertion_sort_rec(seq, i-1) + j = i + while j > 0 and seq[j-i] > seq[j]: + seq[j-1], seq[j] = seq[j], seq[j-1] + j -= 1 + return seq + + +def test_insertion_sort(): + seq = [3, 5, 2, 6, 8, 1, 0, 3, 5, 6, 2, 5, 4, 1, 5, 3] + assert(insertion_sort(seq) == sorted(seq)) + assert(insertion_sort_rec(seq) == sorted(seq)) + print('Tests passed!') + + +if __name__ == '__main__': + test_insertion_sort() + + + + + + + diff --git a/src/examples_in_my_book/sorting/insertion_sort.py~ b/src/examples_in_my_book/sorting/insertion_sort.py~ new file mode 100644 index 0000000..61099a7 --- /dev/null +++ b/src/examples_in_my_book/sorting/insertion_sort.py~ @@ -0,0 +1,46 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + + +from do_benchmark import benchmark + +@benchmark +def insertion_sort(seq): + ''' sort a sequence using the insertion sort alg ''' + for i in range(1, len(seq)): + j = i + while j > 0 and seq[j-1] > seq[j]: + seq[j-1], seq[j] = seq[j], seq[j-1] + j -= 1 + return seq + + +def insertion_sort_rec(seq, i = None): + ''' sort a sequence using the recursive insertion sort alg ''' + if i == None: i = len(seq) -1 + if i == 0: return i + insertion_sort_rec(seq, i-1) + j = i + while j > 0 and seq[j-i] > seq[j]: + seq[j-1], seq[j] = seq[j], seq[j-1] + j -= 1 + return seq + + +def test_insertion_sort(): + seq = [3, 5, 2, 6, 8, 1, 0, 3, 5, 6, 2, 5, 4, 1, 5, 3] + assert(insertion_sort(seq) == sorted(seq)) + assert(insertion_sort_rec(seq) == sorted(seq)) + print('Tests passed!') + + +if __name__ == '__main__': + test_insertion_sort() + + + + + + + diff --git a/src/examples_in_my_book/sorting/merge_sort.py b/src/examples_in_my_book/sorting/merge_sort.py new file mode 100644 index 0000000..46a27dd --- /dev/null +++ b/src/examples_in_my_book/sorting/merge_sort.py @@ -0,0 +1,33 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + + + +def merge_sort(seq): + if len(seq) <= 1: return seq + mid = len(seq)//2 + lft, rgt = seq[:mid], seq[mid:] + if len(lft)>1: lft = merge_sort(lft) + if len(rgt)>1: rgt = merge_sort(rgt) + + res = [] + while lft and rgt: + if lft [-1]>= rgt[-1]: + res.append(lft.pop()) + else: + res.append(rgt.pop()) + res.reverse() + return(lft or rgt) + res + + + + +def test_merge_sort(): + seq = [3, 5, 2, 6, 8, 1, 0, 3, 5, 6, 2] + assert(merge_sort(seq) == sorted(seq)) + print('Tests passed!') + + +if __name__ == '__main__': + test_merge_sort() diff --git a/src/examples_in_my_book/sorting/merge_sort.py~ b/src/examples_in_my_book/sorting/merge_sort.py~ new file mode 100644 index 0000000..e644ecb --- /dev/null +++ b/src/examples_in_my_book/sorting/merge_sort.py~ @@ -0,0 +1,31 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + + + +def merge_sort(seq): + mid = len(seq)//2 + lft, rgt = seq[:mid], seq[mid:] + if len(lft)>1: lft = merge_sort(lft) + if len(rgt)>1: rgt = merge_sort(rgt) + res = [] + while lft and rgt: + if lft [-1]>= rgt[-1]: + res.append(lft.pop()) + else: + res.append(rgt.pop()) + res.reverse() + return(lft or rgt) + res + + + + +def test_merge_sort(): + seq = [3, 5, 2, 6, 8, 1, 0, 3, 5, 6, 2] + assert(merge_sort(seq) == sorted(seq)) + print('Tests passed!') + + +if __name__ == '__main__': + test_merge_sort() diff --git a/src/examples_in_my_book/sorting/quick_sort.py b/src/examples_in_my_book/sorting/quick_sort.py new file mode 100644 index 0000000..ee4d0c1 --- /dev/null +++ b/src/examples_in_my_book/sorting/quick_sort.py @@ -0,0 +1,42 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + + + +def quick_sort(seq): + if len(seq) < 2: return seq + pivot = sorted(seq[0], seq[len(seq)//2], seq[-1])[1] + print(pivot) + left = quick_sort([x for x in seq[1:] if x < pivot]) + right = quick_sort([x for x in seq[1:] if x >= pivot]) + return left + [pivot] + right + + +""" we can also divide them into two functions """ +def partition(seq): + pi,seq = seq[0],seq[1:] + lo = [x for x in seq if x <= pi] + hi = [x for x in seq if x > pi] + return lo, pi, hi + +def quick_sort_divided(seq): + if len(seq) < 2: return seq + lo, pi, hi = partition(seq) + return quick_sort_divided(lo) + [pi] + quick_sort_divided(hi) + + + + +def test_quick_sort(): + seq = [3, 5, 2, 6, 8, 1, 0, 3, 5, 6, 2] + assert(quick_sort(seq) == sorted(seq)) + assert(quick_sort_divided(seq) == sorted(seq)) + print('Tests passed!') + + +if __name__ == '__main__': + test_quick_sort() + + + diff --git a/src/examples_in_my_book/sorting/quick_sort.py~ b/src/examples_in_my_book/sorting/quick_sort.py~ new file mode 100644 index 0000000..ed9b1c6 --- /dev/null +++ b/src/examples_in_my_book/sorting/quick_sort.py~ @@ -0,0 +1,41 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + + + +def quick_sort(seq): + if len(seq) < 2: return seq + pivot = seq[0] + left = quick_sort([x for x in seq[1:] if x < pivot]) + right = quick_sort([x for x in seq[1:] if x >= pivot]) + return left + [pivot] + right + + +""" we can also divide them into two functions """ +def partition(seq): + pi,seq = seq[0],seq[1:] + lo = [x for x in seq if x <= pi] + hi = [x for x in seq if x > pi] + return lo, pi, hi + +def quick_sort_divided(seq): + if len(seq) < 2: return seq + lo, pi, hi = partition(seq) + return quick_sort_divided(lo) + [pi] + quick_sort_divided(hi) + + + + +def test_quick_sort(): + seq = [3, 5, 2, 6, 8, 1, 0, 3, 5, 6, 2] + assert(quick_sort(seq) == sorted(seq)) + assert(quick_sort_divided(seq) == sorted(seq)) + print('Tests passed!') + + +if __name__ == '__main__': + test_quick_sort() + + + diff --git a/src/examples_in_my_book/sorting/selection_sort.py b/src/examples_in_my_book/sorting/selection_sort.py new file mode 100644 index 0000000..7c6ddac --- /dev/null +++ b/src/examples_in_my_book/sorting/selection_sort.py @@ -0,0 +1,31 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + + +def selection_sort(seq): + ''' sort a sequence using the selection sort alg ''' + for i in range(len(seq) -1, 0, -1): + max_j = i + for j in range(max_j): + if seq[j] > seq[max_j]: + max_j = j + seq[i], seq[max_j] = seq[max_j], seq[i] + return seq + + +def test_selection_sort(): + seq = [3, 5, 2, 6, 8, 1, 0, 3, 5, 6, 2] + assert(selection_sort(seq) == sorted(seq)) + print('Tests passed!') + + +if __name__ == '__main__': + test_selection_sort() + + + + + + + diff --git a/src/examples_in_my_book/trees/__init__.py b/src/examples_in_my_book/trees/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/examples_in_my_book/trees/binary_trees/BST.py b/src/examples_in_my_book/trees/binary_trees/BST.py new file mode 100644 index 0000000..b2384a3 --- /dev/null +++ b/src/examples_in_my_book/trees/binary_trees/BST.py @@ -0,0 +1,68 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + +from BT import BT + +class BST(BT): + def __init__(self, value=None): + self.value = value + self.left = None + self.right = None + + def insert_left(self, new_node): + self.insert(value) + + def insert_right(self, new_node): + self.insert(value) + + + def insert(self, value): + if self.value == None: + self.value = value + else: + if value > self.value: + self.right = self.right and self.right.insert(value) or BST(value) + else: + self.left = self.left and self.left.insert(value) or BST(value) + return self + + def find(self, value): + if value == self.value: + return self + elif value > self.value and self.right: + return self.right.find(value) + elif self.left: + return self.left.find(value) + return None + + + + +def main(): + """ + BST + 4 + 2 6 + 1 3 5 7 + """ + tree = BST() + tree.insert(4) + tree.insert(2) + tree.insert(6) + tree.insert(1) + tree.insert(3) + tree.insert(7) + tree.insert(5) + print(tree.get_right()) + print(tree.get_right().get_left()) + print(tree.get_right().get_right()) + print(tree.get_left()) + print(tree.get_left().get_left()) + print(tree.get_left().get_right() == 1) + assert(tree.find(30) == None) + + +if __name__ == '__main__': + main() + diff --git a/src/examples_in_my_book/trees/binary_trees/BST.py~ b/src/examples_in_my_book/trees/binary_trees/BST.py~ new file mode 100644 index 0000000..683b2ea --- /dev/null +++ b/src/examples_in_my_book/trees/binary_trees/BST.py~ @@ -0,0 +1,68 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + +from BT import BT + +class BST(BT): + def __init__(self, value=None): + self.value = value + self.left = None + self.right = None + + def insert_left(self, new_node): + self.insert(value) + + def insert_right(self, new_node): + self.insert(value) + + + def insert(self, value): + if self.value == None: + self.value = value + else: + if value > self.value: + self.right = self.right and self.right.insert(value) or BST(value) + else: + self.left = self.left and self.left.insert(value) or BST(value) + return self + + def find(self, value): + if value == self.value: + return self + elif value > self.value and self.right: + return self.right.find(value) + elif self.left: + return self.left.find(value) + return None + + + + +def main(): + """ + BST + 4 + 2 6 + 1 3 5 7 + """ + tree = BST() + tree.insert(4) + tree.insert(2) + tree.insert(6) + tree.insert(1) + tree.insert(3) + tree.insert(7) + tree.insert(5) + print(tree.get_right()) + print(tree.get_right().get_left()) + print(tree.get_right().get_right()) + print(tree.get_left()) + print(tree.get_left().get_left()) + assert(tree.get_left().get_right() == str(1)) + assert(tree.find(30) == None) + + +if __name__ == '__main__': + main() + diff --git a/src/examples_in_my_book/trees/binary_trees/BST_with_Nodes.py b/src/examples_in_my_book/trees/binary_trees/BST_with_Nodes.py new file mode 100644 index 0000000..91cd081 --- /dev/null +++ b/src/examples_in_my_book/trees/binary_trees/BST_with_Nodes.py @@ -0,0 +1,66 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + + + +class Node(object): + def __init__(self, value): + self.value = value + self.left = None + self.right = None + + def __repr__(self): + return '{}'.format(self.value) + + +class BSTwithNodes(object): + def __init__(self): + self.root = None + + + def insert(self, value): + if self.root == None: + self.root = Node(value) + else: + current = self.root + while True: + if value < current.value: + if current.left: + current = current.left + else: + current.left = Node(value) + break; + + elif value > current.value: + if current.right: + current = current.right + else: + current.right = Node(value) + break; + else: + break + + +def main(): + """ + BST + 4 + 2 6 + 1 3 5 7 + """ + tree = BSTwithNodes() + l1 = [4, 2, 6, 1, 3, 7, 5] + for i in l1: tree.insert(i) + print(tree.root) + print(tree.root.right) + print(tree.root.right.left) + print(tree.root.right.right) + print(tree.root.left) + print(tree.root.left.left) + print(tree.root.left.right) + + +if __name__ == '__main__': + main() + diff --git a/src/examples_in_my_book/trees/binary_trees/BST_with_Nodes.py~ b/src/examples_in_my_book/trees/binary_trees/BST_with_Nodes.py~ new file mode 100644 index 0000000..7575546 --- /dev/null +++ b/src/examples_in_my_book/trees/binary_trees/BST_with_Nodes.py~ @@ -0,0 +1,67 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + + + +class Node(object): + def __init__(self, value): + self.value = value + self.left = None + self.right = None + + def __repr__(self): + return '{}'.format(self.value) + + +class BSTwithNodes(object): + def __init__(self): + self.root = None + + + + def insert(self, value): + if self.root == None: + self.root = Node(value) + else: + current = self.root + while True: + if value < current.value: + if current.left: + current = current.left + else: + current.left = Node(value) + break; + + elif value > current.value: + if current.right: + current = current.right + else: + current.right = Node(value) + break; + else: + break + + +def main(): + """ + BST + 4 + 2 6 + 1 3 5 7 + """ + tree = BSTwithNodes() + l1 = [4, 2, 6, 1, 3, 7, 5] + for i in l1: tree.insert(i) + assert(tree.root == '4') + print(tree.root.right) + print(tree.root.right.left) + print(tree.root.right.right) + print(tree.root.left) + print(tree.root.left.left) + print(tree.root.left.right) + + +if __name__ == '__main__': + main() + diff --git a/src/examples_in_my_book/trees/binary_trees/BT.py b/src/examples_in_my_book/trees/binary_trees/BT.py new file mode 100644 index 0000000..15d93b1 --- /dev/null +++ b/src/examples_in_my_book/trees/binary_trees/BT.py @@ -0,0 +1,72 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + + +class BT(object): + def __init__(self, value): + self.value = value + self.left = None + self.right = None + + + def get_right(self): + return self.right + + def get_left(self): + return self.left + + def is_leaf(self): + return self.left is None and self.right is None + + def set_root(self, obj): + self.value = obj + + def get_root(self): + return self.value + + def insert_left(self, new_node): + if self.left == None: + self.left = BT(new_node) + else: + t = BT(self.left) + t.left = new_node + self.left = t + + def insert_right(self, new_node): + if self.right == None: + self.right = BT(new_node) + else: + t = BT(self.right) + t.right = new_node + self.right = t + + def __repr__(self): + return '{}'.format(self.value) + + + +def tests_BT(): + """ + 1 + 2 3 + 4 5 6 7 + """ + tree = BT(1) + tree.insert_left(2) + tree.insert_right(3) + tree.get_left().insert_left(4) + tree.get_left().insert_right(5) + tree.get_right().insert_left(6) + tree.get_right().insert_right(7) + print(tree.get_right().get_right()) + tree.get_right().get_right().set_root(8) + print(tree.get_right().get_right()) + assert(tree.get_right().is_leaf() == False) + assert(tree.get_right().get_right().is_leaf() == True) + print("Tests Passed!") + + +if __name__ == '__main__': + tests_BT() + diff --git a/src/examples_in_my_book/trees/binary_trees/BT.py~ b/src/examples_in_my_book/trees/binary_trees/BT.py~ new file mode 100644 index 0000000..f32232e --- /dev/null +++ b/src/examples_in_my_book/trees/binary_trees/BT.py~ @@ -0,0 +1,72 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + + +class BT(object): + def __init__(self, value): + self.value = value + self.left = None + self.right = None + + + def get_right(self): + return self.right + + def get_left(self): + return self.left + + def is_leaf(self): + return self.left is None and self.right is None + + def set_root(self, obj): + self.value = obj + + def get_root(self): + return self.value + + def insert_left(self, new_node): + if self.left == None: + self.left = BT(new_node) + else: + t = BT(self.left) + t.left = new_node + self.left = t + + def insert_right(self, new_node): + if self.right == None: + self.right = BT(new_node) + else: + t = BT(self.right) + t.right = new_node + self.right = t + + def __repr__(self): + return '{}'.format(self.value) + + + +def tests_BT(): + """ + 1 + 2 3 + 4 5 6 7 + """ + tree = BT(1) + tree.insert_left(2) + tree.insert_right(3) + tree.get_left().insert_left(4) + tree.get_left().insert_right(5) + tree.get_right().insert_left(6) + tree.get_right().insert_right(7) + assert(tree.get_right().get_right() == str(7)) + tree.get_right().get_right().set_root(8) + assert(tree.get_right().get_right() == str(8)) + assert(tree.get_right().is_leaf() == False) + assert(tree.get_right().get_right().is_leaf() == True) + print("Tests Passed!") + + +if __name__ == '__main__': + tests_BT() + diff --git a/src/examples_in_my_book/trees/binary_trees/BT_lists.py b/src/examples_in_my_book/trees/binary_trees/BT_lists.py new file mode 100644 index 0000000..7e6c1c5 --- /dev/null +++ b/src/examples_in_my_book/trees/binary_trees/BT_lists.py @@ -0,0 +1,61 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + + +def BinaryTreeList(r): + ''' constructs a list with a root and 2 empty sublists for the children. To add a left subtree to the root of a tree, we need to insert a new list into the second position of the root list ''' + return [r, [], []] + + +def insertLeft(root, newBranch): + t = root.pop(1) + if len(t) > 1: + root.insert(1,[newBranch,t,[]]) + else: + root.insert(1,[newBranch, [], []]) + return root + + +def insertRight(root, newBranch): + t = root.pop(2) + if len(t) > 1: + root.insert(2,[newBranch,[],t]) + else: + root.insert(2,[newBranch,[],[]]) + return root + +def getRootVal(root): + return root[0] + +def setRootVal(root, newVal): + root[0] = newVal + +def getLeftChild(root): + return root[1] + +def getRightChild(root): + return root[2] + + + +def main(): + ''' + 3 + [5, [4, [], []], []] + [7, [], [6, [], []]] + ''' + + r = BinaryTreeList(3) + insertLeft(r,4) + insertLeft(r,5) + insertRight(r,6) + insertRight(r,7) + print(getRootVal(r)) + print(getLeftChild(r)) + print(getRightChild(r)) + + +if __name__ == '__main__': + main() + diff --git a/src/examples_in_my_book/trees/binary_trees/__init__.py b/src/examples_in_my_book/trees/binary_trees/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/examples_in_my_book/trees/binary_trees/avl.py b/src/examples_in_my_book/trees/binary_trees/avl.py new file mode 100644 index 0000000..ca23adc --- /dev/null +++ b/src/examples_in_my_book/trees/binary_trees/avl.py @@ -0,0 +1,140 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + +from BST_with_Nodes import BSTwithNodes, Node + + +class AVL(BSTwithNodes): + """AVL binary search tree implementation. + Supports insert, find, and delete-min operations in O(lg n) time. + """ + def __init__(self): + self.root = None + + def left_rotate(self, x): + y = x.right + y.value = x.value + if y.value is None: + self.root = y + else: + if y.value.left is x: + y.value.left = y + elif y.value.right is x: + y.value.right = y + x.right = y.left + if x.right is not None: + x.right.value = x + y.left = x + x.value = y + update_height(x) + update_height(y) + + def right_rotate(self, x): + y = x.left + y.value = x.value + if y.value is None: + self.root = y + else: + if y.value.left is x: + y.value.left = y + elif y.value.right is x: + y.value.right = y + x.left = y.right + if x.left is not None: + x.left.value = x + y.right = x + x.value = y + update_height(x) + update_height(y) + + def insert_item(self, value): + if self.root == None: + self.root = Node(value) + else: + current = self.root + while True: + if value < current.value: + if current.left: + current = current.left + else: + current.left = Node(value) + break; + + elif value > current.value: + if current.right: + current = current.right + else: + current.right = Node(value) + break; + else: + break + + + def insert(self, value): + node = self.insert_item(value) + self.rebalance(node) + + + def rebalance(self, node): + while node is not None: + update_height(node) + if height(node.left) >= 2 + height(node.right): + if height(node.left.left) >= height(node.left.right): + self.right_rotate(node) + else: + self.left_rotate(node.left) + self.right_rotate(node) + elif height(node.right) >= 2 + height(node.left): + if height(node.right.right) >= height(node.right.left): + self.left_rotate(node) + else: + self.right_rotate(node.right) + self.left_rotate(node) + node = node.value + + + def inorder(self, node): + if node is not None: + self.inorder(node.left) + print(node.value) + self.inorder(node.right) + + def preorder(self, node): + if node is not None: + print(node.value) + self.preorder(node.left) + self.preorder(node.right) + + def postorder(self, node): + if node is not None: + self.postorder(node.left) + self.postorder(node.right) + print(node.value) + + +def height(node): + if node is None: return -1 + else: return node.height + +def update_height(node): + node.height = max(height(node.left), height(node.right)) + 1 + + + +def main(): + tree = AVL() + tree.insert(4) + tree.insert(2) + tree.insert(6) + tree.insert(1) + tree.insert(3) + tree.insert(7) + tree.insert(5) + print('Inorder Traversal:') + tree.inorder(tree.root) + + + +if __name__ == '__main__': + main() diff --git a/src/examples_in_my_book/trees/binary_trees/veritfy_if_BST.py b/src/examples_in_my_book/trees/binary_trees/veritfy_if_BST.py new file mode 100644 index 0000000..8aeb9c1 --- /dev/null +++ b/src/examples_in_my_book/trees/binary_trees/veritfy_if_BST.py @@ -0,0 +1,56 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + + +from BT import BT + +def is_bst(root, min=float('-inf'), max=float('inf')): + left, right, value = root.left, root.right, root.value + if min < value < max: + if left and right: + return is_bst(left, min, value) and is_bst(right, value, max) + elif left: + return is_bst(left, min, value) + elif right: + return is_bst(right, value, max) + return True + return False + + +def main(): + """ + BST + 4 + 2 6 + 1 3 5 7 + + BT + 4 + 2 6 + 1 8 5 7 + """ + bst = BT(4) + bst.insert_left(2) + bst.insert_right(6) + bst.get_left().insert_left(1) + bst.get_left().insert_right(3) + bst.get_right().insert_left(5) + bst.get_right().insert_right(7) + print('is_bst(bst) =', is_bst(bst)) + + bt = BT(4) + bt.insert_left(2) + bt.insert_right(6) + bt.get_left().insert_left(1) + bt.get_left().insert_right(8) + bt.get_right().insert_left(5) + bt.get_right().insert_right(7) + print('is_bst(bt) =', is_bst(bt)) + + +if __name__ == '__main__': + main() + + + diff --git a/src/examples_in_my_book/trees/simple_trees/BunchClass.py~ b/src/examples_in_my_book/trees/simple_trees/BunchClass.py~ new file mode 100644 index 0000000..add63bf --- /dev/null +++ b/src/examples_in_my_book/trees/simple_trees/BunchClass.py~ @@ -0,0 +1,22 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + + +class BunchClass(dict): + def __init__(self, *args, **kwds): + super(BunchClass, self).__init__(*args, **kwds) + self.__dict__ = self + + +def main(): + bc = BunchClass # notice the absence of () + tree = bc(left = bc(left="Buffy", right="Angel"), right = bc(left="Willow", right="Xander")) + print(tree) + +if __name__ == '__main__': + main() + + + + diff --git a/src/examples_in_my_book/trees/simple_trees/__init__.py b/src/examples_in_my_book/trees/simple_trees/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/examples_in_my_book/trees/simple_trees/bunchclass.py b/src/examples_in_my_book/trees/simple_trees/bunchclass.py new file mode 100644 index 0000000..03b3104 --- /dev/null +++ b/src/examples_in_my_book/trees/simple_trees/bunchclass.py @@ -0,0 +1,23 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + + +class BunchClass(dict): + def __init__(self, *args, **kwds): + super(BunchClass, self).__init__(*args, **kwds) + self.__dict__ = self + + +def main(): + ''' {'right': {'right': 'Xander', 'left': 'Willow'}, 'left': {'right': 'Angel', 'left': 'Buffy'}}''' + bc = BunchClass # notice the absence of () + tree = bc(left = bc(left="Buffy", right="Angel"), right = bc(left="Willow", right="Xander")) + print(tree) + +if __name__ == '__main__': + main() + + + + diff --git a/src/examples_in_my_book/trees/simple_trees/tree.py b/src/examples_in_my_book/trees/simple_trees/tree.py new file mode 100644 index 0000000..e0646a7 --- /dev/null +++ b/src/examples_in_my_book/trees/simple_trees/tree.py @@ -0,0 +1,36 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + + +class SimpleTree(object): + def __init__(self, value, children = None): + if children == None: children = [] + self.children = children + self.value = value + + def __repr__(self, level=0): + ret = "\t"*level+repr(self.value)+"\n" + for child in self.children: + ret += child.__repr__(level+1) + return ret + + +def main(): + """ + 'a' + 'b' + 'd' + 'e' + 'c' + 'h' + 'g' + """ + st = SimpleTree('a', [SimpleTree('b', [SimpleTree('d'), SimpleTree('e')] ), SimpleTree('c', [SimpleTree('h'), SimpleTree('g')]) ]) + print(st) + + +if __name__ == '__main__': + main() + + diff --git a/src/examples_in_my_book/trees/simple_trees/tree.py~ b/src/examples_in_my_book/trees/simple_trees/tree.py~ new file mode 100644 index 0000000..b84666c --- /dev/null +++ b/src/examples_in_my_book/trees/simple_trees/tree.py~ @@ -0,0 +1,27 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + + +class SimpleTree(object): + def __init__(self, value, children = None): + if children == None: children = [] + self.children = children + self.value = value + + def __repr__(self, level=0): + ret = "\t"*level+repr(self.value)+"\n" + for child in self.children: + ret += child.__repr__(level+1) + return ret + + +def main(): + st = SimpleTree('a', [SimpleTree('b', [SimpleTree('d'), SimpleTree('e')] ), SimpleTree('c', [SimpleTree('h'), SimpleTree('g')]) ]) + print(st) + + +if __name__ == '__main__': + main() + + diff --git a/src/examples_in_my_book/trees/traversals/BST.py b/src/examples_in_my_book/trees/traversals/BST.py new file mode 100644 index 0000000..b2384a3 --- /dev/null +++ b/src/examples_in_my_book/trees/traversals/BST.py @@ -0,0 +1,68 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + +from BT import BT + +class BST(BT): + def __init__(self, value=None): + self.value = value + self.left = None + self.right = None + + def insert_left(self, new_node): + self.insert(value) + + def insert_right(self, new_node): + self.insert(value) + + + def insert(self, value): + if self.value == None: + self.value = value + else: + if value > self.value: + self.right = self.right and self.right.insert(value) or BST(value) + else: + self.left = self.left and self.left.insert(value) or BST(value) + return self + + def find(self, value): + if value == self.value: + return self + elif value > self.value and self.right: + return self.right.find(value) + elif self.left: + return self.left.find(value) + return None + + + + +def main(): + """ + BST + 4 + 2 6 + 1 3 5 7 + """ + tree = BST() + tree.insert(4) + tree.insert(2) + tree.insert(6) + tree.insert(1) + tree.insert(3) + tree.insert(7) + tree.insert(5) + print(tree.get_right()) + print(tree.get_right().get_left()) + print(tree.get_right().get_right()) + print(tree.get_left()) + print(tree.get_left().get_left()) + print(tree.get_left().get_right() == 1) + assert(tree.find(30) == None) + + +if __name__ == '__main__': + main() + diff --git a/src/examples_in_my_book/trees/traversals/BST_ancestor.py b/src/examples_in_my_book/trees/traversals/BST_ancestor.py new file mode 100644 index 0000000..c61933d --- /dev/null +++ b/src/examples_in_my_book/trees/traversals/BST_ancestor.py @@ -0,0 +1,46 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + +from BST_traversal import TranversalBST + +def find_ancestor(path, low_value, high_value): + ''' find the lowest ancestor in a BST ''' + while path: + current_value = path[0] + if current_value < low_value: + try: + path = path[2:] + except: + return current_value + elif current_value > high_value: + try: + path = path[1:] + except: + return current_value + elif low_value <= current_value <= high_value: + return current_value + return None + + +def test_find_ancestor(): + """ + 10 + 5 15 + 1 6 11 50 + """ + t = TranversalBST() + l1 = [10, 5, 15, 1, 6, 11, 50] + for i in l1: t.insert(i) + path = t.preorder() + assert(find_ancestor(path, 1, 6) == 5) + assert(find_ancestor(path, 1, 11) == 10) + assert(find_ancestor(path, 11, 50) == 15) + assert(find_ancestor(path, 5, 15) == 10) + + + print("Tests passsed!") + +if __name__ == '__main__': + test_find_ancestor() + diff --git a/src/examples_in_my_book/trees/traversals/BST_ancestor.py~ b/src/examples_in_my_book/trees/traversals/BST_ancestor.py~ new file mode 100644 index 0000000..41882bc --- /dev/null +++ b/src/examples_in_my_book/trees/traversals/BST_ancestor.py~ @@ -0,0 +1,52 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + +from BST_traversal import TranversalBST + +def find_ancestor(path, low_value, high_value): + ''' find the lowest ancestor in a BST ''' + while path: + current_value = path[0] + if current_value < low_value: + try: + path = path[2:] + except: + return current_value + elif current_value > high_value: + try: + path = path[1:] + except: + return current_value + elif low_value <= current_value <= high_value: + return current_value + return None + + +def test_find_ancestor(): + """ + 10 + 5 15 + 1 6 11 50 + """ + t = TranversalBST() + l1 = [10, 5, 15, 1, 6, 11, 50] + for i in l1: t.insert(i) + path = t.preorder() + assert(find_ancestor(path, 1, 6) == 5) + assert(find_ancestor(path, 1, 11) == 10) + assert(find_ancestor(path, 11, 50) == 15) + assert(find_ancestor(path, 5, 15) == 10) + + path = t.inorder() + print(path) + assert(find_ancestor(path, 1, 6) == 5) + assert(find_ancestor(path, 1, 11) == 10) + assert(find_ancestor(path, 11, 50) == 15) + assert(find_ancestor(path, 5, 15) == 10) + + print("Tests passsed!") + +if __name__ == '__main__': + test_find_ancestor() + diff --git a/src/examples_in_my_book/trees/traversals/BST_traversal.py b/src/examples_in_my_book/trees/traversals/BST_traversal.py new file mode 100644 index 0000000..8a6b21b --- /dev/null +++ b/src/examples_in_my_book/trees/traversals/BST_traversal.py @@ -0,0 +1,88 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + +from BST import BST + +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 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.inorder()) + +if __name__ == '__main__': + main() diff --git a/src/examples_in_my_book/trees/traversals/BST_traversal.py~ b/src/examples_in_my_book/trees/traversals/BST_traversal.py~ new file mode 100644 index 0000000..0d4e400 --- /dev/null +++ b/src/examples_in_my_book/trees/traversals/BST_traversal.py~ @@ -0,0 +1,88 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + +from BST import BST + +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 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.preorder1()) + print(t.preorder()) + print(t.inorder()) + +if __name__ == '__main__': + main() diff --git a/src/examples_in_my_book/trees/traversals/BST_with_Nodes_traversal.py b/src/examples_in_my_book/trees/traversals/BST_with_Nodes_traversal.py new file mode 100644 index 0000000..f443753 --- /dev/null +++ b/src/examples_in_my_book/trees/traversals/BST_with_Nodes_traversal.py @@ -0,0 +1,68 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + +from BST_with_Nodes import BSTwithNodes, Node + +class BSTTraversal(BSTwithNodes): + def __init__(self): + self.root = None + self.nodes_BFS = [] + self.nodes_DFS_pre = [] + self.nodes_DFS_post = [] + self.nodes_DFS_in = [] + + def BFS(self): + self.root.level = 0 + queue = [self.root] + current_level = self.root.level + + while len(queue) > 0: + current_node = queue.pop(0) + if current_node.level > current_level: + current_level += 1 + self.nodes_BFS.append(current_node.value) + + if current_node.left: + current_node.left.level = current_level + 1 + queue.append(current_node.left) + + if current_node.right: + current_node.right.level = current_level + 1 + queue.append(current_node.right) + + return self.nodes_BFS + + def DFS_inorder(self, node): + if node is not None: + self.DFS_inorder(node.left) + self.nodes_DFS_in.append(node.value) + self.DFS_inorder(node.right) + return self.nodes_DFS_in + + def DFS_preorder(self, node): + if node is not None: + self.nodes_DFS_pre.append(node.value) + self.DFS_preorder(node.left) + self.DFS_preorder(node.right) + return self.nodes_DFS_pre + + def DFS_postorder(self, node): + if node is not None: + self.DFS_postorder(node.left) + self.DFS_postorder(node.right) + self.nodes_DFS_post.append(node.value) + return self.nodes_DFS_post + +def main(): + tree = BSTTraversal() + l1 = [10, 5, 15, 1, 6, 11, 50] + for i in l1: tree.insert(i) + + print('Breadth-First Traversal: ', tree.BFS()) + print('Inorder Traversal: ', tree.DFS_inorder(tree.root)) + print('Preorder Traversal: ', tree.DFS_preorder(tree.root)) + print('Postorder Traversal: ', tree.DFS_postorder(tree.root)) + +if __name__ == '__main__': + main() diff --git a/src/examples_in_my_book/trees/traversals/BST_with_extra_methods.py b/src/examples_in_my_book/trees/traversals/BST_with_extra_methods.py new file mode 100644 index 0000000..fd6a424 --- /dev/null +++ b/src/examples_in_my_book/trees/traversals/BST_with_extra_methods.py @@ -0,0 +1,95 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + +from BST_traversal import TranversalBST +from BST import BST + +class BSTwithExtra(TranversalBST): + def __init__(self): + self.bst = BST(None) + self.nodes = [] + + def get_inorder(self, k): + for i, value in enumerate(self.inorder()): + if value == k: + return i + + def get_preorder(self, k): + for i, value in enumerate(self.preorder()): + if value == k: + return i + + + def is_balanced(self, threshold=1): + maxd = self.get_max_depth() + mind = self.get_min_depth() + print('Max depth: ' + str(maxd)) + print('Min depth: ' + str(mind)) + return maxd -mind + + def get_min_depth(self, node=None, initial=1): + if node is None and initial == 1: + node = self.bst + if node.left and node.right: + return 1 + min(self.get_min_depth(node.left, 0), + self.get_min_depth(node.right, 0)) + else: + if node.left: + return 1 + self.get_max_depth(node.left, 0) + elif node.right: + return 1 + self.get_max_depth(node.right, 0) + else: + return 0 + + def get_max_depth(self, node=None, initial=1): + if node is None and initial == 1: + node = self.bst + if node.left and node.right: + return 1 + max(self.get_max_depth(node.left, 0), + self.get_max_depth(node.right, 0)) + else: + if node.left: + return 1 + self.get_max_depth(node.left, 0) + elif node.right: + return 1 + self.get_max_depth(node.right, 0) + else: + return 0 + +def main(): + """ + 10 + 5 15 + 1 6 11 50 + 60 + 70 + 80 + """ + t = BSTwithExtra() + l1 = [10, 5, 15, 1, 6, 11, 50, 60, 70, 80] + for i in l1: t.insert(i) + print(t.inorder()) + print(t.preorder()) + assert(t.get_max_depth() == 5) + assert(t.get_min_depth() == 2) + assert(t.is_balanced() == 3) + assert(t.get_inorder(10) == 3) + assert(t.get_preorder(10) == 0) + + + """ + 1 + 2 3 + 4 5 6 7 + """ + t2 = BSTwithExtra() + l2 = [1, 2, 3, 4, 5, 6, 7, 8] + for i in l2: t2.insert(i) + print(t2.inorder()) + print(t2.preorder()) + assert(t2.is_balanced() == 0) + + print("Tests Passed!") + +if __name__ == '__main__': + main() diff --git a/src/examples_in_my_book/trees/traversals/BST_with_extra_methods.py~ b/src/examples_in_my_book/trees/traversals/BST_with_extra_methods.py~ new file mode 100644 index 0000000..f614d35 --- /dev/null +++ b/src/examples_in_my_book/trees/traversals/BST_with_extra_methods.py~ @@ -0,0 +1,94 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + +from BST_traversal import TranversalBST + +class BSTwithExtra(TranversalBST): + def __init__(self): + self.bst = BST(None) + self.nodes = [] + + def get_inorder(self, k): + for i, value in enumerate(self.inorder()): + if value == k: + return i + + def get_preorder(self, k): + for i, value in enumerate(self.preorder()): + if value == k: + return i + + + def is_balanced(self, threshold=1): + maxd = self.get_max_depth() + mind = self.get_min_depth() + print('Max depth: ' + str(maxd)) + print('Min depth: ' + str(mind)) + return maxd -mind + + def get_min_depth(self, node=None, initial=1): + if node is None and initial == 1: + node = self.bst + if node.left and node.right: + return 1 + min(self.get_min_depth(node.left, 0), + self.get_min_depth(node.right, 0)) + else: + if node.left: + return 1 + self.get_max_depth(node.left, 0) + elif node.right: + return 1 + self.get_max_depth(node.right, 0) + else: + return 0 + + def get_max_depth(self, node=None, initial=1): + if node is None and initial == 1: + node = self.bst + if node.left and node.right: + return 1 + max(self.get_max_depth(node.left, 0), + self.get_max_depth(node.right, 0)) + else: + if node.left: + return 1 + self.get_max_depth(node.left, 0) + elif node.right: + return 1 + self.get_max_depth(node.right, 0) + else: + return 0 + +def main(): + """ + 10 + 5 15 + 1 6 11 50 + 60 + 70 + 80 + """ + t = BSTwithExtra() + l1 = [10, 5, 15, 1, 6, 11, 50, 60, 70, 80] + for i in l1: t.insert(i) + print(t.inorder()) + print(t.preorder()) + assert(t.get_max_depth() == 5) + assert(t.get_min_depth() == 2) + assert(t.is_balanced() == 3) + assert(t.get_inorder(10) == 3) + assert(t.get_preorder(10) == 0) + + + """ + 1 + 2 3 + 4 5 6 7 + """ + t2 = BSTwithExtra() + l2 = [1, 2, 3, 4, 5, 6, 7, 8] + for i in l2: t2.insert(i) + print(t2.inorder()) + print(t2.preorder()) + assert(t2.is_balanced() == 0) + + print("Tests Passed!") + +if __name__ == '__main__': + main() diff --git a/src/examples_in_my_book/trees/traversals/__init__.py b/src/examples_in_my_book/trees/traversals/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/examples_in_my_book/trees/traversals/traversal_BST_with_Nodes.py~ b/src/examples_in_my_book/trees/traversals/traversal_BST_with_Nodes.py~ new file mode 100644 index 0000000..1552b9a --- /dev/null +++ b/src/examples_in_my_book/trees/traversals/traversal_BST_with_Nodes.py~ @@ -0,0 +1,100 @@ +#!/usr/bin/python3 +# mari von steinkirch @2013 +# steinkirch at gmail + +from BST_with_Nodes import BSTwithNodes, Node + +class TraversalBSTwithNodes(BSTwithNodes): + def __init__(self): + self.root = None + + def BFS(self): + self.root.level = 0 + queue = [self.root] + out = [] + current_level = self.root.level + + while len(queue) > 0: + current_node = queue.pop(0) + if current_node.level > current_level: + current_level += 1 + out.append("\n") + out.append(str(current_node.value) + " ") + + if current_node.left: + current_node.left.level = current_level + 1 + queue.append(current_node.left) + + if current_node.right: + current_node.right.level = current_level + 1 + queue.append(current_node.right) + + print("".join(out)) + + def inorder(self, node): + if node is not None: + self.inorder(node.left) + print(node.value) + self.inorder(node.right) + + def preorder(self, node): + if node is not None: + print(node.value) + self.preorder(node.left) + self.preorder(node.right) + + def postorder(self, node): + if node is not None: + self.postorder(node.left) + self.postorder(node.right) + print(node.value) + + + def inorder2(self, node): + if node.left is not None: + self.inorder2(node.left) + print(node.value) + if node.right is not None: + self.inorder2(node.right) + + def postorder2(self, node): + if node.left is not None: + self.inorder2(node.left) + if node.right is not None: + self.inorder2(node.right) + print(node.value) + + def preorder2(self, node): + print(node.value) + if node.left is not None: + self.inorder2(node.left) + if node.right is not None: + self.inorder2(node.right) + + + + +def main(): + tree = TraversalBSTwithNodes() + l1 = [10, 5, 15, 1, 6, 11, 50] + for i in l1: tree.insert(i) + print('Breadth-First Traversal:') + tree.BFS() + + print('Inorder Traversal:') + tree.inorder(tree.root) + tree.inorder2(tree.root) + + print('Preorder Traversal:') + tree.preorder(tree.root) + tree.preorder2(tree.root) + + print('Postorder Traversal:') + tree.postorder(tree.root) + tree.postorder2(tree.root) + + +if __name__ == '__main__': + main() + + diff --git a/src/further_examples/more_algorithm_exercises/arrays_and_strings/comb_str.py b/src/further_examples/more_algorithm_exercises/arrays_and_strings/comb_str.py new file mode 100644 index 0000000..9e9f966 --- /dev/null +++ b/src/further_examples/more_algorithm_exercises/arrays_and_strings/comb_str.py @@ -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() + diff --git a/src/further_examples/more_algorithm_exercises/arrays_and_strings/conv_str2int.py b/src/further_examples/more_algorithm_exercises/arrays_and_strings/conv_str2int.py new file mode 100644 index 0000000..ec7f8c3 --- /dev/null +++ b/src/further_examples/more_algorithm_exercises/arrays_and_strings/conv_str2int.py @@ -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() + diff --git a/src/further_examples/more_algorithm_exercises/arrays_and_strings/find_0_MxN_replace_cols_rows.py b/src/further_examples/more_algorithm_exercises/arrays_and_strings/find_0_MxN_replace_cols_rows.py new file mode 100644 index 0000000..f306d83 --- /dev/null +++ b/src/further_examples/more_algorithm_exercises/arrays_and_strings/find_0_MxN_replace_cols_rows.py @@ -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() + diff --git a/src/further_examples/more_algorithm_exercises/arrays_and_strings/find_first_non_repetead_char.py b/src/further_examples/more_algorithm_exercises/arrays_and_strings/find_first_non_repetead_char.py new file mode 100644 index 0000000..a6b57a0 --- /dev/null +++ b/src/further_examples/more_algorithm_exercises/arrays_and_strings/find_first_non_repetead_char.py @@ -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() + diff --git a/src/further_examples/more_algorithm_exercises/arrays_and_strings/find_if_is_substr.py b/src/further_examples/more_algorithm_exercises/arrays_and_strings/find_if_is_substr.py new file mode 100644 index 0000000..d8fd6d6 --- /dev/null +++ b/src/further_examples/more_algorithm_exercises/arrays_and_strings/find_if_is_substr.py @@ -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() + diff --git a/src/further_examples/more_algorithm_exercises/arrays_and_strings/find_if_only_unique_chars.py b/src/further_examples/more_algorithm_exercises/arrays_and_strings/find_if_only_unique_chars.py new file mode 100644 index 0000000..fe804bb --- /dev/null +++ b/src/further_examples/more_algorithm_exercises/arrays_and_strings/find_if_only_unique_chars.py @@ -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() + diff --git a/src/further_examples/more_algorithm_exercises/arrays_and_strings/perm_str.py b/src/further_examples/more_algorithm_exercises/arrays_and_strings/perm_str.py new file mode 100644 index 0000000..6c32dfa --- /dev/null +++ b/src/further_examples/more_algorithm_exercises/arrays_and_strings/perm_str.py @@ -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() + diff --git a/src/further_examples/more_algorithm_exercises/arrays_and_strings/remove_specified_char_from_str.py b/src/further_examples/more_algorithm_exercises/arrays_and_strings/remove_specified_char_from_str.py new file mode 100644 index 0000000..7c7dc36 --- /dev/null +++ b/src/further_examples/more_algorithm_exercises/arrays_and_strings/remove_specified_char_from_str.py @@ -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() + diff --git a/src/further_examples/more_algorithm_exercises/arrays_and_strings/reverse_str.py b/src/further_examples/more_algorithm_exercises/arrays_and_strings/reverse_str.py new file mode 100644 index 0000000..442877f --- /dev/null +++ b/src/further_examples/more_algorithm_exercises/arrays_and_strings/reverse_str.py @@ -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() + diff --git a/src/further_examples/more_algorithm_exercises/arrays_and_strings/reverse_words_setence.py b/src/further_examples/more_algorithm_exercises/arrays_and_strings/reverse_words_setence.py new file mode 100644 index 0000000..110eb33 --- /dev/null +++ b/src/further_examples/more_algorithm_exercises/arrays_and_strings/reverse_words_setence.py @@ -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() + diff --git a/src/further_examples/more_algorithm_exercises/arrays_and_strings/rotate_NxN.py b/src/further_examples/more_algorithm_exercises/arrays_and_strings/rotate_NxN.py new file mode 100644 index 0000000..d238a94 --- /dev/null +++ b/src/further_examples/more_algorithm_exercises/arrays_and_strings/rotate_NxN.py @@ -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() + diff --git a/src/further_examples/more_algorithm_exercises/arrays_and_strings/simple_str_comprension.py b/src/further_examples/more_algorithm_exercises/arrays_and_strings/simple_str_comprension.py new file mode 100644 index 0000000..d357e69 --- /dev/null +++ b/src/further_examples/more_algorithm_exercises/arrays_and_strings/simple_str_comprension.py @@ -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() + diff --git a/src/further_examples/more_algorithm_exercises/arrays_and_strings/verify_if_perm.py b/src/further_examples/more_algorithm_exercises/arrays_and_strings/verify_if_perm.py new file mode 100644 index 0000000..b4476be --- /dev/null +++ b/src/further_examples/more_algorithm_exercises/arrays_and_strings/verify_if_perm.py @@ -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() + diff --git a/src/further_examples/more_algorithm_exercises/bit_operations/bit_array.py b/src/further_examples/more_algorithm_exercises/bit_operations/bit_array.py new file mode 100644 index 0000000..c5f8366 --- /dev/null +++ b/src/further_examples/more_algorithm_exercises/bit_operations/bit_array.py @@ -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() + diff --git a/src/further_examples/more_algorithm_exercises/bit_operations/clear_bits.py b/src/further_examples/more_algorithm_exercises/bit_operations/clear_bits.py new file mode 100644 index 0000000..e5802cd --- /dev/null +++ b/src/further_examples/more_algorithm_exercises/bit_operations/clear_bits.py @@ -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() + diff --git a/src/further_examples/more_algorithm_exercises/bit_operations/find_bit_len.py b/src/further_examples/more_algorithm_exercises/bit_operations/find_bit_len.py new file mode 100644 index 0000000..d061435 --- /dev/null +++ b/src/further_examples/more_algorithm_exercises/bit_operations/find_bit_len.py @@ -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() + diff --git a/src/further_examples/more_algorithm_exercises/bit_operations/find_how_many_1_binary.py b/src/further_examples/more_algorithm_exercises/bit_operations/find_how_many_1_binary.py new file mode 100644 index 0000000..26a10f7 --- /dev/null +++ b/src/further_examples/more_algorithm_exercises/bit_operations/find_how_many_1_binary.py @@ -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() + diff --git a/src/further_examples/more_algorithm_exercises/bit_operations/get_bit.py b/src/further_examples/more_algorithm_exercises/bit_operations/get_bit.py new file mode 100644 index 0000000..a32c71e --- /dev/null +++ b/src/further_examples/more_algorithm_exercises/bit_operations/get_bit.py @@ -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() + diff --git a/src/further_examples/more_algorithm_exercises/bit_operations/get_float_rep_bin.py b/src/further_examples/more_algorithm_exercises/bit_operations/get_float_rep_bin.py new file mode 100644 index 0000000..e8f7bd4 --- /dev/null +++ b/src/further_examples/more_algorithm_exercises/bit_operations/get_float_rep_bin.py @@ -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() + diff --git a/src/further_examples/more_algorithm_exercises/bit_operations/insert_small_bin_into_big_bin.py b/src/further_examples/more_algorithm_exercises/bit_operations/insert_small_bin_into_big_bin.py new file mode 100644 index 0000000..03257b8 --- /dev/null +++ b/src/further_examples/more_algorithm_exercises/bit_operations/insert_small_bin_into_big_bin.py @@ -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() + diff --git a/src/further_examples/more_algorithm_exercises/bit_operations/next_with_same_num_1s.py b/src/further_examples/more_algorithm_exercises/bit_operations/next_with_same_num_1s.py new file mode 100644 index 0000000..47ba953 --- /dev/null +++ b/src/further_examples/more_algorithm_exercises/bit_operations/next_with_same_num_1s.py @@ -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() + diff --git a/src/further_examples/more_algorithm_exercises/bit_operations/num_bits_to_convert_2_nums.py b/src/further_examples/more_algorithm_exercises/bit_operations/num_bits_to_convert_2_nums.py new file mode 100644 index 0000000..90054de --- /dev/null +++ b/src/further_examples/more_algorithm_exercises/bit_operations/num_bits_to_convert_2_nums.py @@ -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() + diff --git a/src/further_examples/more_algorithm_exercises/bit_operations/set_bit.py b/src/further_examples/more_algorithm_exercises/bit_operations/set_bit.py new file mode 100644 index 0000000..3f98336 --- /dev/null +++ b/src/further_examples/more_algorithm_exercises/bit_operations/set_bit.py @@ -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() + diff --git a/src/further_examples/more_algorithm_exercises/bit_operations/swap_odd_even.py b/src/further_examples/more_algorithm_exercises/bit_operations/swap_odd_even.py new file mode 100644 index 0000000..d640262 --- /dev/null +++ b/src/further_examples/more_algorithm_exercises/bit_operations/swap_odd_even.py @@ -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() + diff --git a/src/further_examples/more_algorithm_exercises/bit_operations/update_bit.py b/src/further_examples/more_algorithm_exercises/bit_operations/update_bit.py new file mode 100644 index 0000000..61422c8 --- /dev/null +++ b/src/further_examples/more_algorithm_exercises/bit_operations/update_bit.py @@ -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() + diff --git a/src/further_examples/more_algorithm_exercises/linked_list/check_pal.py b/src/further_examples/more_algorithm_exercises/linked_list/check_pal.py new file mode 100644 index 0000000..5bf971e --- /dev/null +++ b/src/further_examples/more_algorithm_exercises/linked_list/check_pal.py @@ -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() + diff --git a/src/further_examples/more_algorithm_exercises/linked_list/circ_ll.py b/src/further_examples/more_algorithm_exercises/linked_list/circ_ll.py new file mode 100644 index 0000000..ba6d3b3 --- /dev/null +++ b/src/further_examples/more_algorithm_exercises/linked_list/circ_ll.py @@ -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() diff --git a/src/further_examples/more_algorithm_exercises/linked_list/double_linked_list_fifo.py b/src/further_examples/more_algorithm_exercises/linked_list/double_linked_list_fifo.py new file mode 100644 index 0000000..349ead6 --- /dev/null +++ b/src/further_examples/more_algorithm_exercises/linked_list/double_linked_list_fifo.py @@ -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() diff --git a/src/further_examples/more_algorithm_exercises/linked_list/find_kth.py b/src/further_examples/more_algorithm_exercises/linked_list/find_kth.py new file mode 100644 index 0000000..bcac35c --- /dev/null +++ b/src/further_examples/more_algorithm_exercises/linked_list/find_kth.py @@ -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() + diff --git a/src/further_examples/more_algorithm_exercises/linked_list/hash_table.py b/src/further_examples/more_algorithm_exercises/linked_list/hash_table.py new file mode 100644 index 0000000..e367ea7 --- /dev/null +++ b/src/further_examples/more_algorithm_exercises/linked_list/hash_table.py @@ -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() diff --git a/src/further_examples/more_algorithm_exercises/linked_list/linked_list_fifo.py b/src/further_examples/more_algorithm_exercises/linked_list/linked_list_fifo.py new file mode 100644 index 0000000..c7777a3 --- /dev/null +++ b/src/further_examples/more_algorithm_exercises/linked_list/linked_list_fifo.py @@ -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() diff --git a/src/further_examples/more_algorithm_exercises/linked_list/linked_list_lifo.py b/src/further_examples/more_algorithm_exercises/linked_list/linked_list_lifo.py new file mode 100644 index 0000000..ae061ac --- /dev/null +++ b/src/further_examples/more_algorithm_exercises/linked_list/linked_list_lifo.py @@ -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() diff --git a/src/further_examples/more_algorithm_exercises/linked_list/part_ll.py b/src/further_examples/more_algorithm_exercises/linked_list/part_ll.py new file mode 100644 index 0000000..520e885 --- /dev/null +++ b/src/further_examples/more_algorithm_exercises/linked_list/part_ll.py @@ -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() + diff --git a/src/further_examples/more_algorithm_exercises/linked_list/sum_ll.py b/src/further_examples/more_algorithm_exercises/linked_list/sum_ll.py new file mode 100644 index 0000000..504d627 --- /dev/null +++ b/src/further_examples/more_algorithm_exercises/linked_list/sum_ll.py @@ -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() diff --git a/src/further_examples/more_algorithm_exercises/queues_stacks/animal_shelter.py b/src/further_examples/more_algorithm_exercises/queues_stacks/animal_shelter.py new file mode 100644 index 0000000..1a5b6d7 --- /dev/null +++ b/src/further_examples/more_algorithm_exercises/queues_stacks/animal_shelter.py @@ -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() diff --git a/src/further_examples/more_algorithm_exercises/queues_stacks/queue_2_stacks.py b/src/further_examples/more_algorithm_exercises/queues_stacks/queue_2_stacks.py new file mode 100644 index 0000000..ee9f185 --- /dev/null +++ b/src/further_examples/more_algorithm_exercises/queues_stacks/queue_2_stacks.py @@ -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() diff --git a/src/further_examples/more_algorithm_exercises/queues_stacks/setofStacks.py b/src/further_examples/more_algorithm_exercises/queues_stacks/setofStacks.py new file mode 100644 index 0000000..44c4c3e --- /dev/null +++ b/src/further_examples/more_algorithm_exercises/queues_stacks/setofStacks.py @@ -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() diff --git a/src/further_examples/more_algorithm_exercises/queues_stacks/setofStacksList.py b/src/further_examples/more_algorithm_exercises/queues_stacks/setofStacksList.py new file mode 100644 index 0000000..a9c5d9d --- /dev/null +++ b/src/further_examples/more_algorithm_exercises/queues_stacks/setofStacksList.py @@ -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() diff --git a/src/further_examples/more_algorithm_exercises/queues_stacks/sort_stack.py b/src/further_examples/more_algorithm_exercises/queues_stacks/sort_stack.py new file mode 100644 index 0000000..d6dcc80 --- /dev/null +++ b/src/further_examples/more_algorithm_exercises/queues_stacks/sort_stack.py @@ -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() diff --git a/src/further_examples/more_algorithm_exercises/queues_stacks/stackMinElemO1.py b/src/further_examples/more_algorithm_exercises/queues_stacks/stackMinElemO1.py new file mode 100644 index 0000000..ee29e77 --- /dev/null +++ b/src/further_examples/more_algorithm_exercises/queues_stacks/stackMinElemO1.py @@ -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() diff --git a/src/further_examples/more_algorithm_exercises/queues_stacks/stack_.py b/src/further_examples/more_algorithm_exercises/queues_stacks/stack_.py new file mode 100644 index 0000000..931f095 --- /dev/null +++ b/src/further_examples/more_algorithm_exercises/queues_stacks/stack_.py @@ -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() diff --git a/src/further_examples/more_algorithm_exercises/queues_stacks/towers_of_hanoi.py b/src/further_examples/more_algorithm_exercises/queues_stacks/towers_of_hanoi.py new file mode 100644 index 0000000..88dc70d --- /dev/null +++ b/src/further_examples/more_algorithm_exercises/queues_stacks/towers_of_hanoi.py @@ -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) diff --git a/src/further_examples/more_algorithm_exercises/searching/binary_search.py b/src/further_examples/more_algorithm_exercises/searching/binary_search.py new file mode 100644 index 0000000..b942f79 --- /dev/null +++ b/src/further_examples/more_algorithm_exercises/searching/binary_search.py @@ -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 >> 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() diff --git a/src/further_examples/more_algorithm_exercises/searching/find_item_rotated_sorted_array.py b/src/further_examples/more_algorithm_exercises/searching/find_item_rotated_sorted_array.py new file mode 100644 index 0000000..e8a24fb --- /dev/null +++ b/src/further_examples/more_algorithm_exercises/searching/find_item_rotated_sorted_array.py @@ -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() + diff --git a/src/further_examples/more_algorithm_exercises/searching/find_str_array_with_empty_str.py b/src/further_examples/more_algorithm_exercises/searching/find_str_array_with_empty_str.py new file mode 100644 index 0000000..6ccdc9b --- /dev/null +++ b/src/further_examples/more_algorithm_exercises/searching/find_str_array_with_empty_str.py @@ -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() + diff --git a/src/further_examples/more_algorithm_exercises/sorting/1.dat b/src/further_examples/more_algorithm_exercises/sorting/1.dat new file mode 100644 index 0000000..8a1218a --- /dev/null +++ b/src/further_examples/more_algorithm_exercises/sorting/1.dat @@ -0,0 +1,5 @@ +1 +2 +3 +4 +5 diff --git a/src/further_examples/more_algorithm_exercises/sorting/2.dat b/src/further_examples/more_algorithm_exercises/sorting/2.dat new file mode 100644 index 0000000..18b0eef --- /dev/null +++ b/src/further_examples/more_algorithm_exercises/sorting/2.dat @@ -0,0 +1,4 @@ +3 +5 +6 +7 diff --git a/src/further_examples/more_algorithm_exercises/sorting/3.dat b/src/further_examples/more_algorithm_exercises/sorting/3.dat new file mode 100644 index 0000000..3a07591 --- /dev/null +++ b/src/further_examples/more_algorithm_exercises/sorting/3.dat @@ -0,0 +1,4 @@ +1 +3 +5 +8 diff --git a/src/further_examples/more_algorithm_exercises/sorting/merge_sort.py b/src/further_examples/more_algorithm_exercises/sorting/merge_sort.py new file mode 100644 index 0000000..7797b22 --- /dev/null +++ b/src/further_examples/more_algorithm_exercises/sorting/merge_sort.py @@ -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() + + diff --git a/src/further_examples/more_algorithm_exercises/sorting/merge_sorted_things.py b/src/further_examples/more_algorithm_exercises/sorting/merge_sorted_things.py new file mode 100644 index 0000000..fb935df --- /dev/null +++ b/src/further_examples/more_algorithm_exercises/sorting/merge_sorted_things.py @@ -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() + + diff --git a/src/further_examples/more_algorithm_exercises/sorting/quick_sort.py b/src/further_examples/more_algorithm_exercises/sorting/quick_sort.py new file mode 100644 index 0000000..201aa0c --- /dev/null +++ b/src/further_examples/more_algorithm_exercises/sorting/quick_sort.py @@ -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() diff --git a/src/further_examples/more_algorithm_exercises/sorting/sort_anagrams_together.py b/src/further_examples/more_algorithm_exercises/sorting/sort_anagrams_together.py new file mode 100644 index 0000000..c0b5b42 --- /dev/null +++ b/src/further_examples/more_algorithm_exercises/sorting/sort_anagrams_together.py @@ -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() + diff --git a/src/further_examples/more_algorithm_exercises/trees_graphs/binary_search_tree.py b/src/further_examples/more_algorithm_exercises/trees_graphs/binary_search_tree.py new file mode 100644 index 0000000..a58c937 --- /dev/null +++ b/src/further_examples/more_algorithm_exercises/trees_graphs/binary_search_tree.py @@ -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() + diff --git a/src/further_examples/more_algorithm_exercises/trees_graphs/binary_tree.py b/src/further_examples/more_algorithm_exercises/trees_graphs/binary_tree.py new file mode 100644 index 0000000..a33fa1a --- /dev/null +++ b/src/further_examples/more_algorithm_exercises/trees_graphs/binary_tree.py @@ -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() diff --git a/src/further_examples/more_algorithm_exercises/trees_graphs/traversals.py b/src/further_examples/more_algorithm_exercises/trees_graphs/traversals.py new file mode 100644 index 0000000..a962d46 --- /dev/null +++ b/src/further_examples/more_algorithm_exercises/trees_graphs/traversals.py @@ -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() diff --git a/src/further_examples/project_euler/amicable_numbers.py b/src/further_examples/project_euler/amicable_numbers.py new file mode 100644 index 0000000..02c262b --- /dev/null +++ b/src/further_examples/project_euler/amicable_numbers.py @@ -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() + diff --git a/src/further_examples/project_euler/circular_primes.py b/src/further_examples/project_euler/circular_primes.py new file mode 100644 index 0000000..1f89d6f --- /dev/null +++ b/src/further_examples/project_euler/circular_primes.py @@ -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() + diff --git a/src/further_examples/project_euler/counting_sundays.py b/src/further_examples/project_euler/counting_sundays.py new file mode 100644 index 0000000..6951b8f --- /dev/null +++ b/src/further_examples/project_euler/counting_sundays.py @@ -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() + diff --git a/src/further_examples/project_euler/digit_fifth_pow.py b/src/further_examples/project_euler/digit_fifth_pow.py new file mode 100644 index 0000000..14a9985 --- /dev/null +++ b/src/further_examples/project_euler/digit_fifth_pow.py @@ -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() + diff --git a/src/further_examples/project_euler/dist_pow.py b/src/further_examples/project_euler/dist_pow.py new file mode 100644 index 0000000..0b47350 --- /dev/null +++ b/src/further_examples/project_euler/dist_pow.py @@ -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() + diff --git a/src/further_examples/project_euler/even_fib_num.py b/src/further_examples/project_euler/even_fib_num.py new file mode 100644 index 0000000..f465b29 --- /dev/null +++ b/src/further_examples/project_euler/even_fib_num.py @@ -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() + diff --git a/src/further_examples/project_euler/factorial.py b/src/further_examples/project_euler/factorial.py new file mode 100644 index 0000000..b19bea2 --- /dev/null +++ b/src/further_examples/project_euler/factorial.py @@ -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() + diff --git a/src/further_examples/project_euler/findstprime.py b/src/further_examples/project_euler/findstprime.py new file mode 100644 index 0000000..4f56209 --- /dev/null +++ b/src/further_examples/project_euler/findstprime.py @@ -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() + diff --git a/src/further_examples/project_euler/gold_other.py b/src/further_examples/project_euler/gold_other.py new file mode 100644 index 0000000..5b471e4 --- /dev/null +++ b/src/further_examples/project_euler/gold_other.py @@ -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() + diff --git a/src/further_examples/project_euler/highly_divisible_trian_num.py b/src/further_examples/project_euler/highly_divisible_trian_num.py new file mode 100644 index 0000000..41cd2f1 --- /dev/null +++ b/src/further_examples/project_euler/highly_divisible_trian_num.py @@ -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() + diff --git a/src/further_examples/project_euler/larg_palindrome.py b/src/further_examples/project_euler/larg_palindrome.py new file mode 100644 index 0000000..e9f6a89 --- /dev/null +++ b/src/further_examples/project_euler/larg_palindrome.py @@ -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() + diff --git a/src/further_examples/project_euler/larg_prod_grid.dat b/src/further_examples/project_euler/larg_prod_grid.dat new file mode 100644 index 0000000..4ac2451 --- /dev/null +++ b/src/further_examples/project_euler/larg_prod_grid.dat @@ -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 diff --git a/src/further_examples/project_euler/larg_prod_grid.py b/src/further_examples/project_euler/larg_prod_grid.py new file mode 100644 index 0000000..4af10c5 --- /dev/null +++ b/src/further_examples/project_euler/larg_prod_grid.py @@ -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() + diff --git a/src/further_examples/project_euler/large_sum.dat b/src/further_examples/project_euler/large_sum.dat new file mode 100644 index 0000000..43b568e --- /dev/null +++ b/src/further_examples/project_euler/large_sum.dat @@ -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 diff --git a/src/further_examples/project_euler/large_sum.py b/src/further_examples/project_euler/large_sum.py new file mode 100644 index 0000000..4d0ac69 --- /dev/null +++ b/src/further_examples/project_euler/large_sum.py @@ -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() + diff --git a/src/further_examples/project_euler/largest_prime_factor.py b/src/further_examples/project_euler/largest_prime_factor.py new file mode 100644 index 0000000..0c8eb6b --- /dev/null +++ b/src/further_examples/project_euler/largest_prime_factor.py @@ -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() diff --git a/src/further_examples/project_euler/largest_product_seq.py b/src/further_examples/project_euler/largest_product_seq.py new file mode 100644 index 0000000..65fefa2 --- /dev/null +++ b/src/further_examples/project_euler/largest_product_seq.py @@ -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() + diff --git a/src/further_examples/project_euler/lattice_paths.py b/src/further_examples/project_euler/lattice_paths.py new file mode 100644 index 0000000..8c4fb20 --- /dev/null +++ b/src/further_examples/project_euler/lattice_paths.py @@ -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() + diff --git a/src/further_examples/project_euler/lexico_per.py b/src/further_examples/project_euler/lexico_per.py new file mode 100644 index 0000000..52a5ccb --- /dev/null +++ b/src/further_examples/project_euler/lexico_per.py @@ -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() + diff --git a/src/further_examples/project_euler/long_collatz_seq.py b/src/further_examples/project_euler/long_collatz_seq.py new file mode 100644 index 0000000..70535e2 --- /dev/null +++ b/src/further_examples/project_euler/long_collatz_seq.py @@ -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() + diff --git a/src/further_examples/project_euler/max_path_sum.dat b/src/further_examples/project_euler/max_path_sum.dat new file mode 100644 index 0000000..e236c2f --- /dev/null +++ b/src/further_examples/project_euler/max_path_sum.dat @@ -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 diff --git a/src/further_examples/project_euler/max_path_sum.py b/src/further_examples/project_euler/max_path_sum.py new file mode 100644 index 0000000..955a40f --- /dev/null +++ b/src/further_examples/project_euler/max_path_sum.py @@ -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() + diff --git a/src/further_examples/project_euler/max_path_sum0.dat b/src/further_examples/project_euler/max_path_sum0.dat new file mode 100644 index 0000000..65ff300 --- /dev/null +++ b/src/further_examples/project_euler/max_path_sum0.dat @@ -0,0 +1,4 @@ +3 +7 4 +2 4 6 +8 5 9 3 diff --git a/src/further_examples/project_euler/multiples_of_3_and_5.py b/src/further_examples/project_euler/multiples_of_3_and_5.py new file mode 100644 index 0000000..f63adf8 --- /dev/null +++ b/src/further_examples/project_euler/multiples_of_3_and_5.py @@ -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_() + diff --git a/src/further_examples/project_euler/names.txt b/src/further_examples/project_euler/names.txt new file mode 100644 index 0000000..7b8986b --- /dev/null +++ b/src/further_examples/project_euler/names.txt @@ -0,0 +1 @@ +"MARY","PATRICIA","LINDA","BARBARA","ELIZABETH","JENNIFER","MARIA","SUSAN","MARGARET","DOROTHY","LISA","NANCY","KAREN","BETTY","HELEN","SANDRA","DONNA","CAROL","RUTH","SHARON","MICHELLE","LAURA","SARAH","KIMBERLY","DEBORAH","JESSICA","SHIRLEY","CYNTHIA","ANGELA","MELISSA","BRENDA","AMY","ANNA","REBECCA","VIRGINIA","KATHLEEN","PAMELA","MARTHA","DEBRA","AMANDA","STEPHANIE","CAROLYN","CHRISTINE","MARIE","JANET","CATHERINE","FRANCES","ANN","JOYCE","DIANE","ALICE","JULIE","HEATHER","TERESA","DORIS","GLORIA","EVELYN","JEAN","CHERYL","MILDRED","KATHERINE","JOAN","ASHLEY","JUDITH","ROSE","JANICE","KELLY","NICOLE","JUDY","CHRISTINA","KATHY","THERESA","BEVERLY","DENISE","TAMMY","IRENE","JANE","LORI","RACHEL","MARILYN","ANDREA","KATHRYN","LOUISE","SARA","ANNE","JACQUELINE","WANDA","BONNIE","JULIA","RUBY","LOIS","TINA","PHYLLIS","NORMA","PAULA","DIANA","ANNIE","LILLIAN","EMILY","ROBIN","PEGGY","CRYSTAL","GLADYS","RITA","DAWN","CONNIE","FLORENCE","TRACY","EDNA","TIFFANY","CARMEN","ROSA","CINDY","GRACE","WENDY","VICTORIA","EDITH","KIM","SHERRY","SYLVIA","JOSEPHINE","THELMA","SHANNON","SHEILA","ETHEL","ELLEN","ELAINE","MARJORIE","CARRIE","CHARLOTTE","MONICA","ESTHER","PAULINE","EMMA","JUANITA","ANITA","RHONDA","HAZEL","AMBER","EVA","DEBBIE","APRIL","LESLIE","CLARA","LUCILLE","JAMIE","JOANNE","ELEANOR","VALERIE","DANIELLE","MEGAN","ALICIA","SUZANNE","MICHELE","GAIL","BERTHA","DARLENE","VERONICA","JILL","ERIN","GERALDINE","LAUREN","CATHY","JOANN","LORRAINE","LYNN","SALLY","REGINA","ERICA","BEATRICE","DOLORES","BERNICE","AUDREY","YVONNE","ANNETTE","JUNE","SAMANTHA","MARION","DANA","STACY","ANA","RENEE","IDA","VIVIAN","ROBERTA","HOLLY","BRITTANY","MELANIE","LORETTA","YOLANDA","JEANETTE","LAURIE","KATIE","KRISTEN","VANESSA","ALMA","SUE","ELSIE","BETH","JEANNE","VICKI","CARLA","TARA","ROSEMARY","EILEEN","TERRI","GERTRUDE","LUCY","TONYA","ELLA","STACEY","WILMA","GINA","KRISTIN","JESSIE","NATALIE","AGNES","VERA","WILLIE","CHARLENE","BESSIE","DELORES","MELINDA","PEARL","ARLENE","MAUREEN","COLLEEN","ALLISON","TAMARA","JOY","GEORGIA","CONSTANCE","LILLIE","CLAUDIA","JACKIE","MARCIA","TANYA","NELLIE","MINNIE","MARLENE","HEIDI","GLENDA","LYDIA","VIOLA","COURTNEY","MARIAN","STELLA","CAROLINE","DORA","JO","VICKIE","MATTIE","TERRY","MAXINE","IRMA","MABEL","MARSHA","MYRTLE","LENA","CHRISTY","DEANNA","PATSY","HILDA","GWENDOLYN","JENNIE","NORA","MARGIE","NINA","CASSANDRA","LEAH","PENNY","KAY","PRISCILLA","NAOMI","CAROLE","BRANDY","OLGA","BILLIE","DIANNE","TRACEY","LEONA","JENNY","FELICIA","SONIA","MIRIAM","VELMA","BECKY","BOBBIE","VIOLET","KRISTINA","TONI","MISTY","MAE","SHELLY","DAISY","RAMONA","SHERRI","ERIKA","KATRINA","CLAIRE","LINDSEY","LINDSAY","GENEVA","GUADALUPE","BELINDA","MARGARITA","SHERYL","CORA","FAYE","ADA","NATASHA","SABRINA","ISABEL","MARGUERITE","HATTIE","HARRIET","MOLLY","CECILIA","KRISTI","BRANDI","BLANCHE","SANDY","ROSIE","JOANNA","IRIS","EUNICE","ANGIE","INEZ","LYNDA","MADELINE","AMELIA","ALBERTA","GENEVIEVE","MONIQUE","JODI","JANIE","MAGGIE","KAYLA","SONYA","JAN","LEE","KRISTINE","CANDACE","FANNIE","MARYANN","OPAL","ALISON","YVETTE","MELODY","LUZ","SUSIE","OLIVIA","FLORA","SHELLEY","KRISTY","MAMIE","LULA","LOLA","VERNA","BEULAH","ANTOINETTE","CANDICE","JUANA","JEANNETTE","PAM","KELLI","HANNAH","WHITNEY","BRIDGET","KARLA","CELIA","LATOYA","PATTY","SHELIA","GAYLE","DELLA","VICKY","LYNNE","SHERI","MARIANNE","KARA","JACQUELYN","ERMA","BLANCA","MYRA","LETICIA","PAT","KRISTA","ROXANNE","ANGELICA","JOHNNIE","ROBYN","FRANCIS","ADRIENNE","ROSALIE","ALEXANDRA","BROOKE","BETHANY","SADIE","BERNADETTE","TRACI","JODY","KENDRA","JASMINE","NICHOLE","RACHAEL","CHELSEA","MABLE","ERNESTINE","MURIEL","MARCELLA","ELENA","KRYSTAL","ANGELINA","NADINE","KARI","ESTELLE","DIANNA","PAULETTE","LORA","MONA","DOREEN","ROSEMARIE","ANGEL","DESIREE","ANTONIA","HOPE","GINGER","JANIS","BETSY","CHRISTIE","FREDA","MERCEDES","MEREDITH","LYNETTE","TERI","CRISTINA","EULA","LEIGH","MEGHAN","SOPHIA","ELOISE","ROCHELLE","GRETCHEN","CECELIA","RAQUEL","HENRIETTA","ALYSSA","JANA","KELLEY","GWEN","KERRY","JENNA","TRICIA","LAVERNE","OLIVE","ALEXIS","TASHA","SILVIA","ELVIRA","CASEY","DELIA","SOPHIE","KATE","PATTI","LORENA","KELLIE","SONJA","LILA","LANA","DARLA","MAY","MINDY","ESSIE","MANDY","LORENE","ELSA","JOSEFINA","JEANNIE","MIRANDA","DIXIE","LUCIA","MARTA","FAITH","LELA","JOHANNA","SHARI","CAMILLE","TAMI","SHAWNA","ELISA","EBONY","MELBA","ORA","NETTIE","TABITHA","OLLIE","JAIME","WINIFRED","KRISTIE","MARINA","ALISHA","AIMEE","RENA","MYRNA","MARLA","TAMMIE","LATASHA","BONITA","PATRICE","RONDA","SHERRIE","ADDIE","FRANCINE","DELORIS","STACIE","ADRIANA","CHERI","SHELBY","ABIGAIL","CELESTE","JEWEL","CARA","ADELE","REBEKAH","LUCINDA","DORTHY","CHRIS","EFFIE","TRINA","REBA","SHAWN","SALLIE","AURORA","LENORA","ETTA","LOTTIE","KERRI","TRISHA","NIKKI","ESTELLA","FRANCISCA","JOSIE","TRACIE","MARISSA","KARIN","BRITTNEY","JANELLE","LOURDES","LAUREL","HELENE","FERN","ELVA","CORINNE","KELSEY","INA","BETTIE","ELISABETH","AIDA","CAITLIN","INGRID","IVA","EUGENIA","CHRISTA","GOLDIE","CASSIE","MAUDE","JENIFER","THERESE","FRANKIE","DENA","LORNA","JANETTE","LATONYA","CANDY","MORGAN","CONSUELO","TAMIKA","ROSETTA","DEBORA","CHERIE","POLLY","DINA","JEWELL","FAY","JILLIAN","DOROTHEA","NELL","TRUDY","ESPERANZA","PATRICA","KIMBERLEY","SHANNA","HELENA","CAROLINA","CLEO","STEFANIE","ROSARIO","OLA","JANINE","MOLLIE","LUPE","ALISA","LOU","MARIBEL","SUSANNE","BETTE","SUSANA","ELISE","CECILE","ISABELLE","LESLEY","JOCELYN","PAIGE","JONI","RACHELLE","LEOLA","DAPHNE","ALTA","ESTER","PETRA","GRACIELA","IMOGENE","JOLENE","KEISHA","LACEY","GLENNA","GABRIELA","KERI","URSULA","LIZZIE","KIRSTEN","SHANA","ADELINE","MAYRA","JAYNE","JACLYN","GRACIE","SONDRA","CARMELA","MARISA","ROSALIND","CHARITY","TONIA","BEATRIZ","MARISOL","CLARICE","JEANINE","SHEENA","ANGELINE","FRIEDA","LILY","ROBBIE","SHAUNA","MILLIE","CLAUDETTE","CATHLEEN","ANGELIA","GABRIELLE","AUTUMN","KATHARINE","SUMMER","JODIE","STACI","LEA","CHRISTI","JIMMIE","JUSTINE","ELMA","LUELLA","MARGRET","DOMINIQUE","SOCORRO","RENE","MARTINA","MARGO","MAVIS","CALLIE","BOBBI","MARITZA","LUCILE","LEANNE","JEANNINE","DEANA","AILEEN","LORIE","LADONNA","WILLA","MANUELA","GALE","SELMA","DOLLY","SYBIL","ABBY","LARA","DALE","IVY","DEE","WINNIE","MARCY","LUISA","JERI","MAGDALENA","OFELIA","MEAGAN","AUDRA","MATILDA","LEILA","CORNELIA","BIANCA","SIMONE","BETTYE","RANDI","VIRGIE","LATISHA","BARBRA","GEORGINA","ELIZA","LEANN","BRIDGETTE","RHODA","HALEY","ADELA","NOLA","BERNADINE","FLOSSIE","ILA","GRETA","RUTHIE","NELDA","MINERVA","LILLY","TERRIE","LETHA","HILARY","ESTELA","VALARIE","BRIANNA","ROSALYN","EARLINE","CATALINA","AVA","MIA","CLARISSA","LIDIA","CORRINE","ALEXANDRIA","CONCEPCION","TIA","SHARRON","RAE","DONA","ERICKA","JAMI","ELNORA","CHANDRA","LENORE","NEVA","MARYLOU","MELISA","TABATHA","SERENA","AVIS","ALLIE","SOFIA","JEANIE","ODESSA","NANNIE","HARRIETT","LORAINE","PENELOPE","MILAGROS","EMILIA","BENITA","ALLYSON","ASHLEE","TANIA","TOMMIE","ESMERALDA","KARINA","EVE","PEARLIE","ZELMA","MALINDA","NOREEN","TAMEKA","SAUNDRA","HILLARY","AMIE","ALTHEA","ROSALINDA","JORDAN","LILIA","ALANA","GAY","CLARE","ALEJANDRA","ELINOR","MICHAEL","LORRIE","JERRI","DARCY","EARNESTINE","CARMELLA","TAYLOR","NOEMI","MARCIE","LIZA","ANNABELLE","LOUISA","EARLENE","MALLORY","CARLENE","NITA","SELENA","TANISHA","KATY","JULIANNE","JOHN","LAKISHA","EDWINA","MARICELA","MARGERY","KENYA","DOLLIE","ROXIE","ROSLYN","KATHRINE","NANETTE","CHARMAINE","LAVONNE","ILENE","KRIS","TAMMI","SUZETTE","CORINE","KAYE","JERRY","MERLE","CHRYSTAL","LINA","DEANNE","LILIAN","JULIANA","ALINE","LUANN","KASEY","MARYANNE","EVANGELINE","COLETTE","MELVA","LAWANDA","YESENIA","NADIA","MADGE","KATHIE","EDDIE","OPHELIA","VALERIA","NONA","MITZI","MARI","GEORGETTE","CLAUDINE","FRAN","ALISSA","ROSEANN","LAKEISHA","SUSANNA","REVA","DEIDRE","CHASITY","SHEREE","CARLY","JAMES","ELVIA","ALYCE","DEIRDRE","GENA","BRIANA","ARACELI","KATELYN","ROSANNE","WENDI","TESSA","BERTA","MARVA","IMELDA","MARIETTA","MARCI","LEONOR","ARLINE","SASHA","MADELYN","JANNA","JULIETTE","DEENA","AURELIA","JOSEFA","AUGUSTA","LILIANA","YOUNG","CHRISTIAN","LESSIE","AMALIA","SAVANNAH","ANASTASIA","VILMA","NATALIA","ROSELLA","LYNNETTE","CORINA","ALFREDA","LEANNA","CAREY","AMPARO","COLEEN","TAMRA","AISHA","WILDA","KARYN","CHERRY","QUEEN","MAURA","MAI","EVANGELINA","ROSANNA","HALLIE","ERNA","ENID","MARIANA","LACY","JULIET","JACKLYN","FREIDA","MADELEINE","MARA","HESTER","CATHRYN","LELIA","CASANDRA","BRIDGETT","ANGELITA","JANNIE","DIONNE","ANNMARIE","KATINA","BERYL","PHOEBE","MILLICENT","KATHERYN","DIANN","CARISSA","MARYELLEN","LIZ","LAURI","HELGA","GILDA","ADRIAN","RHEA","MARQUITA","HOLLIE","TISHA","TAMERA","ANGELIQUE","FRANCESCA","BRITNEY","KAITLIN","LOLITA","FLORINE","ROWENA","REYNA","TWILA","FANNY","JANELL","INES","CONCETTA","BERTIE","ALBA","BRIGITTE","ALYSON","VONDA","PANSY","ELBA","NOELLE","LETITIA","KITTY","DEANN","BRANDIE","LOUELLA","LETA","FELECIA","SHARLENE","LESA","BEVERLEY","ROBERT","ISABELLA","HERMINIA","TERRA","CELINA","TORI","OCTAVIA","JADE","DENICE","GERMAINE","SIERRA","MICHELL","CORTNEY","NELLY","DORETHA","SYDNEY","DEIDRA","MONIKA","LASHONDA","JUDI","CHELSEY","ANTIONETTE","MARGOT","BOBBY","ADELAIDE","NAN","LEEANN","ELISHA","DESSIE","LIBBY","KATHI","GAYLA","LATANYA","MINA","MELLISA","KIMBERLEE","JASMIN","RENAE","ZELDA","ELDA","MA","JUSTINA","GUSSIE","EMILIE","CAMILLA","ABBIE","ROCIO","KAITLYN","JESSE","EDYTHE","ASHLEIGH","SELINA","LAKESHA","GERI","ALLENE","PAMALA","MICHAELA","DAYNA","CARYN","ROSALIA","SUN","JACQULINE","REBECA","MARYBETH","KRYSTLE","IOLA","DOTTIE","BENNIE","BELLE","AUBREY","GRISELDA","ERNESTINA","ELIDA","ADRIANNE","DEMETRIA","DELMA","CHONG","JAQUELINE","DESTINY","ARLEEN","VIRGINA","RETHA","FATIMA","TILLIE","ELEANORE","CARI","TREVA","BIRDIE","WILHELMINA","ROSALEE","MAURINE","LATRICE","YONG","JENA","TARYN","ELIA","DEBBY","MAUDIE","JEANNA","DELILAH","CATRINA","SHONDA","HORTENCIA","THEODORA","TERESITA","ROBBIN","DANETTE","MARYJANE","FREDDIE","DELPHINE","BRIANNE","NILDA","DANNA","CINDI","BESS","IONA","HANNA","ARIEL","WINONA","VIDA","ROSITA","MARIANNA","WILLIAM","RACHEAL","GUILLERMINA","ELOISA","CELESTINE","CAREN","MALISSA","LONA","CHANTEL","SHELLIE","MARISELA","LEORA","AGATHA","SOLEDAD","MIGDALIA","IVETTE","CHRISTEN","ATHENA","JANEL","CHLOE","VEDA","PATTIE","TESSIE","TERA","MARILYNN","LUCRETIA","KARRIE","DINAH","DANIELA","ALECIA","ADELINA","VERNICE","SHIELA","PORTIA","MERRY","LASHAWN","DEVON","DARA","TAWANA","OMA","VERDA","CHRISTIN","ALENE","ZELLA","SANDI","RAFAELA","MAYA","KIRA","CANDIDA","ALVINA","SUZAN","SHAYLA","LYN","LETTIE","ALVA","SAMATHA","ORALIA","MATILDE","MADONNA","LARISSA","VESTA","RENITA","INDIA","DELOIS","SHANDA","PHILLIS","LORRI","ERLINDA","CRUZ","CATHRINE","BARB","ZOE","ISABELL","IONE","GISELA","CHARLIE","VALENCIA","ROXANNA","MAYME","KISHA","ELLIE","MELLISSA","DORRIS","DALIA","BELLA","ANNETTA","ZOILA","RETA","REINA","LAURETTA","KYLIE","CHRISTAL","PILAR","CHARLA","ELISSA","TIFFANI","TANA","PAULINA","LEOTA","BREANNA","JAYME","CARMEL","VERNELL","TOMASA","MANDI","DOMINGA","SANTA","MELODIE","LURA","ALEXA","TAMELA","RYAN","MIRNA","KERRIE","VENUS","NOEL","FELICITA","CRISTY","CARMELITA","BERNIECE","ANNEMARIE","TIARA","ROSEANNE","MISSY","CORI","ROXANA","PRICILLA","KRISTAL","JUNG","ELYSE","HAYDEE","ALETHA","BETTINA","MARGE","GILLIAN","FILOMENA","CHARLES","ZENAIDA","HARRIETTE","CARIDAD","VADA","UNA","ARETHA","PEARLINE","MARJORY","MARCELA","FLOR","EVETTE","ELOUISE","ALINA","TRINIDAD","DAVID","DAMARIS","CATHARINE","CARROLL","BELVA","NAKIA","MARLENA","LUANNE","LORINE","KARON","DORENE","DANITA","BRENNA","TATIANA","SAMMIE","LOUANN","LOREN","JULIANNA","ANDRIA","PHILOMENA","LUCILA","LEONORA","DOVIE","ROMONA","MIMI","JACQUELIN","GAYE","TONJA","MISTI","JOE","GENE","CHASTITY","STACIA","ROXANN","MICAELA","NIKITA","MEI","VELDA","MARLYS","JOHNNA","AURA","LAVERN","IVONNE","HAYLEY","NICKI","MAJORIE","HERLINDA","GEORGE","ALPHA","YADIRA","PERLA","GREGORIA","DANIEL","ANTONETTE","SHELLI","MOZELLE","MARIAH","JOELLE","CORDELIA","JOSETTE","CHIQUITA","TRISTA","LOUIS","LAQUITA","GEORGIANA","CANDI","SHANON","LONNIE","HILDEGARD","CECIL","VALENTINA","STEPHANY","MAGDA","KAROL","GERRY","GABRIELLA","TIANA","ROMA","RICHELLE","RAY","PRINCESS","OLETA","JACQUE","IDELLA","ALAINA","SUZANNA","JOVITA","BLAIR","TOSHA","RAVEN","NEREIDA","MARLYN","KYLA","JOSEPH","DELFINA","TENA","STEPHENIE","SABINA","NATHALIE","MARCELLE","GERTIE","DARLEEN","THEA","SHARONDA","SHANTEL","BELEN","VENESSA","ROSALINA","ONA","GENOVEVA","COREY","CLEMENTINE","ROSALBA","RENATE","RENATA","MI","IVORY","GEORGIANNA","FLOY","DORCAS","ARIANA","TYRA","THEDA","MARIAM","JULI","JESICA","DONNIE","VIKKI","VERLA","ROSELYN","MELVINA","JANNETTE","GINNY","DEBRAH","CORRIE","ASIA","VIOLETA","MYRTIS","LATRICIA","COLLETTE","CHARLEEN","ANISSA","VIVIANA","TWYLA","PRECIOUS","NEDRA","LATONIA","LAN","HELLEN","FABIOLA","ANNAMARIE","ADELL","SHARYN","CHANTAL","NIKI","MAUD","LIZETTE","LINDY","KIA","KESHA","JEANA","DANELLE","CHARLINE","CHANEL","CARROL","VALORIE","LIA","DORTHA","CRISTAL","SUNNY","LEONE","LEILANI","GERRI","DEBI","ANDRA","KESHIA","IMA","EULALIA","EASTER","DULCE","NATIVIDAD","LINNIE","KAMI","GEORGIE","CATINA","BROOK","ALDA","WINNIFRED","SHARLA","RUTHANN","MEAGHAN","MAGDALENE","LISSETTE","ADELAIDA","VENITA","TRENA","SHIRLENE","SHAMEKA","ELIZEBETH","DIAN","SHANTA","MICKEY","LATOSHA","CARLOTTA","WINDY","SOON","ROSINA","MARIANN","LEISA","JONNIE","DAWNA","CATHIE","BILLY","ASTRID","SIDNEY","LAUREEN","JANEEN","HOLLI","FAWN","VICKEY","TERESSA","SHANTE","RUBYE","MARCELINA","CHANDA","CARY","TERESE","SCARLETT","MARTY","MARNIE","LULU","LISETTE","JENIFFER","ELENOR","DORINDA","DONITA","CARMAN","BERNITA","ALTAGRACIA","ALETA","ADRIANNA","ZORAIDA","RONNIE","NICOLA","LYNDSEY","KENDALL","JANINA","CHRISSY","AMI","STARLA","PHYLIS","PHUONG","KYRA","CHARISSE","BLANCH","SANJUANITA","RONA","NANCI","MARILEE","MARANDA","CORY","BRIGETTE","SANJUANA","MARITA","KASSANDRA","JOYCELYN","IRA","FELIPA","CHELSIE","BONNY","MIREYA","LORENZA","KYONG","ILEANA","CANDELARIA","TONY","TOBY","SHERIE","OK","MARK","LUCIE","LEATRICE","LAKESHIA","GERDA","EDIE","BAMBI","MARYLIN","LAVON","HORTENSE","GARNET","EVIE","TRESSA","SHAYNA","LAVINA","KYUNG","JEANETTA","SHERRILL","SHARA","PHYLISS","MITTIE","ANABEL","ALESIA","THUY","TAWANDA","RICHARD","JOANIE","TIFFANIE","LASHANDA","KARISSA","ENRIQUETA","DARIA","DANIELLA","CORINNA","ALANNA","ABBEY","ROXANE","ROSEANNA","MAGNOLIA","LIDA","KYLE","JOELLEN","ERA","CORAL","CARLEEN","TRESA","PEGGIE","NOVELLA","NILA","MAYBELLE","JENELLE","CARINA","NOVA","MELINA","MARQUERITE","MARGARETTE","JOSEPHINA","EVONNE","DEVIN","CINTHIA","ALBINA","TOYA","TAWNYA","SHERITA","SANTOS","MYRIAM","LIZABETH","LISE","KEELY","JENNI","GISELLE","CHERYLE","ARDITH","ARDIS","ALESHA","ADRIANE","SHAINA","LINNEA","KAROLYN","HONG","FLORIDA","FELISHA","DORI","DARCI","ARTIE","ARMIDA","ZOLA","XIOMARA","VERGIE","SHAMIKA","NENA","NANNETTE","MAXIE","LOVIE","JEANE","JAIMIE","INGE","FARRAH","ELAINA","CAITLYN","STARR","FELICITAS","CHERLY","CARYL","YOLONDA","YASMIN","TEENA","PRUDENCE","PENNIE","NYDIA","MACKENZIE","ORPHA","MARVEL","LIZBETH","LAURETTE","JERRIE","HERMELINDA","CAROLEE","TIERRA","MIRIAN","META","MELONY","KORI","JENNETTE","JAMILA","ENA","ANH","YOSHIKO","SUSANNAH","SALINA","RHIANNON","JOLEEN","CRISTINE","ASHTON","ARACELY","TOMEKA","SHALONDA","MARTI","LACIE","KALA","JADA","ILSE","HAILEY","BRITTANI","ZONA","SYBLE","SHERRYL","RANDY","NIDIA","MARLO","KANDICE","KANDI","DEB","DEAN","AMERICA","ALYCIA","TOMMY","RONNA","NORENE","MERCY","JOSE","INGEBORG","GIOVANNA","GEMMA","CHRISTEL","AUDRY","ZORA","VITA","VAN","TRISH","STEPHAINE","SHIRLEE","SHANIKA","MELONIE","MAZIE","JAZMIN","INGA","HOA","HETTIE","GERALYN","FONDA","ESTRELLA","ADELLA","SU","SARITA","RINA","MILISSA","MARIBETH","GOLDA","EVON","ETHELYN","ENEDINA","CHERISE","CHANA","VELVA","TAWANNA","SADE","MIRTA","LI","KARIE","JACINTA","ELNA","DAVINA","CIERRA","ASHLIE","ALBERTHA","TANESHA","STEPHANI","NELLE","MINDI","LU","LORINDA","LARUE","FLORENE","DEMETRA","DEDRA","CIARA","CHANTELLE","ASHLY","SUZY","ROSALVA","NOELIA","LYDA","LEATHA","KRYSTYNA","KRISTAN","KARRI","DARLINE","DARCIE","CINDA","CHEYENNE","CHERRIE","AWILDA","ALMEDA","ROLANDA","LANETTE","JERILYN","GISELE","EVALYN","CYNDI","CLETA","CARIN","ZINA","ZENA","VELIA","TANIKA","PAUL","CHARISSA","THOMAS","TALIA","MARGARETE","LAVONDA","KAYLEE","KATHLENE","JONNA","IRENA","ILONA","IDALIA","CANDIS","CANDANCE","BRANDEE","ANITRA","ALIDA","SIGRID","NICOLETTE","MARYJO","LINETTE","HEDWIG","CHRISTIANA","CASSIDY","ALEXIA","TRESSIE","MODESTA","LUPITA","LITA","GLADIS","EVELIA","DAVIDA","CHERRI","CECILY","ASHELY","ANNABEL","AGUSTINA","WANITA","SHIRLY","ROSAURA","HULDA","EUN","BAILEY","YETTA","VERONA","THOMASINA","SIBYL","SHANNAN","MECHELLE","LUE","LEANDRA","LANI","KYLEE","KANDY","JOLYNN","FERNE","EBONI","CORENE","ALYSIA","ZULA","NADA","MOIRA","LYNDSAY","LORRETTA","JUAN","JAMMIE","HORTENSIA","GAYNELL","CAMERON","ADRIA","VINA","VICENTA","TANGELA","STEPHINE","NORINE","NELLA","LIANA","LESLEE","KIMBERELY","ILIANA","GLORY","FELICA","EMOGENE","ELFRIEDE","EDEN","EARTHA","CARMA","BEA","OCIE","MARRY","LENNIE","KIARA","JACALYN","CARLOTA","ARIELLE","YU","STAR","OTILIA","KIRSTIN","KACEY","JOHNETTA","JOEY","JOETTA","JERALDINE","JAUNITA","ELANA","DORTHEA","CAMI","AMADA","ADELIA","VERNITA","TAMAR","SIOBHAN","RENEA","RASHIDA","OUIDA","ODELL","NILSA","MERYL","KRISTYN","JULIETA","DANICA","BREANNE","AUREA","ANGLEA","SHERRON","ODETTE","MALIA","LORELEI","LIN","LEESA","KENNA","KATHLYN","FIONA","CHARLETTE","SUZIE","SHANTELL","SABRA","RACQUEL","MYONG","MIRA","MARTINE","LUCIENNE","LAVADA","JULIANN","JOHNIE","ELVERA","DELPHIA","CLAIR","CHRISTIANE","CHAROLETTE","CARRI","AUGUSTINE","ASHA","ANGELLA","PAOLA","NINFA","LEDA","LAI","EDA","SUNSHINE","STEFANI","SHANELL","PALMA","MACHELLE","LISSA","KECIA","KATHRYNE","KARLENE","JULISSA","JETTIE","JENNIFFER","HUI","CORRINA","CHRISTOPHER","CAROLANN","ALENA","TESS","ROSARIA","MYRTICE","MARYLEE","LIANE","KENYATTA","JUDIE","JANEY","IN","ELMIRA","ELDORA","DENNA","CRISTI","CATHI","ZAIDA","VONNIE","VIVA","VERNIE","ROSALINE","MARIELA","LUCIANA","LESLI","KARAN","FELICE","DENEEN","ADINA","WYNONA","TARSHA","SHERON","SHASTA","SHANITA","SHANI","SHANDRA","RANDA","PINKIE","PARIS","NELIDA","MARILOU","LYLA","LAURENE","LACI","JOI","JANENE","DOROTHA","DANIELE","DANI","CAROLYNN","CARLYN","BERENICE","AYESHA","ANNELIESE","ALETHEA","THERSA","TAMIKO","RUFINA","OLIVA","MOZELL","MARYLYN","MADISON","KRISTIAN","KATHYRN","KASANDRA","KANDACE","JANAE","GABRIEL","DOMENICA","DEBBRA","DANNIELLE","CHUN","BUFFY","BARBIE","ARCELIA","AJA","ZENOBIA","SHAREN","SHAREE","PATRICK","PAGE","MY","LAVINIA","KUM","KACIE","JACKELINE","HUONG","FELISA","EMELIA","ELEANORA","CYTHIA","CRISTIN","CLYDE","CLARIBEL","CARON","ANASTACIA","ZULMA","ZANDRA","YOKO","TENISHA","SUSANN","SHERILYN","SHAY","SHAWANDA","SABINE","ROMANA","MATHILDA","LINSEY","KEIKO","JOANA","ISELA","GRETTA","GEORGETTA","EUGENIE","DUSTY","DESIRAE","DELORA","CORAZON","ANTONINA","ANIKA","WILLENE","TRACEE","TAMATHA","REGAN","NICHELLE","MICKIE","MAEGAN","LUANA","LANITA","KELSIE","EDELMIRA","BREE","AFTON","TEODORA","TAMIE","SHENA","MEG","LINH","KELI","KACI","DANYELLE","BRITT","ARLETTE","ALBERTINE","ADELLE","TIFFINY","STORMY","SIMONA","NUMBERS","NICOLASA","NICHOL","NIA","NAKISHA","MEE","MAIRA","LOREEN","KIZZY","JOHNNY","JAY","FALLON","CHRISTENE","BOBBYE","ANTHONY","YING","VINCENZA","TANJA","RUBIE","RONI","QUEENIE","MARGARETT","KIMBERLI","IRMGARD","IDELL","HILMA","EVELINA","ESTA","EMILEE","DENNISE","DANIA","CARL","CARIE","ANTONIO","WAI","SANG","RISA","RIKKI","PARTICIA","MUI","MASAKO","MARIO","LUVENIA","LOREE","LONI","LIEN","KEVIN","GIGI","FLORENCIA","DORIAN","DENITA","DALLAS","CHI","BILLYE","ALEXANDER","TOMIKA","SHARITA","RANA","NIKOLE","NEOMA","MARGARITE","MADALYN","LUCINA","LAILA","KALI","JENETTE","GABRIELE","EVELYNE","ELENORA","CLEMENTINA","ALEJANDRINA","ZULEMA","VIOLETTE","VANNESSA","THRESA","RETTA","PIA","PATIENCE","NOELLA","NICKIE","JONELL","DELTA","CHUNG","CHAYA","CAMELIA","BETHEL","ANYA","ANDREW","THANH","SUZANN","SPRING","SHU","MILA","LILLA","LAVERNA","KEESHA","KATTIE","GIA","GEORGENE","EVELINE","ESTELL","ELIZBETH","VIVIENNE","VALLIE","TRUDIE","STEPHANE","MICHEL","MAGALY","MADIE","KENYETTA","KARREN","JANETTA","HERMINE","HARMONY","DRUCILLA","DEBBI","CELESTINA","CANDIE","BRITNI","BECKIE","AMINA","ZITA","YUN","YOLANDE","VIVIEN","VERNETTA","TRUDI","SOMMER","PEARLE","PATRINA","OSSIE","NICOLLE","LOYCE","LETTY","LARISA","KATHARINA","JOSELYN","JONELLE","JENELL","IESHA","HEIDE","FLORINDA","FLORENTINA","FLO","ELODIA","DORINE","BRUNILDA","BRIGID","ASHLI","ARDELLA","TWANA","THU","TARAH","SUNG","SHEA","SHAVON","SHANE","SERINA","RAYNA","RAMONITA","NGA","MARGURITE","LUCRECIA","KOURTNEY","KATI","JESUS","JESENIA","DIAMOND","CRISTA","AYANA","ALICA","ALIA","VINNIE","SUELLEN","ROMELIA","RACHELL","PIPER","OLYMPIA","MICHIKO","KATHALEEN","JOLIE","JESSI","JANESSA","HANA","HA","ELEASE","CARLETTA","BRITANY","SHONA","SALOME","ROSAMOND","REGENA","RAINA","NGOC","NELIA","LOUVENIA","LESIA","LATRINA","LATICIA","LARHONDA","JINA","JACKI","HOLLIS","HOLLEY","EMMY","DEEANN","CORETTA","ARNETTA","VELVET","THALIA","SHANICE","NETA","MIKKI","MICKI","LONNA","LEANA","LASHUNDA","KILEY","JOYE","JACQULYN","IGNACIA","HYUN","HIROKO","HENRY","HENRIETTE","ELAYNE","DELINDA","DARNELL","DAHLIA","COREEN","CONSUELA","CONCHITA","CELINE","BABETTE","AYANNA","ANETTE","ALBERTINA","SKYE","SHAWNEE","SHANEKA","QUIANA","PAMELIA","MIN","MERRI","MERLENE","MARGIT","KIESHA","KIERA","KAYLENE","JODEE","JENISE","ERLENE","EMMIE","ELSE","DARYL","DALILA","DAISEY","CODY","CASIE","BELIA","BABARA","VERSIE","VANESA","SHELBA","SHAWNDA","SAM","NORMAN","NIKIA","NAOMA","MARNA","MARGERET","MADALINE","LAWANA","KINDRA","JUTTA","JAZMINE","JANETT","HANNELORE","GLENDORA","GERTRUD","GARNETT","FREEDA","FREDERICA","FLORANCE","FLAVIA","DENNIS","CARLINE","BEVERLEE","ANJANETTE","VALDA","TRINITY","TAMALA","STEVIE","SHONNA","SHA","SARINA","ONEIDA","MICAH","MERILYN","MARLEEN","LURLINE","LENNA","KATHERIN","JIN","JENI","HAE","GRACIA","GLADY","FARAH","ERIC","ENOLA","EMA","DOMINQUE","DEVONA","DELANA","CECILA","CAPRICE","ALYSHA","ALI","ALETHIA","VENA","THERESIA","TAWNY","SONG","SHAKIRA","SAMARA","SACHIKO","RACHELE","PAMELLA","NICKY","MARNI","MARIEL","MAREN","MALISA","LIGIA","LERA","LATORIA","LARAE","KIMBER","KATHERN","KAREY","JENNEFER","JANETH","HALINA","FREDIA","DELISA","DEBROAH","CIERA","CHIN","ANGELIKA","ANDREE","ALTHA","YEN","VIVAN","TERRESA","TANNA","SUK","SUDIE","SOO","SIGNE","SALENA","RONNI","REBBECCA","MYRTIE","MCKENZIE","MALIKA","MAIDA","LOAN","LEONARDA","KAYLEIGH","FRANCE","ETHYL","ELLYN","DAYLE","CAMMIE","BRITTNI","BIRGIT","AVELINA","ASUNCION","ARIANNA","AKIKO","VENICE","TYESHA","TONIE","TIESHA","TAKISHA","STEFFANIE","SINDY","SANTANA","MEGHANN","MANDA","MACIE","LADY","KELLYE","KELLEE","JOSLYN","JASON","INGER","INDIRA","GLINDA","GLENNIS","FERNANDA","FAUSTINA","ENEIDA","ELICIA","DOT","DIGNA","DELL","ARLETTA","ANDRE","WILLIA","TAMMARA","TABETHA","SHERRELL","SARI","REFUGIO","REBBECA","PAULETTA","NIEVES","NATOSHA","NAKITA","MAMMIE","KENISHA","KAZUKO","KASSIE","GARY","EARLEAN","DAPHINE","CORLISS","CLOTILDE","CAROLYNE","BERNETTA","AUGUSTINA","AUDREA","ANNIS","ANNABELL","YAN","TENNILLE","TAMICA","SELENE","SEAN","ROSANA","REGENIA","QIANA","MARKITA","MACY","LEEANNE","LAURINE","KYM","JESSENIA","JANITA","GEORGINE","GENIE","EMIKO","ELVIE","DEANDRA","DAGMAR","CORIE","COLLEN","CHERISH","ROMAINE","PORSHA","PEARLENE","MICHELINE","MERNA","MARGORIE","MARGARETTA","LORE","KENNETH","JENINE","HERMINA","FREDERICKA","ELKE","DRUSILLA","DORATHY","DIONE","DESIRE","CELENA","BRIGIDA","ANGELES","ALLEGRA","THEO","TAMEKIA","SYNTHIA","STEPHEN","SOOK","SLYVIA","ROSANN","REATHA","RAYE","MARQUETTA","MARGART","LING","LAYLA","KYMBERLY","KIANA","KAYLEEN","KATLYN","KARMEN","JOELLA","IRINA","EMELDA","ELENI","DETRA","CLEMMIE","CHERYLL","CHANTELL","CATHEY","ARNITA","ARLA","ANGLE","ANGELIC","ALYSE","ZOFIA","THOMASINE","TENNIE","SON","SHERLY","SHERLEY","SHARYL","REMEDIOS","PETRINA","NICKOLE","MYUNG","MYRLE","MOZELLA","LOUANNE","LISHA","LATIA","LANE","KRYSTA","JULIENNE","JOEL","JEANENE","JACQUALINE","ISAURA","GWENDA","EARLEEN","DONALD","CLEOPATRA","CARLIE","AUDIE","ANTONIETTA","ALISE","ALEX","VERDELL","VAL","TYLER","TOMOKO","THAO","TALISHA","STEVEN","SO","SHEMIKA","SHAUN","SCARLET","SAVANNA","SANTINA","ROSIA","RAEANN","ODILIA","NANA","MINNA","MAGAN","LYNELLE","LE","KARMA","JOEANN","IVANA","INELL","ILANA","HYE","HONEY","HEE","GUDRUN","FRANK","DREAMA","CRISSY","CHANTE","CARMELINA","ARVILLA","ARTHUR","ANNAMAE","ALVERA","ALEIDA","AARON","YEE","YANIRA","VANDA","TIANNA","TAM","STEFANIA","SHIRA","PERRY","NICOL","NANCIE","MONSERRATE","MINH","MELYNDA","MELANY","MATTHEW","LOVELLA","LAURE","KIRBY","KACY","JACQUELYNN","HYON","GERTHA","FRANCISCO","ELIANA","CHRISTENA","CHRISTEEN","CHARISE","CATERINA","CARLEY","CANDYCE","ARLENA","AMMIE","YANG","WILLETTE","VANITA","TUYET","TINY","SYREETA","SILVA","SCOTT","RONALD","PENNEY","NYLA","MICHAL","MAURICE","MARYAM","MARYA","MAGEN","LUDIE","LOMA","LIVIA","LANELL","KIMBERLIE","JULEE","DONETTA","DIEDRA","DENISHA","DEANE","DAWNE","CLARINE","CHERRYL","BRONWYN","BRANDON","ALLA","VALERY","TONDA","SUEANN","SORAYA","SHOSHANA","SHELA","SHARLEEN","SHANELLE","NERISSA","MICHEAL","MERIDITH","MELLIE","MAYE","MAPLE","MAGARET","LUIS","LILI","LEONILA","LEONIE","LEEANNA","LAVONIA","LAVERA","KRISTEL","KATHEY","KATHE","JUSTIN","JULIAN","JIMMY","JANN","ILDA","HILDRED","HILDEGARDE","GENIA","FUMIKO","EVELIN","ERMELINDA","ELLY","DUNG","DOLORIS","DIONNA","DANAE","BERNEICE","ANNICE","ALIX","VERENA","VERDIE","TRISTAN","SHAWNNA","SHAWANA","SHAUNNA","ROZELLA","RANDEE","RANAE","MILAGRO","LYNELL","LUISE","LOUIE","LOIDA","LISBETH","KARLEEN","JUNITA","JONA","ISIS","HYACINTH","HEDY","GWENN","ETHELENE","ERLINE","EDWARD","DONYA","DOMONIQUE","DELICIA","DANNETTE","CICELY","BRANDA","BLYTHE","BETHANN","ASHLYN","ANNALEE","ALLINE","YUKO","VELLA","TRANG","TOWANDA","TESHA","SHERLYN","NARCISA","MIGUELINA","MERI","MAYBELL","MARLANA","MARGUERITA","MADLYN","LUNA","LORY","LORIANN","LIBERTY","LEONORE","LEIGHANN","LAURICE","LATESHA","LARONDA","KATRICE","KASIE","KARL","KALEY","JADWIGA","GLENNIE","GEARLDINE","FRANCINA","EPIFANIA","DYAN","DORIE","DIEDRE","DENESE","DEMETRICE","DELENA","DARBY","CRISTIE","CLEORA","CATARINA","CARISA","BERNIE","BARBERA","ALMETA","TRULA","TEREASA","SOLANGE","SHEILAH","SHAVONNE","SANORA","ROCHELL","MATHILDE","MARGARETA","MAIA","LYNSEY","LAWANNA","LAUNA","KENA","KEENA","KATIA","JAMEY","GLYNDA","GAYLENE","ELVINA","ELANOR","DANUTA","DANIKA","CRISTEN","CORDIE","COLETTA","CLARITA","CARMON","BRYNN","AZUCENA","AUNDREA","ANGELE","YI","WALTER","VERLIE","VERLENE","TAMESHA","SILVANA","SEBRINA","SAMIRA","REDA","RAYLENE","PENNI","PANDORA","NORAH","NOMA","MIREILLE","MELISSIA","MARYALICE","LARAINE","KIMBERY","KARYL","KARINE","KAM","JOLANDA","JOHANA","JESUSA","JALEESA","JAE","JACQUELYNE","IRISH","ILUMINADA","HILARIA","HANH","GENNIE","FRANCIE","FLORETTA","EXIE","EDDA","DREMA","DELPHA","BEV","BARBAR","ASSUNTA","ARDELL","ANNALISA","ALISIA","YUKIKO","YOLANDO","WONDA","WEI","WALTRAUD","VETA","TEQUILA","TEMEKA","TAMEIKA","SHIRLEEN","SHENITA","PIEDAD","OZELLA","MIRTHA","MARILU","KIMIKO","JULIANE","JENICE","JEN","JANAY","JACQUILINE","HILDE","FE","FAE","EVAN","EUGENE","ELOIS","ECHO","DEVORAH","CHAU","BRINDA","BETSEY","ARMINDA","ARACELIS","APRYL","ANNETT","ALISHIA","VEOLA","USHA","TOSHIKO","THEOLA","TASHIA","TALITHA","SHERY","RUDY","RENETTA","REIKO","RASHEEDA","OMEGA","OBDULIA","MIKA","MELAINE","MEGGAN","MARTIN","MARLEN","MARGET","MARCELINE","MANA","MAGDALEN","LIBRADA","LEZLIE","LEXIE","LATASHIA","LASANDRA","KELLE","ISIDRA","ISA","INOCENCIA","GWYN","FRANCOISE","ERMINIA","ERINN","DIMPLE","DEVORA","CRISELDA","ARMANDA","ARIE","ARIANE","ANGELO","ANGELENA","ALLEN","ALIZA","ADRIENE","ADALINE","XOCHITL","TWANNA","TRAN","TOMIKO","TAMISHA","TAISHA","SUSY","SIU","RUTHA","ROXY","RHONA","RAYMOND","OTHA","NORIKO","NATASHIA","MERRIE","MELVIN","MARINDA","MARIKO","MARGERT","LORIS","LIZZETTE","LEISHA","KAILA","KA","JOANNIE","JERRICA","JENE","JANNET","JANEE","JACINDA","HERTA","ELENORE","DORETTA","DELAINE","DANIELL","CLAUDIE","CHINA","BRITTA","APOLONIA","AMBERLY","ALEASE","YURI","YUK","WEN","WANETA","UTE","TOMI","SHARRI","SANDIE","ROSELLE","REYNALDA","RAGUEL","PHYLICIA","PATRIA","OLIMPIA","ODELIA","MITZIE","MITCHELL","MISS","MINDA","MIGNON","MICA","MENDY","MARIVEL","MAILE","LYNETTA","LAVETTE","LAURYN","LATRISHA","LAKIESHA","KIERSTEN","KARY","JOSPHINE","JOLYN","JETTA","JANISE","JACQUIE","IVELISSE","GLYNIS","GIANNA","GAYNELLE","EMERALD","DEMETRIUS","DANYELL","DANILLE","DACIA","CORALEE","CHER","CEOLA","BRETT","BELL","ARIANNE","ALESHIA","YUNG","WILLIEMAE","TROY","TRINH","THORA","TAI","SVETLANA","SHERIKA","SHEMEKA","SHAUNDA","ROSELINE","RICKI","MELDA","MALLIE","LAVONNA","LATINA","LARRY","LAQUANDA","LALA","LACHELLE","KLARA","KANDIS","JOHNA","JEANMARIE","JAYE","HANG","GRAYCE","GERTUDE","EMERITA","EBONIE","CLORINDA","CHING","CHERY","CAROLA","BREANN","BLOSSOM","BERNARDINE","BECKI","ARLETHA","ARGELIA","ARA","ALITA","YULANDA","YON","YESSENIA","TOBI","TASIA","SYLVIE","SHIRL","SHIRELY","SHERIDAN","SHELLA","SHANTELLE","SACHA","ROYCE","REBECKA","REAGAN","PROVIDENCIA","PAULENE","MISHA","MIKI","MARLINE","MARICA","LORITA","LATOYIA","LASONYA","KERSTIN","KENDA","KEITHA","KATHRIN","JAYMIE","JACK","GRICELDA","GINETTE","ERYN","ELINA","ELFRIEDA","DANYEL","CHEREE","CHANELLE","BARRIE","AVERY","AURORE","ANNAMARIA","ALLEEN","AILENE","AIDE","YASMINE","VASHTI","VALENTINE","TREASA","TORY","TIFFANEY","SHERYLL","SHARIE","SHANAE","SAU","RAISA","PA","NEDA","MITSUKO","MIRELLA","MILDA","MARYANNA","MARAGRET","MABELLE","LUETTA","LORINA","LETISHA","LATARSHA","LANELLE","LAJUANA","KRISSY","KARLY","KARENA","JON","JESSIKA","JERICA","JEANELLE","JANUARY","JALISA","JACELYN","IZOLA","IVEY","GREGORY","EUNA","ETHA","DREW","DOMITILA","DOMINICA","DAINA","CREOLA","CARLI","CAMIE","BUNNY","BRITTNY","ASHANTI","ANISHA","ALEEN","ADAH","YASUKO","WINTER","VIKI","VALRIE","TONA","TINISHA","THI","TERISA","TATUM","TANEKA","SIMONNE","SHALANDA","SERITA","RESSIE","REFUGIA","PAZ","OLENE","NA","MERRILL","MARGHERITA","MANDIE","MAN","MAIRE","LYNDIA","LUCI","LORRIANE","LORETA","LEONIA","LAVONA","LASHAWNDA","LAKIA","KYOKO","KRYSTINA","KRYSTEN","KENIA","KELSI","JUDE","JEANICE","ISOBEL","GEORGIANN","GENNY","FELICIDAD","EILENE","DEON","DELOISE","DEEDEE","DANNIE","CONCEPTION","CLORA","CHERILYN","CHANG","CALANDRA","BERRY","ARMANDINA","ANISA","ULA","TIMOTHY","TIERA","THERESSA","STEPHANIA","SIMA","SHYLA","SHONTA","SHERA","SHAQUITA","SHALA","SAMMY","ROSSANA","NOHEMI","NERY","MORIAH","MELITA","MELIDA","MELANI","MARYLYNN","MARISHA","MARIETTE","MALORIE","MADELENE","LUDIVINA","LORIA","LORETTE","LORALEE","LIANNE","LEON","LAVENIA","LAURINDA","LASHON","KIT","KIMI","KEILA","KATELYNN","KAI","JONE","JOANE","JI","JAYNA","JANELLA","JA","HUE","HERTHA","FRANCENE","ELINORE","DESPINA","DELSIE","DEEDRA","CLEMENCIA","CARRY","CAROLIN","CARLOS","BULAH","BRITTANIE","BOK","BLONDELL","BIBI","BEAULAH","BEATA","ANNITA","AGRIPINA","VIRGEN","VALENE","UN","TWANDA","TOMMYE","TOI","TARRA","TARI","TAMMERA","SHAKIA","SADYE","RUTHANNE","ROCHEL","RIVKA","PURA","NENITA","NATISHA","MING","MERRILEE","MELODEE","MARVIS","LUCILLA","LEENA","LAVETA","LARITA","LANIE","KEREN","ILEEN","GEORGEANN","GENNA","GENESIS","FRIDA","EWA","EUFEMIA","EMELY","ELA","EDYTH","DEONNA","DEADRA","DARLENA","CHANELL","CHAN","CATHERN","CASSONDRA","CASSAUNDRA","BERNARDA","BERNA","ARLINDA","ANAMARIA","ALBERT","WESLEY","VERTIE","VALERI","TORRI","TATYANA","STASIA","SHERISE","SHERILL","SEASON","SCOTTIE","SANDA","RUTHE","ROSY","ROBERTO","ROBBI","RANEE","QUYEN","PEARLY","PALMIRA","ONITA","NISHA","NIESHA","NIDA","NEVADA","NAM","MERLYN","MAYOLA","MARYLOUISE","MARYLAND","MARX","MARTH","MARGENE","MADELAINE","LONDA","LEONTINE","LEOMA","LEIA","LAWRENCE","LAURALEE","LANORA","LAKITA","KIYOKO","KETURAH","KATELIN","KAREEN","JONIE","JOHNETTE","JENEE","JEANETT","IZETTA","HIEDI","HEIKE","HASSIE","HAROLD","GIUSEPPINA","GEORGANN","FIDELA","FERNANDE","ELWANDA","ELLAMAE","ELIZ","DUSTI","DOTTY","CYNDY","CORALIE","CELESTA","ARGENTINA","ALVERTA","XENIA","WAVA","VANETTA","TORRIE","TASHINA","TANDY","TAMBRA","TAMA","STEPANIE","SHILA","SHAUNTA","SHARAN","SHANIQUA","SHAE","SETSUKO","SERAFINA","SANDEE","ROSAMARIA","PRISCILA","OLINDA","NADENE","MUOI","MICHELINA","MERCEDEZ","MARYROSE","MARIN","MARCENE","MAO","MAGALI","MAFALDA","LOGAN","LINN","LANNIE","KAYCE","KAROLINE","KAMILAH","KAMALA","JUSTA","JOLINE","JENNINE","JACQUETTA","IRAIDA","GERALD","GEORGEANNA","FRANCHESCA","FAIRY","EMELINE","ELANE","EHTEL","EARLIE","DULCIE","DALENE","CRIS","CLASSIE","CHERE","CHARIS","CAROYLN","CARMINA","CARITA","BRIAN","BETHANIE","AYAKO","ARICA","AN","ALYSA","ALESSANDRA","AKILAH","ADRIEN","ZETTA","YOULANDA","YELENA","YAHAIRA","XUAN","WENDOLYN","VICTOR","TIJUANA","TERRELL","TERINA","TERESIA","SUZI","SUNDAY","SHERELL","SHAVONDA","SHAUNTE","SHARDA","SHAKITA","SENA","RYANN","RUBI","RIVA","REGINIA","REA","RACHAL","PARTHENIA","PAMULA","MONNIE","MONET","MICHAELE","MELIA","MARINE","MALKA","MAISHA","LISANDRA","LEO","LEKISHA","LEAN","LAURENCE","LAKENDRA","KRYSTIN","KORTNEY","KIZZIE","KITTIE","KERA","KENDAL","KEMBERLY","KANISHA","JULENE","JULE","JOSHUA","JOHANNE","JEFFREY","JAMEE","HAN","HALLEY","GIDGET","GALINA","FREDRICKA","FLETA","FATIMAH","EUSEBIA","ELZA","ELEONORE","DORTHEY","DORIA","DONELLA","DINORAH","DELORSE","CLARETHA","CHRISTINIA","CHARLYN","BONG","BELKIS","AZZIE","ANDERA","AIKO","ADENA","YER","YAJAIRA","WAN","VANIA","ULRIKE","TOSHIA","TIFANY","STEFANY","SHIZUE","SHENIKA","SHAWANNA","SHAROLYN","SHARILYN","SHAQUANA","SHANTAY","SEE","ROZANNE","ROSELEE","RICKIE","REMONA","REANNA","RAELENE","QUINN","PHUNG","PETRONILA","NATACHA","NANCEY","MYRL","MIYOKO","MIESHA","MERIDETH","MARVELLA","MARQUITTA","MARHTA","MARCHELLE","LIZETH","LIBBIE","LAHOMA","LADAWN","KINA","KATHELEEN","KATHARYN","KARISA","KALEIGH","JUNIE","JULIEANN","JOHNSIE","JANEAN","JAIMEE","JACKQUELINE","HISAKO","HERMA","HELAINE","GWYNETH","GLENN","GITA","EUSTOLIA","EMELINA","ELIN","EDRIS","DONNETTE","DONNETTA","DIERDRE","DENAE","DARCEL","CLAUDE","CLARISA","CINDERELLA","CHIA","CHARLESETTA","CHARITA","CELSA","CASSY","CASSI","CARLEE","BRUNA","BRITTANEY","BRANDE","BILLI","BAO","ANTONETTA","ANGLA","ANGELYN","ANALISA","ALANE","WENONA","WENDIE","VERONIQUE","VANNESA","TOBIE","TEMPIE","SUMIKO","SULEMA","SPARKLE","SOMER","SHEBA","SHAYNE","SHARICE","SHANEL","SHALON","SAGE","ROY","ROSIO","ROSELIA","RENAY","REMA","REENA","PORSCHE","PING","PEG","OZIE","ORETHA","ORALEE","ODA","NU","NGAN","NAKESHA","MILLY","MARYBELLE","MARLIN","MARIS","MARGRETT","MARAGARET","MANIE","LURLENE","LILLIA","LIESELOTTE","LAVELLE","LASHAUNDA","LAKEESHA","KEITH","KAYCEE","KALYN","JOYA","JOETTE","JENAE","JANIECE","ILLA","GRISEL","GLAYDS","GENEVIE","GALA","FREDDA","FRED","ELMER","ELEONOR","DEBERA","DEANDREA","DAN","CORRINNE","CORDIA","CONTESSA","COLENE","CLEOTILDE","CHARLOTT","CHANTAY","CECILLE","BEATRIS","AZALEE","ARLEAN","ARDATH","ANJELICA","ANJA","ALFREDIA","ALEISHA","ADAM","ZADA","YUONNE","XIAO","WILLODEAN","WHITLEY","VENNIE","VANNA","TYISHA","TOVA","TORIE","TONISHA","TILDA","TIEN","TEMPLE","SIRENA","SHERRIL","SHANTI","SHAN","SENAIDA","SAMELLA","ROBBYN","RENDA","REITA","PHEBE","PAULITA","NOBUKO","NGUYET","NEOMI","MOON","MIKAELA","MELANIA","MAXIMINA","MARG","MAISIE","LYNNA","LILLI","LAYNE","LASHAUN","LAKENYA","LAEL","KIRSTIE","KATHLINE","KASHA","KARLYN","KARIMA","JOVAN","JOSEFINE","JENNELL","JACQUI","JACKELYN","HYO","HIEN","GRAZYNA","FLORRIE","FLORIA","ELEONORA","DWANA","DORLA","DONG","DELMY","DEJA","DEDE","DANN","CRYSTA","CLELIA","CLARIS","CLARENCE","CHIEKO","CHERLYN","CHERELLE","CHARMAIN","CHARA","CAMMY","BEE","ARNETTE","ARDELLE","ANNIKA","AMIEE","AMEE","ALLENA","YVONE","YUKI","YOSHIE","YEVETTE","YAEL","WILLETTA","VONCILE","VENETTA","TULA","TONETTE","TIMIKA","TEMIKA","TELMA","TEISHA","TAREN","TA","STACEE","SHIN","SHAWNTA","SATURNINA","RICARDA","POK","PASTY","ONIE","NUBIA","MORA","MIKE","MARIELLE","MARIELLA","MARIANELA","MARDELL","MANY","LUANNA","LOISE","LISABETH","LINDSY","LILLIANA","LILLIAM","LELAH","LEIGHA","LEANORA","LANG","KRISTEEN","KHALILAH","KEELEY","KANDRA","JUNKO","JOAQUINA","JERLENE","JANI","JAMIKA","JAME","HSIU","HERMILA","GOLDEN","GENEVIVE","EVIA","EUGENA","EMMALINE","ELFREDA","ELENE","DONETTE","DELCIE","DEEANNA","DARCEY","CUC","CLARINDA","CIRA","CHAE","CELINDA","CATHERYN","CATHERIN","CASIMIRA","CARMELIA","CAMELLIA","BREANA","BOBETTE","BERNARDINA","BEBE","BASILIA","ARLYNE","AMAL","ALAYNA","ZONIA","ZENIA","YURIKO","YAEKO","WYNELL","WILLOW","WILLENA","VERNIA","TU","TRAVIS","TORA","TERRILYN","TERICA","TENESHA","TAWNA","TAJUANA","TAINA","STEPHNIE","SONA","SOL","SINA","SHONDRA","SHIZUKO","SHERLENE","SHERICE","SHARIKA","ROSSIE","ROSENA","RORY","RIMA","RIA","RHEBA","RENNA","PETER","NATALYA","NANCEE","MELODI","MEDA","MAXIMA","MATHA","MARKETTA","MARICRUZ","MARCELENE","MALVINA","LUBA","LOUETTA","LEIDA","LECIA","LAURAN","LASHAWNA","LAINE","KHADIJAH","KATERINE","KASI","KALLIE","JULIETTA","JESUSITA","JESTINE","JESSIA","JEREMY","JEFFIE","JANYCE","ISADORA","GEORGIANNE","FIDELIA","EVITA","EURA","EULAH","ESTEFANA","ELSY","ELIZABET","ELADIA","DODIE","DION","DIA","DENISSE","DELORAS","DELILA","DAYSI","DAKOTA","CURTIS","CRYSTLE","CONCHA","COLBY","CLARETTA","CHU","CHRISTIA","CHARLSIE","CHARLENA","CARYLON","BETTYANN","ASLEY","ASHLEA","AMIRA","AI","AGUEDA","AGNUS","YUETTE","VINITA","VICTORINA","TYNISHA","TREENA","TOCCARA","TISH","THOMASENA","TEGAN","SOILA","SHILOH","SHENNA","SHARMAINE","SHANTAE","SHANDI","SEPTEMBER","SARAN","SARAI","SANA","SAMUEL","SALLEY","ROSETTE","ROLANDE","REGINE","OTELIA","OSCAR","OLEVIA","NICHOLLE","NECOLE","NAIDA","MYRTA","MYESHA","MITSUE","MINTA","MERTIE","MARGY","MAHALIA","MADALENE","LOVE","LOURA","LOREAN","LEWIS","LESHA","LEONIDA","LENITA","LAVONE","LASHELL","LASHANDRA","LAMONICA","KIMBRA","KATHERINA","KARRY","KANESHA","JULIO","JONG","JENEVA","JAQUELYN","HWA","GILMA","GHISLAINE","GERTRUDIS","FRANSISCA","FERMINA","ETTIE","ETSUKO","ELLIS","ELLAN","ELIDIA","EDRA","DORETHEA","DOREATHA","DENYSE","DENNY","DEETTA","DAINE","CYRSTAL","CORRIN","CAYLA","CARLITA","CAMILA","BURMA","BULA","BUENA","BLAKE","BARABARA","AVRIL","AUSTIN","ALAINE","ZANA","WILHEMINA","WANETTA","VIRGIL","VI","VERONIKA","VERNON","VERLINE","VASILIKI","TONITA","TISA","TEOFILA","TAYNA","TAUNYA","TANDRA","TAKAKO","SUNNI","SUANNE","SIXTA","SHARELL","SEEMA","RUSSELL","ROSENDA","ROBENA","RAYMONDE","PEI","PAMILA","OZELL","NEIDA","NEELY","MISTIE","MICHA","MERISSA","MAURITA","MARYLN","MARYETTA","MARSHALL","MARCELL","MALENA","MAKEDA","MADDIE","LOVETTA","LOURIE","LORRINE","LORILEE","LESTER","LAURENA","LASHAY","LARRAINE","LAREE","LACRESHA","KRISTLE","KRISHNA","KEVA","KEIRA","KAROLE","JOIE","JINNY","JEANNETTA","JAMA","HEIDY","GILBERTE","GEMA","FAVIOLA","EVELYNN","ENDA","ELLI","ELLENA","DIVINA","DAGNY","COLLENE","CODI","CINDIE","CHASSIDY","CHASIDY","CATRICE","CATHERINA","CASSEY","CAROLL","CARLENA","CANDRA","CALISTA","BRYANNA","BRITTENY","BEULA","BARI","AUDRIE","AUDRIA","ARDELIA","ANNELLE","ANGILA","ALONA","ALLYN","DOUGLAS","ROGER","JONATHAN","RALPH","NICHOLAS","BENJAMIN","BRUCE","HARRY","WAYNE","STEVE","HOWARD","ERNEST","PHILLIP","TODD","CRAIG","ALAN","PHILIP","EARL","DANNY","BRYAN","STANLEY","LEONARD","NATHAN","MANUEL","RODNEY","MARVIN","VINCENT","JEFFERY","JEFF","CHAD","JACOB","ALFRED","BRADLEY","HERBERT","FREDERICK","EDWIN","DON","RICKY","RANDALL","BARRY","BERNARD","LEROY","MARCUS","THEODORE","CLIFFORD","MIGUEL","JIM","TOM","CALVIN","BILL","LLOYD","DEREK","WARREN","DARRELL","JEROME","FLOYD","ALVIN","TIM","GORDON","GREG","JORGE","DUSTIN","PEDRO","DERRICK","ZACHARY","HERMAN","GLEN","HECTOR","RICARDO","RICK","BRENT","RAMON","GILBERT","MARC","REGINALD","RUBEN","NATHANIEL","RAFAEL","EDGAR","MILTON","RAUL","BEN","CHESTER","DUANE","FRANKLIN","BRAD","RON","ROLAND","ARNOLD","HARVEY","JARED","ERIK","DARRYL","NEIL","JAVIER","FERNANDO","CLINTON","TED","MATHEW","TYRONE","DARREN","LANCE","KURT","ALLAN","NELSON","GUY","CLAYTON","HUGH","MAX","DWAYNE","DWIGHT","ARMANDO","FELIX","EVERETT","IAN","WALLACE","KEN","BOB","ALFREDO","ALBERTO","DAVE","IVAN","BYRON","ISAAC","MORRIS","CLIFTON","WILLARD","ROSS","ANDY","SALVADOR","KIRK","SERGIO","SETH","KENT","TERRANCE","EDUARDO","TERRENCE","ENRIQUE","WADE","STUART","FREDRICK","ARTURO","ALEJANDRO","NICK","LUTHER","WENDELL","JEREMIAH","JULIUS","OTIS","TREVOR","OLIVER","LUKE","HOMER","GERARD","DOUG","KENNY","HUBERT","LYLE","MATT","ALFONSO","ORLANDO","REX","CARLTON","ERNESTO","NEAL","PABLO","LORENZO","OMAR","WILBUR","GRANT","HORACE","RODERICK","ABRAHAM","WILLIS","RICKEY","ANDRES","CESAR","JOHNATHAN","MALCOLM","RUDOLPH","DAMON","KELVIN","PRESTON","ALTON","ARCHIE","MARCO","WM","PETE","RANDOLPH","GARRY","GEOFFREY","JONATHON","FELIPE","GERARDO","ED","DOMINIC","DELBERT","COLIN","GUILLERMO","EARNEST","LUCAS","BENNY","SPENCER","RODOLFO","MYRON","EDMUND","GARRETT","SALVATORE","CEDRIC","LOWELL","GREGG","SHERMAN","WILSON","SYLVESTER","ROOSEVELT","ISRAEL","JERMAINE","FORREST","WILBERT","LELAND","SIMON","CLARK","IRVING","BRYANT","OWEN","RUFUS","WOODROW","KRISTOPHER","MACK","LEVI","MARCOS","GUSTAVO","JAKE","LIONEL","GILBERTO","CLINT","NICOLAS","ISMAEL","ORVILLE","ERVIN","DEWEY","AL","WILFRED","JOSH","HUGO","IGNACIO","CALEB","TOMAS","SHELDON","ERICK","STEWART","DOYLE","DARREL","ROGELIO","TERENCE","SANTIAGO","ALONZO","ELIAS","BERT","ELBERT","RAMIRO","CONRAD","NOAH","GRADY","PHIL","CORNELIUS","LAMAR","ROLANDO","CLAY","PERCY","DEXTER","BRADFORD","DARIN","AMOS","MOSES","IRVIN","SAUL","ROMAN","RANDAL","TIMMY","DARRIN","WINSTON","BRENDAN","ABEL","DOMINICK","BOYD","EMILIO","ELIJAH","DOMINGO","EMMETT","MARLON","EMANUEL","JERALD","EDMOND","EMIL","DEWAYNE","WILL","OTTO","TEDDY","REYNALDO","BRET","JESS","TRENT","HUMBERTO","EMMANUEL","STEPHAN","VICENTE","LAMONT","GARLAND","MILES","EFRAIN","HEATH","RODGER","HARLEY","ETHAN","ELDON","ROCKY","PIERRE","JUNIOR","FREDDY","ELI","BRYCE","ANTOINE","STERLING","CHASE","GROVER","ELTON","CLEVELAND","DYLAN","CHUCK","DAMIAN","REUBEN","STAN","AUGUST","LEONARDO","JASPER","RUSSEL","ERWIN","BENITO","HANS","MONTE","BLAINE","ERNIE","CURT","QUENTIN","AGUSTIN","MURRAY","JAMAL","ADOLFO","HARRISON","TYSON","BURTON","BRADY","ELLIOTT","WILFREDO","BART","JARROD","VANCE","DENIS","DAMIEN","JOAQUIN","HARLAN","DESMOND","ELLIOT","DARWIN","GREGORIO","BUDDY","XAVIER","KERMIT","ROSCOE","ESTEBAN","ANTON","SOLOMON","SCOTTY","NORBERT","ELVIN","WILLIAMS","NOLAN","ROD","QUINTON","HAL","BRAIN","ROB","ELWOOD","KENDRICK","DARIUS","MOISES","FIDEL","THADDEUS","CLIFF","MARCEL","JACKSON","RAPHAEL","BRYON","ARMAND","ALVARO","JEFFRY","DANE","JOESPH","THURMAN","NED","RUSTY","MONTY","FABIAN","REGGIE","MASON","GRAHAM","ISAIAH","VAUGHN","GUS","LOYD","DIEGO","ADOLPH","NORRIS","MILLARD","ROCCO","GONZALO","DERICK","RODRIGO","WILEY","RIGOBERTO","ALPHONSO","TY","NOE","VERN","REED","JEFFERSON","ELVIS","BERNARDO","MAURICIO","HIRAM","DONOVAN","BASIL","RILEY","NICKOLAS","MAYNARD","SCOT","VINCE","QUINCY","EDDY","SEBASTIAN","FEDERICO","ULYSSES","HERIBERTO","DONNELL","COLE","DAVIS","GAVIN","EMERY","WARD","ROMEO","JAYSON","DANTE","CLEMENT","COY","MAXWELL","JARVIS","BRUNO","ISSAC","DUDLEY","BROCK","SANFORD","CARMELO","BARNEY","NESTOR","STEFAN","DONNY","ART","LINWOOD","BEAU","WELDON","GALEN","ISIDRO","TRUMAN","DELMAR","JOHNATHON","SILAS","FREDERIC","DICK","IRWIN","MERLIN","CHARLEY","MARCELINO","HARRIS","CARLO","TRENTON","KURTIS","HUNTER","AURELIO","WINFRED","VITO","COLLIN","DENVER","CARTER","LEONEL","EMORY","PASQUALE","MOHAMMAD","MARIANO","DANIAL","LANDON","DIRK","BRANDEN","ADAN","BUFORD","GERMAN","WILMER","EMERSON","ZACHERY","FLETCHER","JACQUES","ERROL","DALTON","MONROE","JOSUE","EDWARDO","BOOKER","WILFORD","SONNY","SHELTON","CARSON","THERON","RAYMUNDO","DAREN","HOUSTON","ROBBY","LINCOLN","GENARO","BENNETT","OCTAVIO","CORNELL","HUNG","ARRON","ANTONY","HERSCHEL","GIOVANNI","GARTH","CYRUS","CYRIL","RONNY","LON","FREEMAN","DUNCAN","KENNITH","CARMINE","ERICH","CHADWICK","WILBURN","RUSS","REID","MYLES","ANDERSON","MORTON","JONAS","FOREST","MITCHEL","MERVIN","ZANE","RICH","JAMEL","LAZARO","ALPHONSE","RANDELL","MAJOR","JARRETT","BROOKS","ABDUL","LUCIANO","SEYMOUR","EUGENIO","MOHAMMED","VALENTIN","CHANCE","ARNULFO","LUCIEN","FERDINAND","THAD","EZRA","ALDO","RUBIN","ROYAL","MITCH","EARLE","ABE","WYATT","MARQUIS","LANNY","KAREEM","JAMAR","BORIS","ISIAH","EMILE","ELMO","ARON","LEOPOLDO","EVERETTE","JOSEF","ELOY","RODRICK","REINALDO","LUCIO","JERROD","WESTON","HERSHEL","BARTON","PARKER","LEMUEL","BURT","JULES","GIL","ELISEO","AHMAD","NIGEL","EFREN","ANTWAN","ALDEN","MARGARITO","COLEMAN","DINO","OSVALDO","LES","DEANDRE","NORMAND","KIETH","TREY","NORBERTO","NAPOLEON","JEROLD","FRITZ","ROSENDO","MILFORD","CHRISTOPER","ALFONZO","LYMAN","JOSIAH","BRANT","WILTON","RICO","JAMAAL","DEWITT","BRENTON","OLIN","FOSTER","FAUSTINO","CLAUDIO","JUDSON","GINO","EDGARDO","ALEC","TANNER","JARRED","DONN","TAD","PRINCE","PORFIRIO","ODIS","LENARD","CHAUNCEY","TOD","MEL","MARCELO","KORY","AUGUSTUS","KEVEN","HILARIO","BUD","SAL","ORVAL","MAURO","ZACHARIAH","OLEN","ANIBAL","MILO","JED","DILLON","AMADO","NEWTON","LENNY","RICHIE","HORACIO","BRICE","MOHAMED","DELMER","DARIO","REYES","MAC","JONAH","JERROLD","ROBT","HANK","RUPERT","ROLLAND","KENTON","DAMION","ANTONE","WALDO","FREDRIC","BRADLY","KIP","BURL","WALKER","TYREE","JEFFEREY","AHMED","WILLY","STANFORD","OREN","NOBLE","MOSHE","MIKEL","ENOCH","BRENDON","QUINTIN","JAMISON","FLORENCIO","DARRICK","TOBIAS","HASSAN","GIUSEPPE","DEMARCUS","CLETUS","TYRELL","LYNDON","KEENAN","WERNER","GERALDO","COLUMBUS","CHET","BERTRAM","MARKUS","HUEY","HILTON","DWAIN","DONTE","TYRON","OMER","ISAIAS","HIPOLITO","FERMIN","ADALBERTO","BO","BARRETT","TEODORO","MCKINLEY","MAXIMO","GARFIELD","RALEIGH","LAWERENCE","ABRAM","RASHAD","KING","EMMITT","DARON","SAMUAL","MIQUEL","EUSEBIO","DOMENIC","DARRON","BUSTER","WILBER","RENATO","JC","HOYT","HAYWOOD","EZEKIEL","CHAS","FLORENTINO","ELROY","CLEMENTE","ARDEN","NEVILLE","EDISON","DESHAWN","NATHANIAL","JORDON","DANILO","CLAUD","SHERWOOD","RAYMON","RAYFORD","CRISTOBAL","AMBROSE","TITUS","HYMAN","FELTON","EZEQUIEL","ERASMO","STANTON","LONNY","LEN","IKE","MILAN","LINO","JAROD","HERB","ANDREAS","WALTON","RHETT","PALMER","DOUGLASS","CORDELL","OSWALDO","ELLSWORTH","VIRGILIO","TONEY","NATHANAEL","DEL","BENEDICT","MOSE","JOHNSON","ISREAL","GARRET","FAUSTO","ASA","ARLEN","ZACK","WARNER","MODESTO","FRANCESCO","MANUAL","GAYLORD","GASTON","FILIBERTO","DEANGELO","MICHALE","GRANVILLE","WES","MALIK","ZACKARY","TUAN","ELDRIDGE","CRISTOPHER","CORTEZ","ANTIONE","MALCOM","LONG","KOREY","JOSPEH","COLTON","WAYLON","VON","HOSEA","SHAD","SANTO","RUDOLF","ROLF","REY","RENALDO","MARCELLUS","LUCIUS","KRISTOFER","BOYCE","BENTON","HAYDEN","HARLAND","ARNOLDO","RUEBEN","LEANDRO","KRAIG","JERRELL","JEROMY","HOBERT","CEDRICK","ARLIE","WINFORD","WALLY","LUIGI","KENETH","JACINTO","GRAIG","FRANKLYN","EDMUNDO","SID","PORTER","LEIF","JERAMY","BUCK","WILLIAN","VINCENZO","SHON","LYNWOOD","JERE","HAI","ELDEN","DORSEY","DARELL","BRODERICK","ALONSO" \ No newline at end of file diff --git a/src/further_examples/project_euler/names_score.py b/src/further_examples/project_euler/names_score.py new file mode 100644 index 0000000..7c2f1bb --- /dev/null +++ b/src/further_examples/project_euler/names_score.py @@ -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() + diff --git a/src/further_examples/project_euler/non_abund_sums.py b/src/further_examples/project_euler/non_abund_sums.py new file mode 100644 index 0000000..2f9e496 --- /dev/null +++ b/src/further_examples/project_euler/non_abund_sums.py @@ -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_() + diff --git a/src/further_examples/project_euler/number_letter_counts.py b/src/further_examples/project_euler/number_letter_counts.py new file mode 100644 index 0000000..8b1b43b --- /dev/null +++ b/src/further_examples/project_euler/number_letter_counts.py @@ -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() + diff --git a/src/further_examples/project_euler/number_spiral.py b/src/further_examples/project_euler/number_spiral.py new file mode 100644 index 0000000..387146d --- /dev/null +++ b/src/further_examples/project_euler/number_spiral.py @@ -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() + diff --git a/src/further_examples/project_euler/path_sum_two_ways.py~ b/src/further_examples/project_euler/path_sum_two_ways.py~ new file mode 100644 index 0000000..cb3aaa1 --- /dev/null +++ b/src/further_examples/project_euler/path_sum_two_ways.py~ @@ -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() + diff --git a/src/further_examples/project_euler/power_digit_sum.py b/src/further_examples/project_euler/power_digit_sum.py new file mode 100644 index 0000000..a47d1db --- /dev/null +++ b/src/further_examples/project_euler/power_digit_sum.py @@ -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_() + diff --git a/src/further_examples/project_euler/quad_primes.py b/src/further_examples/project_euler/quad_primes.py new file mode 100644 index 0000000..af84e3f --- /dev/null +++ b/src/further_examples/project_euler/quad_primes.py @@ -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() + diff --git a/src/further_examples/project_euler/self_powers.py b/src/further_examples/project_euler/self_powers.py new file mode 100644 index 0000000..1fb2420 --- /dev/null +++ b/src/further_examples/project_euler/self_powers.py @@ -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() + diff --git a/src/further_examples/project_euler/smallest_multiple.py b/src/further_examples/project_euler/smallest_multiple.py new file mode 100644 index 0000000..23d3e4e --- /dev/null +++ b/src/further_examples/project_euler/smallest_multiple.py @@ -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_() diff --git a/src/further_examples/project_euler/special_pyt.py b/src/further_examples/project_euler/special_pyt.py new file mode 100644 index 0000000..2fa2dde --- /dev/null +++ b/src/further_examples/project_euler/special_pyt.py @@ -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() + diff --git a/src/further_examples/project_euler/square_dig_chains.py b/src/further_examples/project_euler/square_dig_chains.py new file mode 100644 index 0000000..12b67b2 --- /dev/null +++ b/src/further_examples/project_euler/square_dig_chains.py @@ -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() + diff --git a/src/further_examples/project_euler/sum_square_diff.py b/src/further_examples/project_euler/sum_square_diff.py new file mode 100644 index 0000000..8cbc368 --- /dev/null +++ b/src/further_examples/project_euler/sum_square_diff.py @@ -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() + diff --git a/src/further_examples/project_euler/summation_primes.py b/src/further_examples/project_euler/summation_primes.py new file mode 100644 index 0000000..fb53b56 --- /dev/null +++ b/src/further_examples/project_euler/summation_primes.py @@ -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() + diff --git a/src/further_examples/top_coder/tco2013_round3_3b_div1.py b/src/further_examples/top_coder/tco2013_round3_3b_div1.py new file mode 100644 index 0000000..491ab8f --- /dev/null +++ b/src/further_examples/top_coder/tco2013_round3_3b_div1.py @@ -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() +