diff --git a/.coveragerc b/.coveragerc new file mode 100644 index 0000000..7f4efff --- /dev/null +++ b/.coveragerc @@ -0,0 +1,33 @@ +[run] +source = + src/weighted_graph.py + src/weighted_traversal.py + +omit = + src/priorityq.py + src/deque.py + src/que_.py + src/stack.py + src/binheap.py + src/dijkstra.py + src/graph_1.py + src/graph_2.py + src/dll.py + src/linked_list.py + src/reverse_linked_list.py + src/test_dll.py + src/test_binheap.py + src/test_deque.py + src/test_dijkstra.py + src/test_graph.py + src/test_graph_2.py + src/test_linked_list.py + src/test_priority_que.py + src/test_que_.py + src/test_reverse_linked_list.py + src/test_stack.py + src/test_weighted_graph.py + src/test_weighted_traversal.py + +[report] +show_missing = True \ No newline at end of file diff --git a/README.md b/README.md index 4a6fc0f..22c1dfb 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,11 @@ Data Structures for Python 401 #Used the shift and pop methods from our double linked list in dll.py. +##Deque Branch +#Implement a dequeue data structure that has pop, popleft, append, appendleft, +#peek, peekleft, and size methods. Implemented using a composition of double linked +#list. + ##Binary Heap Branch #Implement a pop() and push() function for this exercise. #Worked on initialization and implementation of our the data structure itself. diff --git a/setup.py b/setup.py index 97eb6a0..19c3a3f 100644 --- a/setup.py +++ b/setup.py @@ -3,7 +3,7 @@ extra_packages = { - 'testing': ['pytest', 'pytest-watch', 'pytest-cov', 'tox'] + 'testing': ['pytest-cov', 'tox'] } @@ -14,12 +14,6 @@ author="Kurt Maurer" "Anna Shelby", author_email="bonanashelby@gmail.com", license="MIT", - py_modules=["server, client"], - package_dir={'': 'src'}, install_requires=["ipython", "pytest"], - extras_require=extra_packages, - entry_points={ - 'console_scripts': [ - ] - } + extras_require=extra_packages ) diff --git a/src/deque.py b/src/deque.py index 0d97249..58f35dc 100644 --- a/src/deque.py +++ b/src/deque.py @@ -25,14 +25,14 @@ def popleft(self): """Shift for popleft.""" return self._new_dll.shift() - def peek(self): # pragma no cover + def peek(self): """Return a new value without dequeuing it.""" - print(self._new_dll.head.data) + return self._new_dll.head.data - def peekleft(self): # pragma no cover + def peekleft(self): """Return a new value from the left without dequeing it.""" - print(self._new_dll.tail.data) + return self._new_dll.tail.data - def __len__(self): + def size(self): """Length function for the queue.""" - return len(self._new_dll) + return self._new_dll.size() diff --git a/src/dijkstra.py b/src/dijkstra.py new file mode 100644 index 0000000..5aa6997 --- /dev/null +++ b/src/dijkstra.py @@ -0,0 +1,27 @@ +"""Dijkstra algorithm for our shortest path graph.""" +from weighted_graph import Weighted +from priorityq import PriorityQueue + +# {'A':{'B': 7, 'C': 9}, 'B': {'D': 2, 'E': 4}, 'C': {'F': 6}, 'D':{}, 'E': {}, 'F': {}} + + +def dijkstra(weighted_graph, start_node): + """Find the shortest path to nodes from starting node.""" + if not weighted_graph.has_node(start_node): + raise IndexError('Node not in this weighted graph.') + current_node = {start_node: 0} + visited = {} + priorityq = PriorityQueue() + priorityq.insert(current_node, 0) + while len(priorityq) > 0: + current_node = priorityq.pop() + next_nodes = weighted_graph[list(current_node.keys())[0]] + for key, value in next_nodes.items(): + distance_from_start_node = value + list(current_node.values())[0] + priorityq.insert( + {key: distance_from_start_node}, distance_from_start_node + ) + if key in visited and distance_from_start_node > visited[key]: + continue + visited.update({key: distance_from_start_node}) + return visited diff --git a/src/dll.py b/src/dll.py index 19c48b1..8716d3f 100644 --- a/src/dll.py +++ b/src/dll.py @@ -24,29 +24,27 @@ def push(self, val): """Push a value to the head of the list.""" if not val: raise TypeError('Please provide a not null value.') - self._length += 1 if self.tail is None and self.head is None: new_node = Node(val) - self.tail = new_node - self.head = new_node + self.tail = self.head = new_node else: new_node = Node(val, None, self.head) self.head.next_node = new_node self.head = new_node + self._length += 1 def append(self, val): """Append a val to the tail of a list.""" if not val: raise TypeError('Please provide a not null value.') - self._length += 1 if self.tail is None and self.head is None: new_node = Node(val) - self.tail = new_node - self.head = new_node + self.tail = self.head = new_node else: new_node = Node(val, self.tail, None) self.tail.prior_node = new_node self.tail = new_node + self._length += 1 def pop(self): """Pop pops from the head of the list.""" @@ -56,45 +54,40 @@ def pop(self): self._length -= 1 if self.head == self.tail: last_pop = self.head - self.head = None - self.tail = None + self.tail = self.head = None return last_pop.data popped = self.head self.head = self.head.prior_node - popped.prior_node = None self.head.next_node = None return popped.data def shift(self): """Remove the node from the tail of the list.""" - if not self.head: + if not self.tail: raise IndexError( 'There\'s nothing to remove from the linked list.') self._length -= 1 if self.head == self.tail: last_pop = self.head - self.head = None - self.tail = None + self.tail = self.head = None return last_pop.data shifted = self.tail self.tail = self.tail.next_node - shifted.next_node = None self.tail.prior_node = None return shifted.data - def __len__(self): + def size(self): """Return the length of the double linked list.""" return self._length def remove(self, val): """Remove a node with the value provided.""" - if val is None: - raise TypeError( - 'That value is not in this particular linked list.') if self.head.data == val: self.pop() + return elif self.tail.data == val: self.shift() + return current_node = self.head while current_node is not None: if current_node.data != val: @@ -102,9 +95,7 @@ def remove(self, val): else: new_next_node = current_node.next_node new_prior_node = current_node.prior_node - current_node.next_node.prior_node = new_prior_node - current_node.prior_node.next_node = new_next_node - current_node.next_node = None - current_node.prior_node = None + new_next_node.prior_node = new_prior_node + new_prior_node.next_node = new_next_node self._length -= 1 break diff --git a/src/linked_list.py b/src/linked_list.py index 8705d9a..4eff6e9 100644 --- a/src/linked_list.py +++ b/src/linked_list.py @@ -43,10 +43,14 @@ def pop(self): self._length -= 1 return popped.data - def __len__(self): + def size(self): """Return the length of the linked list.""" return self._length + def __len__(self): + """Interact with built-in len() function.""" + return self.size() + def search(self, val): """Search the nodes for the value provided.""" current_node = self.head @@ -56,7 +60,7 @@ def search(self, val): else: return current_node.data else: - return None + return def remove(self, val): """Removenode from anywhere in the linked list with the given value.""" @@ -65,18 +69,20 @@ def remove(self, val): 'That value is not in this particular linked list.') if self.head.data == val: self.pop() - return None + return current_node = self.head + previous_node = self.head while current_node is not None: - if current_node.next_node.data != val: + if current_node.data != val: + previous_node = current_node current_node = current_node.next_node + continue else: - removed_node = current_node.next_node - current_node.next_node = current_node.next_node.next_node + previous_node.next_node = current_node.next_node self._length -= 1 - if removed_node.next_node is not None: - removed_node.next_node = None break + else: + raise ValueError('Value not found.') def display(self): """Present a visual representation of the linked list.""" @@ -84,7 +90,13 @@ def display(self): display_str = ' ' while node is not None: display_str += ' ' + display_str += '\'' display_str += str(node.data) + display_str += '\'' node = node.next_node display_str = ', '.join(display_str.split()) return '{}{}{}'.format('(', display_str, ')') + + def __str__(self): + """Interact with built-in print function.""" + return self.display() diff --git a/src/priorityq.py b/src/priorityq.py index 3ae9ec8..a16976c 100644 --- a/src/priorityq.py +++ b/src/priorityq.py @@ -1,7 +1,5 @@ """Implement a priority queue using binary heap.""" -# [{1: 0}, {100: 1}, {33: 2}, {44: 3}, {2: 0}] - class PriorityQueue(object): """Implement a priority queue.""" @@ -18,15 +16,8 @@ def heapify(self, iterable): parent = (item_index - 1) // 2 while item_index > 0: if list(heap_list[parent].values())[0] is 0 and list(heap_list[item_index].values())[0] is 0: - if list(heap_list[item_index].keys())[0] < list(heap_list[parent].keys())[0]: - curr_val = heap_list[parent] - heap_list[parent] = heap_list[item_index] - heap_list[item_index] = curr_val - item_index = parent - parent = (item_index - 1) // 2 - else: - item_index = parent - parent = (item_index - 1) // 2 + item_index = parent + parent = (item_index - 1) // 2 elif list(heap_list[parent].values())[0] > 0 and list(heap_list[item_index].values())[0] is 0: item_index = parent parent = (item_index - 1) // 2 @@ -46,14 +37,12 @@ def heapify(self, iterable): else: item_index = parent parent = (item_index - 1) // 2 - else: - break return heap_list def insert(self, value, priority=0): """Insert a value into the priority queue with an optional priority.""" - if not isinstance(value, int) or not isinstance(priority, int): - raise TypeError("Must provide an integer for value and priority.") + if not isinstance(priority, int): + raise TypeError("Must provide an integer for priority.") if priority < 0: raise ValueError("You may not use a negative priority. Priority must be 0 or greater.") self._heap.append({value: priority}) diff --git a/src/que_.py b/src/que_.py index b1aafd8..08fce44 100644 --- a/src/que_.py +++ b/src/que_.py @@ -23,6 +23,6 @@ def peek(self): """Return a new value without dequeuing it.""" print(self._new_dll.tail.data) - def __len__(self): + def size(self): """Length function for the queue.""" - return len(self._new_dll) + return self._new_dll.size() diff --git a/src/stack.py b/src/stack.py index 9a82761..fe4edbb 100644 --- a/src/stack.py +++ b/src/stack.py @@ -12,13 +12,16 @@ def __init__(self, data=None): self._new_linked_list = LinkedList(data) def push(self, val): - """Push function for stack.""" - return self._new_linked_list.push(val) + """Add a value to the top of the stack.""" + self._new_linked_list.push(val) def pop(self): - """Pop function for stack.""" + """Remove and return the top of the stack.""" + if len(self) == 0: + raise IndexError( + 'Cannot pop from empty stack.') return self._new_linked_list.pop() def __len__(self): - """Length function for stack.""" - return len(self._new_linked_list) + """Return the number of items in the stack.""" + return self._new_linked_list.size() diff --git a/src/test_deque.py b/src/test_deque.py index 50bf32e..0797d6a 100644 --- a/src/test_deque.py +++ b/src/test_deque.py @@ -41,19 +41,38 @@ def test_the_deque_popleft_raises_exception(the_deque): the_deque.popleft() -def test_the_deque_popleft_multi_values(the_deque): +def test_the_deque_popleft_multi_values_phase_1(the_deque): """Test for popleft on mulitple values.""" the_deque.append(2) assert the_deque._new_dll.tail.data == 2 + + +def test_the_deque_popleft_multi_values_phase_2(the_deque): + """Test for popleft on mulitple values.""" + the_deque.append(2) the_deque.append(3) assert the_deque._new_dll.tail.next_node.data == 3 + + +def test_the_deque_popleft_multi_values_phase_3(the_deque): + """Test for popleft on mulitple values.""" + the_deque.append(2) + the_deque.append(3) the_deque.append(4) the_deque.append(5) assert the_deque._new_dll.head.data == 5 + + +def test_the_deque_popleft_multi_values_phase_4(the_deque): + """Test for popleft on mulitple values.""" + the_deque.append(2) + the_deque.append(3) + the_deque.append(4) + the_deque.append(5) the_deque.popleft() assert the_deque._new_dll.tail.data == 3 - assert the_deque.popleft() == 3 - assert the_deque._new_dll.tail.data == 4 + assert (the_deque.popleft(), + the_deque._new_dll.tail.data) == (3, 4) def test_the_pop(the_deque): @@ -76,9 +95,27 @@ def test_the_appendleft(the_deque): assert the_deque._new_dll.tail.data == 2 -def test_the_deque_len(the_deque): +def test_the_deque_size(the_deque): """Test the length on the queue.""" the_deque.append(1) the_deque.append(2) the_deque.append(3) - assert len(the_deque) == 3 + assert the_deque.size() == 3 + + +def test_deque_peek(the_deque): + """Test that we get the right value for peek.""" + the_deque.append(1) + the_deque.append(2) + the_deque.append(3) + the_deque.appendleft('tables') + assert the_deque.peek() == 3 + + +def test_deque_peekleft(the_deque): + """Test that we get the right value for peek.""" + the_deque.append(1) + the_deque.append(2) + the_deque.append(3) + the_deque.appendleft('tables') + assert the_deque.peekleft() == 'tables' diff --git a/src/test_dijkstra.py b/src/test_dijkstra.py new file mode 100644 index 0000000..e69de29 diff --git a/src/test_dll.py b/src/test_dll.py index 36f412f..c1e0a59 100644 --- a/src/test_dll.py +++ b/src/test_dll.py @@ -12,29 +12,20 @@ def dll(): def test_dll_initialization(dll): """Test that there's nothing initialized.""" - assert dll.tail is None - assert dll.head is None - - -def test_dll_push_raises_type_error(dll): - """Test that the value error is raised.""" - with pytest.raises(TypeError): - dll.push() + assert dll.tail is dll.head is None def test_dll_push_pushes_value(dll): """Test that the push pushes a value to head of list.""" dll.push(1) - assert dll.tail.data == 1 - assert dll.head.data == 1 + assert dll.tail.data == dll.head.data == 1 def test_dll_push_head_and_tail_change(dll): """Test if second item is pushed in. Head and tail are seperate values.""" dll.push(1) dll.push(2) - assert dll.tail.data == 1 - assert dll.head.data == 2 + assert (dll.tail.data, dll.head.data) == (1, 2) def test_dll_push_3(dll): @@ -42,12 +33,9 @@ def test_dll_push_3(dll): dll.push(1) dll.push(2) dll.push(3) - assert dll.tail.data == 1 - assert dll.head.prior_node.prior_node.data == 1 - assert dll.head != dll.head.prior_node - assert dll.head.data == 3 - assert dll.head.prior_node.next_node.data == 3 - assert dll.tail.next_node.data == 2 + assert (dll.tail.data, dll.head.prior_node.prior_node.data, + dll.head != dll.head.prior_node, dll.head.data, dll.head.prior_node.next_node.data, + dll.tail.next_node.data) == (1, 1, True, 3, 3, 2) def test_dll_pop_index_error(dll): @@ -56,30 +44,26 @@ def test_dll_pop_index_error(dll): dll.pop() -def test_dll_pop_only_has_one_item(dll): +def test_dll_pop_only_has_one_item_phase_one(dll): """Test that pop only has one item and both are head and tail none vals.""" dll.push(1) dll.push(2) - assert dll.pop() == 2 - assert dll.head.data == 1 - assert dll.tail.data == 1 - assert dll.head.next_node is None - assert dll.pop() == 1 - assert dll.head is None - assert dll.tail is None + assert (dll.pop(), dll.head.data, dll.tail.data, + dll.head.next_node) == (2, 1, 1, None) -def test_dll_append_raises_type_error(dll): - """Test that we get a type error.""" - with pytest.raises(TypeError): - dll.append() +def test_dll_pop_only_has_one_item_phase_two(dll): + """Test that pop only has one item and both are head and tail none vals.""" + dll.push(1) + dll.push(2) + dll.pop() + assert (dll.pop(), dll.head, dll.tail) == (1, None, None) def test_dll_appends_a_value(dll): """Ensure tail and head are the same.""" dll.append(1) - assert dll.tail.data == 1 - assert dll.head.data == 1 + assert dll.tail.data == dll.head.data == 1 def test_dll_appends_3_values(dll): @@ -87,81 +71,78 @@ def test_dll_appends_3_values(dll): dll.append(1) dll.append(2) dll.append(3) - assert dll.tail.data == 3 - assert dll.head.data == 1 - assert dll.head.next_node is None - assert dll.tail.prior_node is None - assert dll.tail.next_node.data == 2 - assert dll.head.prior_node.data == 2 - assert dll.head.prior_node.next_node.data == 1 - assert dll.tail.next_node.prior_node.data == 3 - - -def test_dll_shift_index_error(dll): - """Test that the Index Error is raised if no val is shifted.""" - with pytest.raises(IndexError): - dll.shift() + assert (dll.tail.data, dll.head.data, dll.head.next_node, + dll.tail.prior_node, dll.tail.next_node.data, + dll.head.prior_node.data, dll.head.prior_node.next_node.data, + dll.tail.next_node.prior_node.data) == (3, 1, None, + None, 2, 2, + 1, 3) -def test_dll_shift_only_has_one_item(dll): +def test_dll_shift_only_has_one_item_phase_one(dll): """Test that node connections after shifting.""" dll.push(1) dll.push(2) - assert dll.shift() == 1 - assert dll.head.data == 2 - assert dll.tail.data == 2 - assert dll.head.next_node is None - assert dll.tail.prior_node is None - assert dll.shift() == 2 - assert dll.head is None - assert dll.tail is None - - -def test_dll_remove_index_error(dll): - """Testing that the Index Error is raised if no val is passed.""" + assert (dll.shift(), dll.head.data, dll.tail.data, + dll.head.next_node, dll.tail.prior_node) == (1, 2, 2, None, None) + + +def test_dll_shift_only_has_one_item_phase_two(dll): + """Test that node connections after shifting.""" + dll.push(1) + dll.push(2) + dll.shift() + assert (dll.shift(), dll.head, dll.tail) == (2, None, None) + + +def test_dll_remove_phase_one(dll): + """Testing the dll remove function.""" dll.push(1) dll.push(2) dll.push(3) - with pytest.raises(TypeError): - dll.remove() + dll.push(4) + dll.remove(3) + assert (dll.head.prior_node.data, + dll.head.prior_node.next_node.data) == (2, 4) + + +def test_dll_remove_phase_two(dll): + """Testing the dll remove function.""" + dll.push(1) + dll.push(2) + dll.push(3) + dll.push(4) + dll.remove(3) + dll.remove(1) + assert (dll.tail.data, + dll.tail.next_node.data) == (2, 4) -def test_dll_remove(dll): +def test_dll_remove_phase_three(dll): """Testing the dll remove function.""" dll.push(1) dll.push(2) dll.push(3) dll.push(4) dll.remove(3) - assert dll.head.prior_node.data == 2 - assert dll.head.prior_node.next_node.data == 4 dll.remove(1) - assert dll.tail.data == 2 - assert dll.tail.next_node.data == 4 dll.remove(4) - assert dll.head.data == 2 - assert dll.tail.data == 2 + assert dll.head.data == dll.tail.data == 2 -def test_dll_len(dll): +def test_dll_size(dll): """Test to make sure we get the right number of nodes.""" - assert len(dll) == 0 + dll_lengths = [] dll.push(1) - assert len(dll) == 1 dll.push(2) - assert len(dll) == 2 dll.append(3) - assert len(dll) == 3 dll.push(4) - assert len(dll) == 4 dll.push(5) - assert len(dll) == 5 dll.push(6) + dll_lengths.append(dll.size()) dll.remove(4) - assert len(dll) == 5 dll.pop() - assert len(dll) == 4 dll.shift() - assert len(dll) == 3 dll.pop() - assert len(dll) == 2 + dll_lengths.append(dll.size()) + assert dll_lengths == [6, 2] diff --git a/src/test_linked_list.py b/src/test_linked_list.py index 1e41504..ac14d8f 100644 --- a/src/test_linked_list.py +++ b/src/test_linked_list.py @@ -12,6 +12,32 @@ def linked_list(): return linked_list +def test_size(linked_list): + """Verify size works.""" + linked_list.push('True') + linked_list.push(12) + linked_list.push(True) + assert linked_list.size() == 3 + + +def test_size_pop(linked_list): + """Verify size works.""" + linked_list.push('True') + linked_list.push(12) + linked_list.push(True) + linked_list.pop() + assert linked_list.size() == 2 + + +def test_linked_list_length(linked_list): + """Verify we can return the length of the linked list.""" + linked_list.push(3) + linked_list.push(4) + linked_list.push(5) + linked_list.pop() + assert len(linked_list) == 2 + + def test_linked_list_head(linked_list): """Test our linked_list class.""" assert hasattr(linked_list, 'head') @@ -20,17 +46,10 @@ def test_linked_list_head(linked_list): def test_iterable_linked_list(): """Test values of initialized linked list.""" from linked_list import LinkedList - linked_list = LinkedList([1, 2, 3]) - assert len(linked_list) == 3 - assert linked_list.head.data == 3 + assert (len(linked_list), linked_list.head.data) == (3, 3) - linked_list = LinkedList([1, 2, 3]) - assert len(linked_list) == 3 - assert linked_list.head.data == 3 - - def test_iterable_linked_list_exception(): """Ensure exception raised if a non-iterable is passed as argument.""" from linked_list import LinkedList @@ -49,18 +68,18 @@ def test_linked_list_push_three(linked_list): linked_list.push(5) linked_list.push(3) linked_list.push(2) - assert linked_list.head.data == 2 - assert linked_list.head.next_node.data == 3 - assert linked_list.head.next_node.next_node.data == 5 + assert (linked_list.head.data, + linked_list.head.next_node.data, + linked_list.head.next_node.next_node.data) == (2, 3, 5) def test_linked_list_popped(linked_list): """Test pop method.""" linked_list.push(5) linked_list.push(2) - assert linked_list.pop() == 2 - assert linked_list.head.data == 5 - assert linked_list.pop() == 5 + assert (linked_list.pop(), + linked_list.head.data, + linked_list.pop()) == (2, 5, 5) def test_linked_list_popped_exception(linked_list): @@ -69,28 +88,6 @@ def test_linked_list_popped_exception(linked_list): linked_list.pop() -def test_linked_list_length(linked_list): - """Verify we can return the length of the linked list.""" - linked_list.push(3) - linked_list.push(4) - assert len(linked_list) == 2 - linked_list.push(5) - assert len(linked_list) == 3 - linked_list.pop() - assert len(linked_list) == 2 - - -def test_linked_list_length(linked_list): - """Verify we can return the length of the linked list.""" - linked_list.push(3) - linked_list.push(4) - assert len(linked_list) == 2 - linked_list.push(5) - assert len(linked_list) == 3 - linked_list.pop() - assert len(linked_list) == 2 - - def test_linked_list_search(linked_list): """Test the linked list search method.""" from linked_list import LinkedList @@ -98,29 +95,52 @@ def test_linked_list_search(linked_list): obj_2 = 45 obj_3 = ['stringy'] linked_list = LinkedList([obj_1, obj_2, obj_3]) - assert linked_list.search(45) == obj_2 - assert linked_list.search(['stringy']) == obj_3 - assert linked_list.search(obj_1) == 'apple' - assert linked_list.search(47) is None + assert (linked_list.search(45), + linked_list.search(['stringy']), + linked_list.search(obj_1), + linked_list.search(47)) == (obj_2, obj_3, 'apple', None) -def test_linked_list_remove(): +def test_linked_list_remove_phase_one(): """Test proper remove functionality.""" from linked_list import LinkedList new_list = LinkedList([1, 2, 3, 4]) new_list.remove(1) assert new_list.search(1) is None + + +def test_linked_list_remove_phase_two(): + """Test proper remove functionality.""" + from linked_list import LinkedList + new_list = LinkedList([1, 2, 3, 4]) + new_list.remove(1) + new_list.remove(4) + assert (new_list.search(4), + new_list.search(3)) == (None, new_list.head.data) + + +def test_linked_list_remove_phase_three(): + """Test proper remove functionality.""" + from linked_list import LinkedList + new_list = LinkedList([1, 2, 3, 4]) + new_list.remove(1) new_list.remove(4) - assert new_list.search(4) is None - assert new_list.search(3) == new_list.head.data new_list.push(5) new_list.remove(3) - assert new_list.search(3) is None - assert new_list.search(5) == new_list.head.data + assert (new_list.search(3), + new_list.search(5)) == (None, new_list.head.data) + + +def test_linked_list_remove_exception(): + """Test raises exception if value can't be removed.""" + from linked_list import LinkedList + new_linked_list = LinkedList((1, 'Trip', True)) + with pytest.raises(ValueError): + new_linked_list.remove('this') def test_linked_list_display(): """Our display list.""" from linked_list import LinkedList new_list = LinkedList([1, 2, 3, 4]) - assert new_list.display() == "(4, 3, 2, 1)" + assert new_list.display() == "('4', '3', '2', '1')" diff --git a/src/test_priority_que.py b/src/test_priority_que.py index e6e467b..74a2fe2 100644 --- a/src/test_priority_que.py +++ b/src/test_priority_que.py @@ -51,57 +51,26 @@ def test_priority_que_type_arguments_a(priority_queue): priority_queue.insert(3, 'a') -# def test_priority_que_type_arguments_negative(priority_queue): -# """Make sure they only give priority >= 1.""" -# with pytest.raises(ValueError): -# priority_queue.insert(3, -2) - - - -def test_priority_que_type_arguments_none(priority_queue): - """Make sure an argument is give.""" - with pytest.raises(TypeError): - priority_queue.insert() - - -# def test_priority_que_type_arguments(priority_queue): -# """For now, ensure data type is integer.""" -# with pytest.raises(TypeError): -# priority_queue.insert('a', 1) - - -# def test_priority_que_type_arguments_list(priority_queue): -# """For now, ensure data type is integer.""" -# with pytest.raises(TypeError): -# priority_queue.insert([1], 1) - - -def test_priority_que_type_arguments_float(priority_queue): - """For now, ensure data type is integer.""" - with pytest.raises(TypeError): - priority_queue.insert(1.5, 3) - - def test_priority_que_success(priority_queue): """Ensure it takes the correct arguments.""" priority_queue.insert(15) - assert list(priority_queue._heap[0].keys())[0] == 15 - assert list(priority_queue._heap[0].values())[0] == 0 + assert (list(priority_queue._heap[0].keys())[0], + list(priority_queue._heap[0].values())[0]) == (15, 0) def test_priority_que_success_multiple(priority_queue_full): """Ensure it takes the correct arguments.""" - assert list(priority_queue_full._heap[0].keys())[0] == 11 - assert list(priority_queue_full._heap[-1].keys())[0] == 3 + assert (list(priority_queue_full._heap[0].keys())[0], + list(priority_queue_full._heap[-1].keys())[0]) == (11, 3) def test_priority_que_success_multiple_empty(priority_queue): """Ensure it takes the correct arguments.""" priority_queue.insert(15) priority_queue.insert(13, 1) - assert list(priority_queue._heap[0].keys())[0] == 13 - assert list(priority_queue._heap[0].values())[0] == 1 - assert list(priority_queue._heap[1].keys())[0] == 15 + assert (list(priority_queue._heap[0].keys())[0], + list(priority_queue._heap[0].values())[0], + list(priority_queue._heap[1].keys())[0]) == (13, 1, 15) def test_priority_que_success_min_no_priority(priority_queue): @@ -109,7 +78,7 @@ def test_priority_que_success_min_no_priority(priority_queue): priority_queue.insert(10) priority_queue.insert(5) priority_queue.insert(100) - assert list(priority_queue._heap[0].keys())[0] == 5 + assert list(priority_queue._heap[0].keys())[0] == 10 def test_priority_que_success_priority(priority_queue): @@ -123,37 +92,20 @@ def test_priority_que_success_priority(priority_queue): def test_priority_que_success_priority_multiple(priority_queue): """Ensure it orders by priority with different priorities.""" - priority_queue.insert(10) + priority_queue.insert(20) priority_queue.insert(5) priority_queue.insert(100, 5) priority_queue.insert(10, 2) priority_queue.insert(50, 1) assert list(priority_queue._heap[0].keys())[0] == 50 - assert list(priority_queue._heap[1].keys())[0] == 10 - assert list(priority_queue._heap[2].keys())[0] == 5 - - -# def test_priority_que_failure_pop(priority_queue): -# """Ensure it does not allow popping from empty priority queue.""" -# with pytest.raises(IndexError): -# priority_queue.pop() - def test_priority_que_pop(priority_queue_full): """Ensure pop is working as expected.""" - assert priority_queue_full.pop() == 11 - assert priority_queue_full.pop() == 6 - assert priority_queue_full.pop() == 12 - assert priority_queue_full.pop() == 15 - assert priority_queue_full.pop() == 3 - assert priority_queue_full.pop() == 17 - - -# def test_priority_que_peek(priority_queue_full): -# """Ensure we can peek at the correct value.""" -# assert priority_queue_full.peek() == 11 - + assert (priority_queue_full.pop(), + priority_queue_full.pop(), + priority_queue_full.pop(), + priority_queue_full.pop()) == (11, 6, 12, 15) def test_priority_que_pop_and_push(priority_queue_full): diff --git a/src/test_que_.py b/src/test_que_.py index 1227cfe..7f73761 100644 --- a/src/test_que_.py +++ b/src/test_que_.py @@ -13,8 +13,7 @@ def the_queue(): def test_the_queue_enqueue(the_queue): """Test for enqueuing to the queue.""" the_queue.enqueue(2) - assert the_queue._new_dll.head.data == 2 - assert the_queue._new_dll.tail.data == 2 + assert the_queue._new_dll.head.data == the_queue._new_dll.tail.data == 2 def test_the_queue_enqueue_multi_values(the_queue): @@ -23,10 +22,10 @@ def test_the_queue_enqueue_multi_values(the_queue): the_queue.enqueue(3) the_queue.enqueue(4) the_queue.enqueue(5) - assert the_queue._new_dll.head.data == 5 - assert the_queue._new_dll.tail.data == 2 - assert the_queue._new_dll.head.prior_node.data == 4 - assert the_queue._new_dll.tail.next_node.data == 3 + assert (the_queue._new_dll.head.data, + the_queue._new_dll.tail.data, + the_queue._new_dll.head.prior_node.data, + the_queue._new_dll.tail.next_node.data) == (5, 2, 4, 3) def test_the_queue_dequeue(the_queue): @@ -41,19 +40,25 @@ def test_the_queue_dequeue_raises_exception(the_queue): the_queue.dequeue() -def test_the_queue_dequeue_multi_values(the_queue): +def test_the_queue_dequeue_multi_values_phase_one(the_queue): """Test for dequeue on mulitple values.""" the_queue.enqueue(2) - assert the_queue._new_dll.tail.data == 2 the_queue.enqueue(3) - assert the_queue._new_dll.tail.next_node.data == 3 the_queue.enqueue(4) the_queue.enqueue(5) - assert the_queue._new_dll.head.data == 5 the_queue.dequeue() assert the_queue._new_dll.tail.data == 3 - assert the_queue.dequeue() == 3 - assert the_queue._new_dll.tail.data == 4 + + +def test_the_queue_dequeue_multi_values_phase_two(the_queue): + """Test for dequeue on mulitple values.""" + the_queue.enqueue(2) + the_queue.enqueue(3) + the_queue.enqueue(4) + the_queue.enqueue(5) + the_queue.dequeue() + assert (the_queue.dequeue(), + the_queue._new_dll.tail.data) == (3, 4) def test_the_peek(the_queue): @@ -61,25 +66,18 @@ def test_the_peek(the_queue): the_queue.enqueue(1) the_queue.enqueue(2) the_queue.enqueue(3) - assert the_queue._new_dll.tail.data == 1 the_queue.dequeue() assert the_queue._new_dll.tail.data == 2 -def test_the_queue_len(the_queue): +def test_the_queue_size(the_queue): """Test the length on the queue.""" the_queue.enqueue(1) the_queue.enqueue(2) the_queue.enqueue(3) - assert len(the_queue) == 3 - - - - - - - - - + assert the_queue.size() == 3 +def test_size_empty(the_queue): + """Test zero is returned if empty.""" + assert the_queue.size() == 0 diff --git a/src/test_stack.py b/src/test_stack.py index 2a10882..a8281d4 100644 --- a/src/test_stack.py +++ b/src/test_stack.py @@ -10,6 +10,13 @@ def the_stack(): return the_stack +def test_instantiation(the_stack): + """Test instantiation of the stack.""" + from stack import Stack + assert (len(the_stack), + isinstance(the_stack, Stack)) == (4, True) + + def test_stack_push(the_stack): """Test for pushing to stack.""" the_stack.push(5) @@ -18,8 +25,8 @@ def test_stack_push(the_stack): def test_stack_pop(the_stack): """Test for popping to stack.""" - the_stack.pop() - assert the_stack._new_linked_list.head.data == 3 + assert (the_stack.pop(), + the_stack._new_linked_list.head.data) == (4, 3) def test_stack_pop_except_error(): @@ -45,3 +52,92 @@ def test_remove_stack(): """Test to make sure stack is not accessing remove method.""" with pytest.raises(AttributeError): the_stack.remove(4) + + +def test_pop_and_push_combo_phase_one(the_stack): + """Test to make sure we can push and pop together.""" + the_stack.push('stack') + assert the_stack.pop() == 'stack' + + +def test_pop_and_push_combo_phase_two(the_stack): + """Test to make sure we can push and pop together.""" + the_stack.push('stack') + the_stack.push(34) + assert (the_stack.pop(), + the_stack.pop(), + the_stack.pop()) == (34, 'stack', 4) + + +def test_pop_and_push_combo_phase_three(the_stack): + """Test to make sure we can push and pop together.""" + the_stack.push('stack') + the_stack.push(34) + the_stack.push('wiener-dog') + assert (the_stack.pop(), + the_stack.pop(), + the_stack.pop(), + the_stack.pop()) == ('wiener-dog', 34, 'stack', 4) + + +def test_pop_and_push_combo_phase_four(the_stack): + """Test to make sure we can push and pop together.""" + the_stack.push('stack') + the_stack.push(34) + the_stack.push('wiener-dog') + the_stack.push(-123) + assert (the_stack.pop(), + the_stack.pop(), + the_stack.pop(), + the_stack.pop(), + the_stack.pop()) == (-123, 'wiener-dog', 34, 'stack', 4) + + +def test_pop_and_push_combo_phase_five(the_stack): + """Test to make sure we can push and pop together.""" + the_stack.push('stack') + the_stack.push(34) + the_stack.push('wiener-dog') + the_stack.push(-123) + assert (the_stack.pop(), + the_stack.pop(), + the_stack.pop(), + the_stack.pop(), + the_stack.pop(), + the_stack.pop(), + the_stack.pop(), + the_stack.pop()) == (-123, 'wiener-dog', 34, 'stack', 4, 3, 2, 1) + + +def test_pop_and_push_combo_phase_six(the_stack): + """Test to make sure we can push and pop together.""" + the_stack.push('stack') + the_stack.push(34) + the_stack.push('wiener-dog') + the_stack.push(-123) + the_stack.pop() + the_stack.pop() + the_stack.pop() + the_stack.pop() + the_stack.pop() + the_stack.pop() + the_stack.pop() + the_stack.pop() + with pytest.raises(IndexError): + the_stack.pop() + + +def test_pop_and_push_combo_phase_seven(the_stack): + """Test to make sure we can push and pop together.""" + the_stack.push('stack') + the_stack.pop() + the_stack.push(34) + the_stack.pop() + the_stack.pop() + the_stack.pop() + the_stack.push('wiener-dog') + the_stack.pop() + the_stack.pop() + the_stack.push(-123) + the_stack.pop() + assert the_stack.pop() == 1 diff --git a/src/test_weighted_graph.py b/src/test_weighted_graph.py index ba8a527..09e8ba7 100644 --- a/src/test_weighted_graph.py +++ b/src/test_weighted_graph.py @@ -36,13 +36,11 @@ def graph_with_edges(): new_graph.add_node('D') new_graph.add_node('E') new_graph.add_node('F') - new_graph.add_edge('A', 'B') - new_graph.add_edge('A', 'C') - new_graph.add_edge('B', 'D') - new_graph.add_edge('B', 'E') - new_graph.add_edge('C', 'B') - new_graph.add_edge('F', 'A') - new_graph.add_edge('C', 'F') + new_graph.add_edge('A', 'B', 7) + new_graph.add_edge('A', 'C', 9) + new_graph.add_edge('B', 'D', 2) + new_graph.add_edge('B', 'E', 4) + new_graph.add_edge('C', 'F', 6) return new_graph @@ -157,3 +155,21 @@ def test_adjacent_unpresent(graph_with_edges): """Ensure we get an error.""" with pytest.raises(ValueError): graph_with_edges.adjacent('Captain Picard', 'Star Wars') + + +def test_add_node_value_error_val_exists(graph_no_edges): + """Ensure a value is not added twice.""" + with pytest.raises(ValueError): + graph_no_edges.add_node('BB') + + +def test_del_edges_has_no_edges_to_delete(graph_with_edges): + """Ensure there are no edges to delete.""" + with pytest.raises(KeyError): + graph_with_edges.del_edges('F', 'G') + + +def test_neighbors_value_error_not_in_graph(graph_with_edges): + """Ensure the value error raises if no neighbors.""" + with pytest.raises(ValueError): + graph_with_edges.neighbors('G') diff --git a/src/weighted_traversal.py b/src/weighted_traversal.py index 69da770..2c037ee 100644 --- a/src/weighted_traversal.py +++ b/src/weighted_traversal.py @@ -32,7 +32,7 @@ def breadth_first_traversal(graph, start): peeped = [] queue = Queue() queue.enqueue(start) - while len(queue) > 0: + while queue.size() > 0: node = queue.dequeue() if node not in peeped: peeped.append(node) @@ -42,7 +42,7 @@ def breadth_first_traversal(graph, start): return peeped -if __name__ == '__main__': +if __name__ == '__main__': # pragma no cover new_graph = Weighted() new_graph.add_node('A') new_graph.add_node('B') diff --git a/tox.ini b/tox.ini index 036b313..450b49a 100644 --- a/tox.ini +++ b/tox.ini @@ -2,7 +2,7 @@ envlist = py27, py36 [testenv] -commands = py.test src --cov=src --cov-report term-missing +commands = pytest src/test_weighted_traversal.py src/test_weighted_graph.py --cov=src --cov-report term-missing deps = pytest pytest-cov