diff --git a/README.md b/README.md index 18aaf11..aaaa060 100644 --- a/README.md +++ b/README.md @@ -130,3 +130,24 @@ def multiples(s1, s2, s3): return [a for a in xrange(1, s3) if not(a % s1 or a % s2)] ``` +Sum of the first nth terms of a series (7 kyu) +- Module: series_sum.py +- Tests: test_series_sum.py +- Link: http://www.codewars.com/kata/sum-of-the-first-nth-term-of-series/train/python +- Interesting Solution: Making the numerator a float() was smart. +```python +def series_sum(n): + """Solution by MMMAAANNN""" + return '{:.2f}'.format(sum(1.0/(3 * i + 1) for i in range(n))) +``` + + +Proper Parenthetics +- Module: proper_parenthetics.py +- Tests: test_proper_parenthetics.py + + +Sort Cards (7kyu) +-Module: sort_cards.py +-Tests: test_sort_cards.py +-Link: https://www.codewars.com/kata/sort-deck-of-cards/train/python diff --git a/setup.py b/setup.py index cd6801e..b669148 100644 --- a/setup.py +++ b/setup.py @@ -13,7 +13,8 @@ py_modules=["last", "string_to_array", "fake_binary", "count_positives_sum_negatives", "digitize", "binary_list_to_number", "sea_sick", "reverse_and_mirror", - "flatten_me", "sum_from_string", "multiples"], + "flatten_me", "sum_from_string", "multiples", "sort_cards", + "priority"], install_requires=[], extras_require={ "test": ["pytest", "pytest-watch", "pytest-cov", "tox"] diff --git a/src/__pycache__/test_binary_list_to_number.cpython-27-PYTEST.pyc b/src/__pycache__/test_binary_list_to_number.cpython-27-PYTEST.pyc index 15650ed..21ab5d0 100644 Binary files a/src/__pycache__/test_binary_list_to_number.cpython-27-PYTEST.pyc and b/src/__pycache__/test_binary_list_to_number.cpython-27-PYTEST.pyc differ diff --git a/src/__pycache__/test_count_positives_sum_negatives.cpython-27-PYTEST.pyc b/src/__pycache__/test_count_positives_sum_negatives.cpython-27-PYTEST.pyc index 88dffe1..16e814e 100644 Binary files a/src/__pycache__/test_count_positives_sum_negatives.cpython-27-PYTEST.pyc and b/src/__pycache__/test_count_positives_sum_negatives.cpython-27-PYTEST.pyc differ diff --git a/src/__pycache__/test_digitize.cpython-27-PYTEST.pyc b/src/__pycache__/test_digitize.cpython-27-PYTEST.pyc index ee8ecb2..4e8759e 100644 Binary files a/src/__pycache__/test_digitize.cpython-27-PYTEST.pyc and b/src/__pycache__/test_digitize.cpython-27-PYTEST.pyc differ diff --git a/src/__pycache__/test_fake_bin.cpython-27-PYTEST.pyc b/src/__pycache__/test_fake_bin.cpython-27-PYTEST.pyc index 88d45bb..d663fde 100644 Binary files a/src/__pycache__/test_fake_bin.cpython-27-PYTEST.pyc and b/src/__pycache__/test_fake_bin.cpython-27-PYTEST.pyc differ diff --git a/src/__pycache__/test_flatten_me.cpython-27-PYTEST.pyc b/src/__pycache__/test_flatten_me.cpython-27-PYTEST.pyc index 3ef8748..a52b673 100644 Binary files a/src/__pycache__/test_flatten_me.cpython-27-PYTEST.pyc and b/src/__pycache__/test_flatten_me.cpython-27-PYTEST.pyc differ diff --git a/src/__pycache__/test_last.cpython-27-PYTEST.pyc b/src/__pycache__/test_last.cpython-27-PYTEST.pyc index 3360ba5..b181a03 100644 Binary files a/src/__pycache__/test_last.cpython-27-PYTEST.pyc and b/src/__pycache__/test_last.cpython-27-PYTEST.pyc differ diff --git a/src/__pycache__/test_multiples.cpython-27-PYTEST.pyc b/src/__pycache__/test_multiples.cpython-27-PYTEST.pyc index 812ac41..e2c8b29 100644 Binary files a/src/__pycache__/test_multiples.cpython-27-PYTEST.pyc and b/src/__pycache__/test_multiples.cpython-27-PYTEST.pyc differ diff --git a/src/__pycache__/test_reverse_and_mirror.cpython-27-PYTEST.pyc b/src/__pycache__/test_reverse_and_mirror.cpython-27-PYTEST.pyc index 05ffc74..d3d7d64 100644 Binary files a/src/__pycache__/test_reverse_and_mirror.cpython-27-PYTEST.pyc and b/src/__pycache__/test_reverse_and_mirror.cpython-27-PYTEST.pyc differ diff --git a/src/__pycache__/test_sea_sick.cpython-27-PYTEST.pyc b/src/__pycache__/test_sea_sick.cpython-27-PYTEST.pyc index c775ca4..f0292be 100644 Binary files a/src/__pycache__/test_sea_sick.cpython-27-PYTEST.pyc and b/src/__pycache__/test_sea_sick.cpython-27-PYTEST.pyc differ diff --git a/src/__pycache__/test_string_to_array.cpython-27-PYTEST.pyc b/src/__pycache__/test_string_to_array.cpython-27-PYTEST.pyc index 36ad973..3116dd3 100644 Binary files a/src/__pycache__/test_string_to_array.cpython-27-PYTEST.pyc and b/src/__pycache__/test_string_to_array.cpython-27-PYTEST.pyc differ diff --git a/src/__pycache__/test_sum.cpython-27-PYTEST.pyc b/src/__pycache__/test_sum.cpython-27-PYTEST.pyc index 7a0308d..1b14d6b 100644 Binary files a/src/__pycache__/test_sum.cpython-27-PYTEST.pyc and b/src/__pycache__/test_sum.cpython-27-PYTEST.pyc differ diff --git a/src/__pycache__/test_sum_from_string.cpython-27-PYTEST.pyc b/src/__pycache__/test_sum_from_string.cpython-27-PYTEST.pyc index ab6449a..72c1e50 100644 Binary files a/src/__pycache__/test_sum_from_string.cpython-27-PYTEST.pyc and b/src/__pycache__/test_sum_from_string.cpython-27-PYTEST.pyc differ diff --git a/src/binary_list_to_number.pyc b/src/binary_list_to_number.pyc index 65ecd78..676595a 100644 Binary files a/src/binary_list_to_number.pyc and b/src/binary_list_to_number.pyc differ diff --git a/src/code_katas.egg-info/SOURCES.txt b/src/code_katas.egg-info/SOURCES.txt index c18a04c..81c3bbc 100644 --- a/src/code_katas.egg-info/SOURCES.txt +++ b/src/code_katas.egg-info/SOURCES.txt @@ -5,8 +5,10 @@ src/digitize.py src/flatten_me.py src/last.py src/multiples.py +src/priority.py src/reverse_and_mirror.py src/sea_sick.py +src/sort_cards.py src/string_to_array.py src/sum_from_string.py src/code_katas.egg-info/PKG-INFO diff --git a/src/code_katas.egg-info/top_level.txt b/src/code_katas.egg-info/top_level.txt index 4429a32..2b582bf 100644 --- a/src/code_katas.egg-info/top_level.txt +++ b/src/code_katas.egg-info/top_level.txt @@ -5,7 +5,9 @@ fake_binary flatten_me last multiples +priority reverse_and_mirror sea_sick +sort_cards string_to_array sum_from_string diff --git a/src/count_positives_sum_negatives.pyc b/src/count_positives_sum_negatives.pyc index 5ff6119..2232787 100644 Binary files a/src/count_positives_sum_negatives.pyc and b/src/count_positives_sum_negatives.pyc differ diff --git a/src/digitize.pyc b/src/digitize.pyc index 5570438..ff34534 100644 Binary files a/src/digitize.pyc and b/src/digitize.pyc differ diff --git a/src/fake_bin.pyc b/src/fake_bin.pyc index 4bb5359..eaf245f 100644 Binary files a/src/fake_bin.pyc and b/src/fake_bin.pyc differ diff --git a/src/flatten_me.pyc b/src/flatten_me.pyc index 74e8866..3bf2f48 100644 Binary files a/src/flatten_me.pyc and b/src/flatten_me.pyc differ diff --git a/src/last.pyc b/src/last.pyc index d32bfa8..1cf7697 100644 Binary files a/src/last.pyc and b/src/last.pyc differ diff --git a/src/linked_list.py b/src/linked_list.py new file mode 100644 index 0000000..af36cc5 --- /dev/null +++ b/src/linked_list.py @@ -0,0 +1,83 @@ +"""Implementation of Linked_List data type.""" + + +class LinkedList(object): + """Class representation of linked list.""" + + def __init__(self, iterable=None): + """Instantiate linked list.""" + self.head_node = None + self.length = 0 + try: + for item in iterable: + self.push(item) + except TypeError: + if iterable: + return "Please only enter iterable values" + + def push(self, contents): + """Add node to this linked list.""" + self.head_node = Node(contents, self.head_node) + self.length += 1 + + def pop(self): + """Remove and return the current head node.""" + if not self.head_node: + return "Linked list is already empty" + old_head_node = self.head_node + self.head_node = self.head_node.next_node + self.length -= 1 + return old_head_node.contents + + def size(self): + """Return the current size of this linked list.""" + return self.length + + def search(self, search_value): + """Return the node with the searched contents if found.""" + if self.length: + if search_value == self.head_node.contents: + return self.head_node + current_node = self.head_node + while current_node.contents != search_value: + if current_node.next_node is None: + return None + current_node = current_node.next_node + return current_node + else: + return None + + def remove(self, remove_node): + """Remove a node from linked list.""" + if remove_node == self.head_node: + self.head_node = self.head_node.next_node + self.length -= 1 + return None + elif remove_node is None: + raise ValueError("Provided value not in list.") + current_node = self.head_node + while current_node.next_node != remove_node: + current_node = current_node.next_node + current_node.next_node = current_node.next_node.next_node + self.length -= 1 + + def display(self): + """Return the tuple of all values in linked list.""" + if self.length == 0: + return None + else: + new_list = [self.head_node.contents] + current_node = self.head_node + while current_node.next_node is not None: + current_node = current_node.next_node + new_list.append(current_node.contents) + return tuple(new_list) + + +class Node(object): + """Class representation of linked list node.""" + + def __init__(self, contents, next_node): + """Instantiate linked list node.""" + self.contents = contents + self.next_node = next_node diff --git a/src/multiples.pyc b/src/multiples.pyc index 1716616..cdf71a6 100644 Binary files a/src/multiples.pyc and b/src/multiples.pyc differ diff --git a/src/priority.py b/src/priority.py new file mode 100644 index 0000000..10d6cae --- /dev/null +++ b/src/priority.py @@ -0,0 +1,40 @@ +"""Priority Queue data structure.""" + + +class PriorityQueue(object): + """Priority Queue data structure. + + .insert(item) - adds an item to the queue and sorts + .pop() - removes the highest priority item, returns its value. + .peek() - returns the value of the highest priority item. + """ + + def __init__(self, iterable=None): + """Initialize the Priority Queue.""" + self._pq_dict = {} + if hasattr(iterable, "__iter__"): + for val in iterable: + self.insert(val[1], priority=val[0]) + + def insert(self, value, priority=0): + """Insert values and priorities in to priority queue.""" + if priority not in self._pq_dict.keys(): + self._pq_dict[priority] = [] + self._pq_dict[priority].append(value) + + def pop(self): + """Remove the highest priority item, returns its value.""" + pop_val = self.peek() + hi_pri = sorted(self._pq_dict.keys())[0] + if len(self._pq_dict[hi_pri]) == 1: + del self._pq_dict[hi_pri] + else: + self._pq_dict[hi_pri] = self._pq_dict[hi_pri][1:] + return pop_val + + def peek(self): + if len(self._pq_dict.keys()) == 0: + raise KeyError("The Priority Queue is empty.") + hi_pri = sorted(self._pq_dict.keys())[0] + pop_val = self._pq_dict[hi_pri][0] + return pop_val diff --git a/src/proper_parenthetics.py b/src/proper_parenthetics.py new file mode 100644 index 0000000..aaeff61 --- /dev/null +++ b/src/proper_parenthetics.py @@ -0,0 +1,18 @@ +"""Ensure the same number of opening and closing parenthetics in a string.""" + +from stack import Stack + + +def proper_parenthetics(input_string): + """Ensure the balance of opening and closing parenthtics.""" + parenthetics_stack = Stack() + for i in input_string: + if i == '(': + parenthetics_stack.push(i) + if i == ')': + if parenthetics_stack.head_node is None: + return -1 + parenthetics_stack.pop() + if parenthetics_stack.head_node is None: + return 0 + return 1 diff --git a/src/reverse_and_mirror.pyc b/src/reverse_and_mirror.pyc index 99b801a..c21cbb1 100644 Binary files a/src/reverse_and_mirror.pyc and b/src/reverse_and_mirror.pyc differ diff --git a/src/sea_sick.pyc b/src/sea_sick.pyc index 25b92c7..a146356 100644 Binary files a/src/sea_sick.pyc and b/src/sea_sick.pyc differ diff --git a/src/sort_cards.py b/src/sort_cards.py new file mode 100644 index 0000000..de248f8 --- /dev/null +++ b/src/sort_cards.py @@ -0,0 +1,49 @@ +"""Sort a deck of cards code-kata using a Priority Queue.""" + +from priority import PriorityQueue + +card_dict = { + 'A': 1, + 'T': 10, + 'J': 11, + 'Q': 12, + 'K': 13, + 1: 'A', + 10: 'T', + 11: 'J', + 12: 'Q', + 13: 'K', +} + + +def sort_cards(cards): + """Sort shuffled list of cards, sorted by rank.""" + card_list = [] + for card in cards: + try: + card_list.append(int(card)) + except ValueError: + card_list.append(card_dict[card]) + card_list.sort() + result = [] + for card in card_list: + if card > 1 and card < 10: + result.append(str(card)) + else: + result.append(card_dict[card]) + return result + + +def sort_cards_w_pq(cards): + """Sort shuffled list of cards, sorted by rank, using a priority queue.""" + card_list = [] + for card in cards: + try: + card_list.append((int(card), card)) + except ValueError: + card_list.append(card_dict[card]) + card_q = PriorityQueue(card_list) + result = [] + for i in range(len(card_list)): + result.append(card_q.pop()) + return result diff --git a/src/stack.py b/src/stack.py new file mode 100644 index 0000000..7c6e988 --- /dev/null +++ b/src/stack.py @@ -0,0 +1,24 @@ +"""Implementation of Stack data type.""" + +from linked_list import LinkedList + + +class Stack(object): + """Class representation of a stack.""" + + def __init__(self, iterable=None): + """Instantiate stack.""" + self.linked_list = LinkedList(iterable) + self.length = self.linked_list.length + self.head_node = self.linked_list.head_node + + def push(self, contents): + """Add node to this stack.""" + self.linked_list.push(contents) + self.head_node = self.linked_list.head_node + + def pop(self): + """Remove and return the current head node.""" + old_head_node_value = self.linked_list.pop() + self.head_node = self.linked_list.head_node + return old_head_node_value diff --git a/src/string_to_array.pyc b/src/string_to_array.pyc index fd38868..8dccd68 100644 Binary files a/src/string_to_array.pyc and b/src/string_to_array.pyc differ diff --git a/src/sum_from_string.pyc b/src/sum_from_string.pyc index c3fa60c..6fa762d 100644 Binary files a/src/sum_from_string.pyc and b/src/sum_from_string.pyc differ diff --git a/src/test_priority.py b/src/test_priority.py new file mode 100644 index 0000000..78b30a7 --- /dev/null +++ b/src/test_priority.py @@ -0,0 +1,69 @@ +"""Test the priority queue's functionality.""" + + +import pytest + +INPUT_VALUES = [ + ([], {}, None, None), + ([(1, 'a'), (2, 'b'), (3, 'c')], {1: ['a'], 2: ['b'], 3: ['c']}, 'a', 1), + ([(2, 'a'), (5, 'b'), (12, 'c')], {2: ['a'], 5: ['b'], 12: ['c']}, 'a', 2), + ([(15, 'words'), (6, 'are'), (70, 'hard')], {6: ['are'], 15: ['words'], 70: ['hard']}, 'are', 6), + ([(1, 15), (2, 20), (3, 25)], {1: [15], 2: [20], 3: [25]}, 15, 1), + ([(1, 'a'), (1, 'b'), (2, 'c')], {1: ['a', 'b'], 2: ['c']}, 'a', 1), +] + + +@pytest.fixture(scope="module", params=INPUT_VALUES) +def pri(request): + """Paramaterized fixture for testing.""" + from priority import PriorityQueue + processed = PriorityQueue(request.param[0]) + prioq = (processed, request.param[1], request.param[2], request.param[3]) + return prioq + + +def test_init(pri): + """Test that the class initializes.""" + from priority import PriorityQueue + assert isinstance(pri[0], PriorityQueue) + + +def test_insert(pri): + """Test that values are inserted at the right priority in the right order.""" + assert pri[0]._pq_dict == pri[1] + # (the_input, the_expected_output) = pri + + +def test_pop(pri): + """Test that pop returns the right value.""" + try: + assert pri[0].pop() == pri[2] + except KeyError: + assert True + + +def test_del(pri): + """Test that empty keys are deleted.""" + try: + pri[0].pop() + pri[0].pop() + assert pri[3] not in pri[0]._pq_dict + except KeyError: + assert True + + +def test_pop_remove(pri): + """Test that pop properly removes values.""" + try: + pri[0].pop() + assert pri[2] not in pri[0]._pq_dict[pri[3]] + except KeyError: + assert True + + +def test_peek(pri): + """Test that peek returns the right value.""" + try: + assert pri[0].peek() == pri[2] + except KeyError: + assert True diff --git a/src/test_proper_parenthetics.py b/src/test_proper_parenthetics.py new file mode 100644 index 0000000..2099a88 --- /dev/null +++ b/src/test_proper_parenthetics.py @@ -0,0 +1,21 @@ +"""Tests for proper_parenthetics.""" +import pytest + + +ASSERTIONS = [ + ['(', 1], + ['(This is (a string)', 1], + ['()', 0], + ['some (strings) and (others)', 0], + ['((Nestes)ones)', 0], + [')', -1], + ['(bloop))', -1], + [')its backwards(', -1] +] + + +@pytest.mark.parametrize("input, result", ASSERTIONS) +def test_proper_parenthetics(input, result): + """Test proper_parenthetics for proper output in test cases.""" + from proper_parenthetics import proper_parenthetics + assert proper_parenthetics(input) == result diff --git a/src/test_sort_cards.py b/src/test_sort_cards.py new file mode 100644 index 0000000..6517f2a --- /dev/null +++ b/src/test_sort_cards.py @@ -0,0 +1,26 @@ +"""Tests for count_positives_sum_negatives.count_positives_sum_negatives.""" +import pytest + + +ASSERTIONS = [ + [list('39A5T824Q7J6K'), list('A23456789TJQK')], + [list('Q286JK395A47T'), list('A23456789TJQK')], + [list('54TQKJ69327A8'), list('A23456789TJQK')], + [list('AAA4555336773'), list('AAA3334555677')], + [list('3'), list('3')], + [list('TTTTTTTTTTTAK'), list('ATTTTTTTTTTTK')], +] + + +@pytest.mark.parametrize("n, result", ASSERTIONS) +def test_sort_cards(n, result): + """Test sort_cards() for proper output in test cases.""" + from sort_cards import sort_cards + assert sort_cards(n) == result + + +@pytest.mark.parametrize("n, result", ASSERTIONS) +def test_sort_cards_w_pq(n, result): + """Test sort_cards_w_pq() for proper output in test cases.""" + from sort_cards import sort_cards + assert sort_cards(n) == result