2023-10-31 04:58:52 +00:00
|
|
|
import json
|
|
|
|
|
2023-10-19 15:23:24 +00:00
|
|
|
import pytest
|
|
|
|
|
|
|
|
import stuff
|
2023-10-21 12:23:14 +00:00
|
|
|
import stdlib
|
2023-10-19 15:23:24 +00:00
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
|
|
("n", "expected"),
|
|
|
|
[
|
|
|
|
(0, 0),
|
|
|
|
(1, 1),
|
|
|
|
(5, 2),
|
|
|
|
(4, 2),
|
|
|
|
(8, 2),
|
|
|
|
(9, 3),
|
|
|
|
],
|
|
|
|
)
|
|
|
|
def test_find_sqrt_ish(n: int, expected: int):
|
|
|
|
assert stuff.find_sqrt_ish(n) == expected
|
2023-10-20 14:38:20 +00:00
|
|
|
|
|
|
|
|
2023-10-21 11:18:56 +00:00
|
|
|
@pytest.mark.parametrize(
|
|
|
|
("ops", "expected"),
|
|
|
|
[
|
|
|
|
(
|
|
|
|
(
|
|
|
|
[
|
|
|
|
("new",),
|
|
|
|
("push", -2),
|
|
|
|
("push", 0),
|
|
|
|
("push", -3),
|
|
|
|
("getMin",),
|
|
|
|
("pop",),
|
|
|
|
("top",),
|
|
|
|
("getMin",),
|
|
|
|
]
|
|
|
|
),
|
|
|
|
[
|
|
|
|
None,
|
|
|
|
None,
|
|
|
|
None,
|
|
|
|
None,
|
|
|
|
-3,
|
|
|
|
None,
|
|
|
|
0,
|
|
|
|
-2,
|
|
|
|
],
|
|
|
|
)
|
|
|
|
],
|
|
|
|
)
|
|
|
|
def test_min_stack(ops: list[tuple[str] | tuple[str, int]], expected: list[int | None]):
|
|
|
|
returned: list[int | None] = []
|
|
|
|
inst: stuff.MinStack | None = None
|
|
|
|
|
|
|
|
for op in ops:
|
|
|
|
if len(op) == 1:
|
|
|
|
if op[0] == "new":
|
|
|
|
inst = stuff.MinStack()
|
|
|
|
returned.append(None)
|
|
|
|
continue
|
|
|
|
|
|
|
|
returned.append(getattr(inst, op[0])())
|
|
|
|
continue
|
|
|
|
|
|
|
|
method, arg = op
|
|
|
|
returned.append(getattr(inst, method)(arg))
|
|
|
|
|
|
|
|
assert returned == expected
|
2023-10-21 12:23:14 +00:00
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
|
|
("head", "expected"),
|
|
|
|
[
|
|
|
|
(None, None),
|
|
|
|
(
|
|
|
|
stdlib.ListNode(
|
|
|
|
4, stdlib.ListNode(2, stdlib.ListNode(1, stdlib.ListNode(3)))
|
|
|
|
),
|
|
|
|
stdlib.ListNode(
|
|
|
|
1, stdlib.ListNode(2, stdlib.ListNode(3, stdlib.ListNode(4)))
|
|
|
|
),
|
|
|
|
),
|
2023-10-21 12:41:41 +00:00
|
|
|
(
|
|
|
|
stdlib.ListNode(
|
|
|
|
4,
|
|
|
|
stdlib.ListNode(
|
|
|
|
19,
|
|
|
|
stdlib.ListNode(
|
|
|
|
14,
|
|
|
|
stdlib.ListNode(
|
|
|
|
5,
|
|
|
|
stdlib.ListNode(
|
|
|
|
-3,
|
|
|
|
stdlib.ListNode(
|
|
|
|
1,
|
|
|
|
stdlib.ListNode(
|
|
|
|
8,
|
|
|
|
stdlib.ListNode(
|
|
|
|
5, stdlib.ListNode(11, stdlib.ListNode(15))
|
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
stdlib.ListNode(
|
|
|
|
-3,
|
|
|
|
stdlib.ListNode(
|
|
|
|
1,
|
|
|
|
stdlib.ListNode(
|
|
|
|
4,
|
|
|
|
stdlib.ListNode(
|
|
|
|
5,
|
|
|
|
stdlib.ListNode(
|
|
|
|
5,
|
|
|
|
stdlib.ListNode(
|
|
|
|
8,
|
|
|
|
stdlib.ListNode(
|
|
|
|
11,
|
|
|
|
stdlib.ListNode(
|
|
|
|
14, stdlib.ListNode(15, stdlib.ListNode(19))
|
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
2023-10-21 12:23:14 +00:00
|
|
|
],
|
|
|
|
)
|
2023-10-24 12:12:35 +00:00
|
|
|
def test_sort_linked_list(
|
|
|
|
head: stdlib.LinkedListNode | None, expected: stdlib.LinkedListNode | None
|
|
|
|
):
|
2023-10-21 12:23:14 +00:00
|
|
|
if head is None:
|
|
|
|
assert stuff.sort_linked_list(head) == expected
|
|
|
|
return
|
|
|
|
|
|
|
|
assert stuff.linked_list_to_list(
|
|
|
|
stuff.sort_linked_list(head)
|
|
|
|
) == stuff.linked_list_to_list(expected)
|
2023-10-21 19:45:16 +00:00
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
|
|
("root", "expected"),
|
|
|
|
[
|
|
|
|
(
|
|
|
|
stdlib.Node(
|
|
|
|
1,
|
|
|
|
left=stdlib.Node(2, left=stdlib.Node(4), right=stdlib.Node(5)),
|
|
|
|
right=stdlib.Node(3, right=stdlib.Node(7)),
|
|
|
|
),
|
|
|
|
[1, None, 2, 3, None, 4, 5, 7, None],
|
|
|
|
),
|
|
|
|
],
|
|
|
|
)
|
|
|
|
def test_connect_binary_tree_right(
|
2023-10-24 12:12:35 +00:00
|
|
|
root: stdlib.ConnectableBinaryTreeNode | None, expected: list[int | None] | None
|
2023-10-21 19:45:16 +00:00
|
|
|
):
|
|
|
|
if expected is None:
|
|
|
|
assert root is None
|
|
|
|
return
|
|
|
|
|
|
|
|
connected, serialized = stuff.connect_binary_tree_right(root)
|
|
|
|
assert connected is not None
|
|
|
|
assert serialized == expected
|
2023-10-21 20:34:42 +00:00
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
|
|
("root", "expected"),
|
|
|
|
[
|
|
|
|
(
|
|
|
|
stdlib.Node(
|
|
|
|
4,
|
|
|
|
right=stdlib.Node(0),
|
|
|
|
left=stdlib.Node(9, right=stdlib.Node(1), left=stdlib.Node(5)),
|
|
|
|
),
|
|
|
|
1026,
|
|
|
|
),
|
|
|
|
],
|
|
|
|
)
|
2023-10-24 12:12:35 +00:00
|
|
|
def test_connect_binary_tree_sum_numbers(
|
|
|
|
root: stdlib.BinaryTreeNode | None, expected: int
|
|
|
|
):
|
2023-10-21 20:34:42 +00:00
|
|
|
assert stuff.sum_binary_tree_path_ints(root) == expected
|
2023-10-24 12:12:35 +00:00
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
|
|
("inlist", "expected"),
|
|
|
|
[
|
|
|
|
(
|
|
|
|
[3, 5, 1, 6, 2, 0, 8, None, None, 7, 4],
|
|
|
|
stdlib.TreeNode(
|
|
|
|
3,
|
|
|
|
left=stdlib.TreeNode(
|
|
|
|
5,
|
|
|
|
left=stdlib.TreeNode(6),
|
|
|
|
right=stdlib.TreeNode(
|
|
|
|
2,
|
|
|
|
left=stdlib.TreeNode(7),
|
|
|
|
right=stdlib.TreeNode(4),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
right=stdlib.TreeNode(
|
|
|
|
1,
|
|
|
|
left=stdlib.TreeNode(0),
|
|
|
|
right=stdlib.TreeNode(8),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
],
|
|
|
|
)
|
|
|
|
def test_binary_tree_from_list(
|
|
|
|
inlist: list[int | None], expected: stdlib.BinaryTreeNode | None
|
|
|
|
):
|
|
|
|
assert stuff.binary_tree_from_list(inlist) == expected
|
2023-10-24 19:42:42 +00:00
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
|
|
("preorder", "inorder", "expected"),
|
|
|
|
[
|
|
|
|
(
|
|
|
|
[3, 9, 20, 15, 7],
|
|
|
|
[9, 3, 15, 20, 7],
|
|
|
|
stdlib.TreeNode(
|
|
|
|
3,
|
|
|
|
left=stdlib.TreeNode(9),
|
|
|
|
right=stdlib.TreeNode(
|
|
|
|
20, left=stdlib.TreeNode(15), right=stdlib.TreeNode(7)
|
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
(
|
|
|
|
[-1],
|
|
|
|
[-1],
|
|
|
|
stdlib.TreeNode(-1),
|
|
|
|
),
|
|
|
|
(
|
|
|
|
[1, 2],
|
|
|
|
[1, 2],
|
|
|
|
stdlib.TreeNode(1, right=stdlib.TreeNode(2)),
|
|
|
|
),
|
|
|
|
],
|
|
|
|
)
|
|
|
|
def test_binary_tree_from_preorder_inorder(
|
|
|
|
preorder: list[int], inorder: list[int], expected: stdlib.BinaryTreeNode
|
|
|
|
):
|
|
|
|
assert stuff.binary_tree_from_preorder_inorder(preorder, inorder) == expected
|
2023-10-24 23:46:01 +00:00
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
|
|
("board", "expected"),
|
|
|
|
[
|
|
|
|
(
|
|
|
|
[2, 3, 1, 1, 4],
|
|
|
|
[
|
|
|
|
[0, 1, 2, 3, 4],
|
|
|
|
[0, 1, 3, 4],
|
|
|
|
[0, 1, 4],
|
|
|
|
[0, 2, 3, 4],
|
|
|
|
],
|
|
|
|
),
|
|
|
|
],
|
|
|
|
)
|
|
|
|
def test_collect_complete_jump_paths_from_board(
|
|
|
|
board: list[int], expected: list[list[int]]
|
|
|
|
):
|
|
|
|
assert list(sorted(stuff.collect_complete_jump_paths_from_board(board))) == expected
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
|
|
("board", "expected"),
|
|
|
|
[
|
|
|
|
(
|
|
|
|
[2, 3, 1, 1, 4],
|
|
|
|
2,
|
|
|
|
),
|
|
|
|
(
|
|
|
|
[2, 3, 0, 1, 4],
|
|
|
|
2,
|
|
|
|
),
|
|
|
|
(
|
|
|
|
[1],
|
|
|
|
0,
|
|
|
|
),
|
|
|
|
(
|
|
|
|
[1, 2],
|
|
|
|
1,
|
|
|
|
),
|
2023-10-25 20:51:35 +00:00
|
|
|
(
|
|
|
|
[6, 2, 6, 1, 7, 9, 3, 5, 3, 7, 2, 8, 9, 4, 7, 7, 2, 2, 8, 4, 6, 6, 1, 3],
|
|
|
|
4,
|
|
|
|
),
|
|
|
|
(
|
|
|
|
[3, 4, 3, 2, 5, 4, 3],
|
|
|
|
3,
|
|
|
|
),
|
|
|
|
(
|
|
|
|
[3, 2, 1],
|
|
|
|
1,
|
|
|
|
),
|
|
|
|
(
|
|
|
|
[1, 2, 3],
|
|
|
|
2,
|
|
|
|
),
|
2023-10-24 23:46:01 +00:00
|
|
|
],
|
|
|
|
)
|
|
|
|
def test_count_min_jumps_from_board(board: list[int], expected: int):
|
|
|
|
assert stuff.count_min_jumps_from_board(board) == expected
|
2023-10-25 23:18:05 +00:00
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
|
|
("citations", "expected"),
|
|
|
|
[
|
|
|
|
(
|
|
|
|
[3, 0, 6, 1, 5],
|
|
|
|
3,
|
|
|
|
),
|
|
|
|
(
|
|
|
|
[1, 3, 1],
|
|
|
|
1,
|
|
|
|
),
|
|
|
|
(
|
|
|
|
[100],
|
|
|
|
1,
|
|
|
|
),
|
|
|
|
],
|
|
|
|
)
|
|
|
|
def test_h_index(citations: list[int], expected: int):
|
|
|
|
assert stuff.h_index(citations) == expected
|
2023-10-26 00:15:43 +00:00
|
|
|
|
|
|
|
|
2023-10-26 07:58:50 +00:00
|
|
|
@pytest.mark.parametrize(
|
|
|
|
("cls",),
|
|
|
|
[
|
|
|
|
(stuff.SlowRandomizedSet,),
|
|
|
|
(stuff.RandomizedSet,),
|
|
|
|
],
|
|
|
|
)
|
|
|
|
def test_randomized_set(cls: type[stuff.RandomizedSet] | type[stuff.SlowRandomizedSet]):
|
|
|
|
inst = cls()
|
2023-10-26 00:15:43 +00:00
|
|
|
|
|
|
|
assert inst.insert(1) is True
|
|
|
|
assert inst.remove(2) is False
|
|
|
|
assert inst.insert(2) is True
|
|
|
|
assert inst.getRandom() in (1, 2)
|
|
|
|
assert inst.remove(1) is True
|
|
|
|
assert inst.insert(2) is False
|
|
|
|
assert inst.getRandom() == 2
|
|
|
|
|
2023-10-26 07:58:50 +00:00
|
|
|
inst = cls()
|
2023-10-26 00:15:43 +00:00
|
|
|
|
|
|
|
assert inst.insert(1) is True
|
|
|
|
assert inst.insert(10) is True
|
|
|
|
assert inst.insert(20) is True
|
|
|
|
assert inst.insert(30) is True
|
|
|
|
|
|
|
|
seen: set[int] = set()
|
|
|
|
|
2023-10-26 07:58:50 +00:00
|
|
|
for _ in range(10_000):
|
2023-10-26 00:15:43 +00:00
|
|
|
seen.add(inst.getRandom())
|
|
|
|
|
|
|
|
assert seen == {1, 10, 20, 30}
|
2023-10-26 07:58:50 +00:00
|
|
|
|
|
|
|
# ["remove","remove","insert","getRandom","remove","insert"]
|
|
|
|
# [[0],[0],[0],[],[0],[0]]
|
|
|
|
|
|
|
|
inst = cls()
|
|
|
|
|
|
|
|
assert inst.remove(0) is False
|
|
|
|
assert inst.remove(0) is False
|
|
|
|
assert inst.insert(0) is True
|
|
|
|
assert inst.getRandom() == 0
|
|
|
|
assert inst.remove(0) is True
|
|
|
|
assert inst.insert(0) is True
|
|
|
|
|
|
|
|
# ["RandomizedSet","insert","insert","remove","insert","remove","getRandom"]
|
|
|
|
# [[],[0],[1],[0],[2],[1],[]]
|
|
|
|
|
|
|
|
inst = cls()
|
|
|
|
|
|
|
|
assert inst.insert(0) is True
|
|
|
|
assert inst.insert(1) is True
|
|
|
|
assert inst.remove(0) is True
|
|
|
|
assert inst.insert(2) is True
|
|
|
|
assert inst.remove(1) is True
|
|
|
|
assert inst.getRandom() == 2
|
2023-10-26 23:59:11 +00:00
|
|
|
|
|
|
|
|
2023-10-27 12:19:03 +00:00
|
|
|
def test_trie_single_letter():
|
|
|
|
trie = stuff.Trie()
|
|
|
|
|
|
|
|
assert trie.insert("a") is None
|
|
|
|
assert trie.search("a") is True
|
|
|
|
assert trie.startsWith("a") is True
|
|
|
|
|
|
|
|
|
|
|
|
def test_trie_prefix_leaf():
|
2023-10-26 23:59:11 +00:00
|
|
|
trie = stuff.Trie()
|
|
|
|
|
|
|
|
assert trie.insert("apple") is None
|
|
|
|
assert trie.search("apple") is True
|
|
|
|
assert trie.search("app") is False
|
|
|
|
assert trie.startsWith("app") is True
|
|
|
|
assert trie.insert("app") is None
|
|
|
|
assert trie.search("app") is True
|
2023-10-27 12:19:03 +00:00
|
|
|
|
|
|
|
|
|
|
|
def test_trie_two_letter():
|
|
|
|
trie = stuff.Trie()
|
|
|
|
|
|
|
|
assert trie.insert("ab") is None
|
|
|
|
assert trie.search("a") is False
|
|
|
|
assert trie.startsWith("a") is True
|
|
|
|
|
|
|
|
|
|
|
|
def test_trie_busy():
|
|
|
|
trie = stuff.Trie()
|
|
|
|
|
|
|
|
assert trie.insert("app") is None
|
|
|
|
assert trie.insert("apple") is None
|
|
|
|
assert trie.insert("beer") is None
|
|
|
|
assert trie.insert("add") is None
|
|
|
|
assert trie.insert("jam") is None
|
|
|
|
assert trie.insert("rental") is None
|
|
|
|
assert trie.search("apps") is False
|
|
|
|
assert trie.search("app") is True
|
|
|
|
assert trie.search("ad") is False
|
|
|
|
assert trie.search("applepie") is False
|
|
|
|
assert trie.search("rest") is False
|
|
|
|
assert trie.search("jan") is False
|
|
|
|
assert trie.search("rent") is False
|
|
|
|
assert trie.search("beer") is True
|
|
|
|
assert trie.search("jam") is True
|
|
|
|
assert trie.startsWith("apps") is False
|
|
|
|
assert trie.startsWith("app") is True
|
|
|
|
assert trie.startsWith("ad") is True
|
|
|
|
assert trie.startsWith("applepie") is False
|
|
|
|
assert trie.startsWith("rest") is False
|
|
|
|
assert trie.startsWith("jan") is False
|
|
|
|
assert trie.startsWith("rent") is True
|
|
|
|
assert trie.startsWith("beer") is True
|
|
|
|
assert trie.startsWith("jam") is True
|
2023-10-28 12:21:39 +00:00
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
|
|
("nums", "expected"),
|
|
|
|
[
|
|
|
|
(
|
|
|
|
[-2, 1, -3, 4, -1, 2, 1, -5, 4],
|
|
|
|
6,
|
|
|
|
),
|
|
|
|
(
|
|
|
|
[1],
|
|
|
|
1,
|
|
|
|
),
|
|
|
|
(
|
|
|
|
[5, 4, -1, 7, 8],
|
|
|
|
23,
|
|
|
|
),
|
2023-10-28 12:24:17 +00:00
|
|
|
(
|
|
|
|
[-2, 1],
|
|
|
|
1,
|
|
|
|
),
|
2023-10-31 04:58:52 +00:00
|
|
|
(
|
|
|
|
json.load(open(".testdata/max_sub_array0.json")),
|
|
|
|
11081,
|
|
|
|
),
|
2023-10-28 12:21:39 +00:00
|
|
|
],
|
|
|
|
)
|
2023-10-31 04:58:52 +00:00
|
|
|
def test_max_sub_array(nums: list[int], expected: int):
|
2023-10-28 12:21:39 +00:00
|
|
|
assert stuff.sum_max_sub_array(nums) == expected
|
2023-11-01 04:12:36 +00:00
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
|
|
("inlist",),
|
|
|
|
[
|
|
|
|
([[2, 3, 4], [1, 7], [1], [1, 5, 6, 8], [4], [4], [2], [4]],),
|
|
|
|
([[2, 4], [1, 3], [2, 4], [1, 3]],),
|
|
|
|
],
|
|
|
|
)
|
|
|
|
def test_copy_neighborly_node(inlist):
|
|
|
|
orig = stuff.neighborly_node_from_list(inlist)
|
|
|
|
copied = stuff.neighborly_node_from_list(stuff.neighborly_node_to_list(orig))
|
|
|
|
|
|
|
|
assert id(orig) != id(copied)
|
|
|
|
assert orig == copied
|
|
|
|
assert stuff.neighborly_node_to_list(orig) == stuff.neighborly_node_to_list(copied)
|