Skip to content

Commit de44942

Browse files
committed
refactor(datastructures, linkedlist): cleans up reverse_between method
Adds validation checks for the reverse_between method of the singly linked list class and tests to validate these changes. Additionally adds linting fixes to the code base
1 parent c9bab33 commit de44942

File tree

10 files changed

+1167
-1069
lines changed

10 files changed

+1167
-1069
lines changed

datastructures/linked_lists/singly_linked_list/__init__.py

Lines changed: 5 additions & 1032 deletions
Large diffs are not rendered by default.

datastructures/linked_lists/singly_linked_list/single_linked_list.py

Lines changed: 1059 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
from typing import List
2+
import unittest
3+
from parameterized import parameterized
4+
from datastructures.linked_lists.singly_linked_list.single_linked_list import (
5+
SinglyLinkedList,
6+
)
7+
8+
9+
class ReverseBetweenSinglyLinkedListTestCase(unittest.TestCase):
10+
def test_return_none_for_empty_linked_list(self):
11+
"""should return none for an empty linked list when attempting to reverse"""
12+
linked_list = SinglyLinkedList()
13+
14+
actual = linked_list.reverse_between(0, 1)
15+
self.assertIsNone(actual)
16+
17+
def test_raises_exception_for_invalid_arguments(self):
18+
"""should raise an exception for invalid left and right arguments"""
19+
linked_list = SinglyLinkedList()
20+
21+
with self.assertRaises(ValueError):
22+
linked_list.reverse_between(10, 9)
23+
24+
@parameterized.expand(
25+
[
26+
([1, 2, 3, 4, 5, 4, 3, 2, 1], 1, 9, [1, 2, 3, 4, 5, 4, 3, 2, 1]),
27+
([1, 2, 3, 4, 5], 2, 4, [1, 4, 3, 2, 5]),
28+
([1, 2, 3, 4, 5], 1, 5, [5, 4, 3, 2, 1]),
29+
(
30+
[103, 7, 10, -9, 105, 67, 31, 63],
31+
1,
32+
8,
33+
[63, 31, 67, 105, -9, 10, 7, 103],
34+
),
35+
(
36+
[103, 7, 10, -9, 105, 67, 31, 63],
37+
1,
38+
8,
39+
[63, 31, 67, 105, -9, 10, 7, 103],
40+
),
41+
([-499, 399, -299, 199, -99, 9], 3, 5, [-499, 399, -99, 199, -299, 9]),
42+
([7, -9, 2, -10, 1, -8, 6], 2, 5, [7, 1, -10, 2, -9, -8, 6]),
43+
([6, 8, 7], 1, 2, [8, 6, 7]),
44+
([9, 0, 8, 2], 2, 4, [9, 2, 8, 0]),
45+
([7, 4, 6, 1, 5, 8], 2, 5, [7, 5, 1, 6, 4, 8]),
46+
([3, 7, 12, 2, 5, 1], 3, 6, [3, 7, 1, 5, 2, 12]),
47+
([3, 6, 7, 4, 2], 2, 4, [3, 4, 7, 6, 2]),
48+
]
49+
)
50+
def test_reverse_between(
51+
self, data: List[int], left: int, right: int, expected: List[int]
52+
):
53+
"""should reverse linked list between left and right arguments"""
54+
linked_list = SinglyLinkedList()
55+
# add the data to the linked list
56+
for d in data:
57+
linked_list.append(d)
58+
59+
# perform reversal
60+
actual = linked_list.reverse_between(left, right)
61+
62+
# since the head node is returned, we want the values of the linked list and not just the head node
63+
# to check that the actual reversal worked
64+
actual_list: List[int] = []
65+
curr = actual
66+
while curr:
67+
actual_list.append(curr.data)
68+
curr = curr.next
69+
70+
# perform assertion
71+
self.assertEqual(expected, actual_list)
72+
73+
74+
if __name__ == "__main__":
75+
unittest.main()

datastructures/trees/heaps/binary/min_heap/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ def __bubble_down(self, idx: int):
5959

6060
self.__bubble_down(min_child_index)
6161

62+
# FIXME: fails on some instances with a KeyError, check the puzzle min_cost_connect_sticks
6263
def __bubble_up(self, idx: int):
6364
if idx == 0:
6465
return

datastructures/trees/heaps/node.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,22 +16,22 @@ def __init__(self, data: T, key: Optional[T] = None):
1616
def name(self):
1717
return self.__class__.__name__
1818

19-
def __eq__(self, other: 'HeapNode') -> bool:
19+
def __eq__(self, other: "HeapNode") -> bool:
2020
return self.data == other.data
2121

22-
def __lt__(self, other: 'HeapNode') -> bool:
22+
def __lt__(self, other: "HeapNode") -> bool:
2323
return self.data < other.data
2424

25-
def __gt__(self, other: 'HeapNode') -> bool:
25+
def __gt__(self, other: "HeapNode") -> bool:
2626
return self.data > other.data
2727

28-
def __le__(self, other: 'HeapNode') -> bool:
28+
def __le__(self, other: "HeapNode") -> bool:
2929
return self.data <= other.data
3030

31-
def __ge__(self, other: 'HeapNode') -> bool:
31+
def __ge__(self, other: "HeapNode") -> bool:
3232
return self.data >= other.data
3333

34-
def __ne__(self, other: 'HeapNode') -> bool:
34+
def __ne__(self, other: "HeapNode") -> bool:
3535
return self.data != other.data
3636

3737
def __hash__(self) -> int:

datastructures/trees/trie/suffix/suffix_tree.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ class SuffixTree:
1010
Basically, this is a Trie optimized for suffix matching by storing reversed strings.
1111
Each node tracks the best candidate word for tie-breaking.
1212
"""
13+
1314
def __init__(self):
1415
super().__init__()
1516
self.root = SuffixTreeNode()

datastructures/trees/trie/suffix/suffix_tree_node.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from typing import DefaultDict, Tuple
1+
from typing import DefaultDict
22
from collections import defaultdict
33
from datastructures.trees.trie.trie_node import TrieNode
44
from datastructures.trees.trie.suffix.types import WordInfo, INF_WORD_INFO
@@ -10,6 +10,7 @@ class SuffixTreeNode(TrieNode):
1010
Each node stores its children and the index of the best word
1111
(shortest, earliest) that passes through this node.
1212
"""
13+
1314
def __init__(self):
1415
super().__init__()
1516
# index of best word passing through this node
@@ -18,4 +19,3 @@ def __init__(self):
1819
# Stores the best WordInfo (length, index) for any word that passes
1920
# through or ends at this node. Initialized to infinity.
2021
self.best_info: WordInfo = INF_WORD_INFO
21-
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
from typing import DefaultDict, Tuple
1+
from typing import Tuple
22

33
# Type alias for the best word info: (length, original_index)
44
WordInfo = Tuple[int, int]
55
# Initialize with a very large length to ensure the first word always wins
6-
INF_WORD_INFO: WordInfo = (float('inf'), float('inf'))
6+
INF_WORD_INFO: WordInfo = (float("inf"), float("inf"))

puzzles/heap/min_cost_to_connect_sticks/test_min_cost_connect_sticks.py

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@
44

55
class MinCostConnectSticksTestCase(unittest.TestCase):
66
def test_1(self):
7-
sticks = [3,5,4]
7+
sticks = [3, 5, 4]
88
expected = 19
99
actual = connect_sticks(sticks)
1010
self.assertEqual(expected, actual)
1111

1212
def test_2(self):
13-
sticks = [2,9,4,6]
13+
sticks = [2, 9, 4, 6]
1414
expected = 39
1515
actual = connect_sticks(sticks)
1616
self.assertEqual(expected, actual)
@@ -22,7 +22,7 @@ def test_3(self):
2222
self.assertEqual(expected, actual)
2323

2424
def test_4(self):
25-
sticks = [3,3,3]
25+
sticks = [3, 3, 3]
2626
expected = 15
2727
actual = connect_sticks(sticks)
2828
self.assertEqual(expected, actual)
@@ -34,38 +34,39 @@ def test_5(self):
3434
self.assertEqual(expected, actual)
3535

3636
def test_6(self):
37-
sticks = [7,10,16]
37+
sticks = [7, 10, 16]
3838
expected = 50
3939
actual = connect_sticks(sticks)
4040
self.assertEqual(expected, actual)
4141

4242
def test_7(self):
43-
sticks = [5,120,7,30,10]
43+
sticks = [5, 120, 7, 30, 10]
4444
expected = 258
4545
actual = connect_sticks(sticks)
4646
self.assertEqual(expected, actual)
4747

4848
def test_8(self):
49-
sticks = [100,200,300,400,500]
49+
sticks = [100, 200, 300, 400, 500]
5050
expected = 3300
5151
actual = connect_sticks(sticks)
5252
self.assertEqual(expected, actual)
5353

5454
def test_9(self):
55-
sticks = [20,20,20,20]
55+
sticks = [20, 20, 20, 20]
5656
expected = 160
5757
actual = connect_sticks(sticks)
5858
self.assertEqual(expected, actual)
5959

60+
6061
class MinCostConnectSticks2TestCase(unittest.TestCase):
6162
def test_1(self):
62-
sticks = [3,5,4]
63+
sticks = [3, 5, 4]
6364
expected = 19
6465
actual = connect_sticks_2(sticks)
6566
self.assertEqual(expected, actual)
6667

6768
def test_2(self):
68-
sticks = [2,9,4,6]
69+
sticks = [2, 9, 4, 6]
6970
expected = 39
7071
actual = connect_sticks_2(sticks)
7172
self.assertEqual(expected, actual)
@@ -77,7 +78,7 @@ def test_3(self):
7778
self.assertEqual(expected, actual)
7879

7980
def test_4(self):
80-
sticks = [3,3,3]
81+
sticks = [3, 3, 3]
8182
expected = 15
8283
actual = connect_sticks_2(sticks)
8384
self.assertEqual(expected, actual)
@@ -89,29 +90,29 @@ def test_5(self):
8990
self.assertEqual(expected, actual)
9091

9192
def test_6(self):
92-
sticks = [7,10,16]
93+
sticks = [7, 10, 16]
9394
expected = 50
9495
actual = connect_sticks_2(sticks)
9596
self.assertEqual(expected, actual)
9697

9798
def test_7(self):
98-
sticks = [5,120,7,30,10]
99+
sticks = [5, 120, 7, 30, 10]
99100
expected = 258
100101
actual = connect_sticks_2(sticks)
101102
self.assertEqual(expected, actual)
102103

103104
def test_8(self):
104-
sticks = [100,200,300,400,500]
105+
sticks = [100, 200, 300, 400, 500]
105106
expected = 3300
106107
actual = connect_sticks_2(sticks)
107108
self.assertEqual(expected, actual)
108109

109110
def test_9(self):
110-
sticks = [20,20,20,20]
111+
sticks = [20, 20, 20, 20]
111112
expected = 160
112113
actual = connect_sticks_2(sticks)
113114
self.assertEqual(expected, actual)
114115

115116

116-
if __name__ == '__main__':
117+
if __name__ == "__main__":
117118
unittest.main()

pystrings/memesorting/__init__.py

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,3 @@ def memesorting(meme):
2929
spelled_word += letter
3030

3131
return receiver.get(letters[spelled_word], "Vlad")
32-
33-
34-
Test.assert_equals(memesorting("This is programmer meme ecause it has bug"), "Roma")
35-
Test.assert_equals(
36-
memesorting("This is also programbur meme gecause it has needed key word"), "Roma"
37-
)
38-
Test.assert_equals(memesorting("This is edsigner meme cause it has key word"), "Danik")
39-
Test.assert_equals(
40-
memesorting("This could be chemistry meme but our gey word boom is too late"),
41-
"Roma",
42-
)
43-
Test.assert_equals(memesorting("This is meme"), "Vlad")

0 commit comments

Comments
 (0)