-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
e893fd7
commit 8c6ecce
Showing
14 changed files
with
1,867 additions
and
0 deletions.
There are no files selected for viewing
Empty file.
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
#!/usr/bin/env python3 | ||
"""Tests for `datastructures._searching`.""" | ||
from __future__ import annotations | ||
|
||
from typing import Iterator | ||
|
||
import pytest | ||
|
||
from nrw.algorithms._seraching import ( | ||
breadth_first_search, | ||
depth_first_search, | ||
linear_search, | ||
) | ||
from nrw.datastructures import Edge, Graph, List, Vertex | ||
|
||
|
||
def test_linear_search() -> None: | ||
lst: List[int] = List() | ||
for i in range(5): | ||
lst.append(i) | ||
|
||
assert linear_search(lst, 3) == 3 | ||
assert lst.content == 3 | ||
assert linear_search(lst, 10) == 5 | ||
assert not lst.has_access | ||
|
||
|
||
def test_depth_first_search() -> None: | ||
graph: Graph = Graph() | ||
vertex1: Vertex = Vertex("A") | ||
graph.add_vertex(vertex1) | ||
vertex2: Vertex = Vertex("B") | ||
graph.add_vertex(vertex2) | ||
vertex3: Vertex = Vertex("C") | ||
graph.add_vertex(vertex3) | ||
edge1: Edge = Edge(vertex1, vertex2, 1) | ||
graph.add_edge(edge1) | ||
edge2: Edge = Edge(vertex1, vertex3, 1) | ||
graph.add_edge(edge2) | ||
edge3: Edge = Edge(vertex2, vertex3, 1) | ||
graph.add_edge(edge3) | ||
|
||
expected_result: Iterator[Vertex] = iter((vertex1, vertex2, vertex3)) | ||
result: List[Vertex] = depth_first_search(graph, vertex1) | ||
result.to_first() | ||
while result.has_access: | ||
assert result.content is next(expected_result) | ||
result.next() | ||
|
||
|
||
def test_breadth_first_search() -> None: | ||
graph: Graph = Graph() | ||
vertex1: Vertex = Vertex("A") | ||
graph.add_vertex(vertex1) | ||
vertex2: Vertex = Vertex("B") | ||
graph.add_vertex(vertex2) | ||
vertex3: Vertex = Vertex("C") | ||
graph.add_vertex(vertex3) | ||
edge1: Edge = Edge(vertex1, vertex2, 1) | ||
graph.add_edge(edge1) | ||
edge2: Edge = Edge(vertex1, vertex3, 1) | ||
graph.add_edge(edge2) | ||
edge3: Edge = Edge(vertex2, vertex3, 1) | ||
graph.add_edge(edge3) | ||
|
||
expected_result: Iterator[Vertex] = iter((vertex1, vertex2, vertex3)) | ||
result: List[Vertex] = breadth_first_search(graph, vertex1) | ||
result.to_first() | ||
while result.has_access: | ||
assert result.content is next(expected_result) | ||
result.next() | ||
|
||
|
||
if __name__ == "__main__": | ||
raise SystemExit(pytest.main()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,154 @@ | ||
#!/usr/bin/env python3 | ||
"""Tests for `datastructures._sorting`.""" | ||
from __future__ import annotations | ||
|
||
from typing import Callable | ||
|
||
import pytest | ||
|
||
from nrw.algorithms._sorting import ( | ||
bubble_sort, | ||
insertion_sort, | ||
merge_sort, | ||
quick_sort, | ||
selection_sort, | ||
) | ||
from nrw.datastructures import ComparableContentT, List | ||
|
||
|
||
@pytest.fixture() | ||
def empty_list() -> List[int]: | ||
return List() | ||
|
||
|
||
@pytest.fixture() | ||
def sorted_list() -> List[int]: | ||
lst: List[int] = List() | ||
lst.append(1) | ||
lst.append(2) | ||
lst.append(3) | ||
lst.append(3) | ||
lst.append(5) | ||
lst.append(10) | ||
return lst | ||
|
||
|
||
@pytest.fixture() | ||
def unsorted_list() -> List[int]: | ||
lst: List[int] = List() | ||
lst.append(3) | ||
lst.append(1) | ||
lst.append(3) | ||
lst.append(10) | ||
lst.append(5) | ||
return lst | ||
|
||
|
||
def _is_sorted(lst: List[ComparableContentT]) -> bool: | ||
lst.to_first() | ||
while lst.has_access and lst._current.next_node is not None: | ||
previous: ComparableContentT | None = lst.content | ||
lst.next() | ||
if previous > lst.content: # type: ignore[operator] | ||
return False | ||
return True | ||
|
||
|
||
def _have_same_elements( | ||
lst1: List[ComparableContentT], | ||
lst2: List[ComparableContentT], | ||
) -> bool: | ||
elements_of_lst1: list[ComparableContentT] = [] | ||
lst1.to_first() | ||
while lst1.has_access: | ||
elements_of_lst1.append(lst1.content) # type: ignore[arg-type] | ||
lst1.next() | ||
|
||
elements_of_lst2: list[ComparableContentT] = [] | ||
lst2.to_first() | ||
while lst2.has_access: | ||
elements_of_lst2.append(lst2.content) # type: ignore[arg-type] | ||
lst2.next() | ||
|
||
return sorted(elements_of_lst1) == sorted(elements_of_lst2) | ||
|
||
|
||
def _copy(lst: List[ComparableContentT]) -> List[ComparableContentT]: | ||
copy: List[ComparableContentT] = List() | ||
lst.to_first() | ||
while lst.has_access: | ||
copy.append(lst.content) | ||
lst.next() | ||
return copy | ||
|
||
|
||
def test_is_sorted_on_empty_list(empty_list: List[int]) -> None: | ||
assert _is_sorted(empty_list) | ||
|
||
|
||
def test_is_sorted_on_sorted_list(sorted_list: List[int]) -> None: | ||
assert _is_sorted(sorted_list) | ||
|
||
|
||
def test_is_sorted_on_unsorted_list(unsorted_list: List[int]) -> None: | ||
assert not _is_sorted(unsorted_list) | ||
|
||
|
||
def test_have_same_elements() -> None: | ||
lst1: List[int] = List() | ||
lst1.append(1) | ||
lst1.append(2) | ||
lst1.append(3) | ||
|
||
lst2: List[int] = List() | ||
lst2.append(3) | ||
lst2.append(1) | ||
lst2.append(2) | ||
|
||
assert _have_same_elements(lst1, lst2) | ||
|
||
assert _have_same_elements(List[int](), List[int]()) | ||
assert not _have_same_elements(lst1, List[int]()) | ||
|
||
|
||
@pytest.mark.parametrize( | ||
"sorting_algorithm", | ||
[bubble_sort, insertion_sort, merge_sort, quick_sort, selection_sort], | ||
) | ||
def test_sorting_algorithm_on_empty_list( | ||
sorting_algorithm: Callable[[List[int]], List[int]], | ||
empty_list: List[int], | ||
) -> None: | ||
newly_sorted_list: List[int] = sorting_algorithm(empty_list) | ||
assert _is_sorted(newly_sorted_list) | ||
assert _have_same_elements(newly_sorted_list, empty_list) | ||
|
||
|
||
@pytest.mark.parametrize( | ||
"sorting_algorithm", | ||
[bubble_sort, insertion_sort, merge_sort, quick_sort, selection_sort], | ||
) | ||
def test_sorting_algorithm_on_sorted_list( | ||
sorting_algorithm: Callable[[List[int]], List[int]], | ||
sorted_list: List[int], | ||
) -> None: | ||
newly_sorted_list: List[int] = sorting_algorithm(_copy(sorted_list)) | ||
assert _is_sorted(newly_sorted_list) | ||
assert _have_same_elements(newly_sorted_list, sorted_list) | ||
|
||
|
||
@pytest.mark.parametrize( | ||
"sorting_algorithm", | ||
[bubble_sort, insertion_sort, merge_sort, quick_sort, selection_sort], | ||
) | ||
def test_sorting_algorithm_on_unsorted_list( | ||
sorting_algorithm: Callable[[List[int]], List[int]], | ||
unsorted_list: List[int], | ||
) -> None: | ||
newly_sorted_list: List[int] = sorting_algorithm(_copy(unsorted_list)) | ||
assert _is_sorted(newly_sorted_list) | ||
assert _have_same_elements(newly_sorted_list, unsorted_list) | ||
|
||
|
||
if __name__ == "__main__": | ||
raise SystemExit(pytest.main()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,157 @@ | ||
#!/usr/bin/env python3 | ||
"""Tests for `datastructures._traversal`.""" | ||
from __future__ import annotations | ||
|
||
from typing import TYPE_CHECKING, Callable, Iterator | ||
|
||
import pytest | ||
|
||
from nrw.algorithms._traversal import ( | ||
inorder, | ||
levelorder, | ||
postorder, | ||
preorder, | ||
reverse_inorder, | ||
) | ||
from nrw.datastructures import BinarySearchTree, BinaryTree | ||
|
||
if TYPE_CHECKING: | ||
from nrw.datastructures import List | ||
|
||
|
||
@pytest.fixture() | ||
def bst() -> BinarySearchTree[int]: | ||
tree: BinarySearchTree[int] = BinarySearchTree() | ||
tree.insert(1) | ||
tree.insert(0) | ||
tree.insert(2) | ||
return tree | ||
|
||
|
||
@pytest.fixture() | ||
def binary_tree() -> BinaryTree[int]: | ||
tree: BinaryTree[int] = BinaryTree() | ||
tree.content = 1 | ||
tree.left_tree.content = 0 | ||
tree.right_tree.content = 2 | ||
return tree | ||
|
||
|
||
@pytest.mark.parametrize("empty_tree", [BinaryTree[int](), BinarySearchTree[int]()]) | ||
@pytest.mark.parametrize( | ||
"traverse", | ||
[inorder, postorder, preorder, reverse_inorder, levelorder], | ||
) | ||
def test_traversal_on_empty_tree( | ||
empty_tree: BinaryTree[int] | BinarySearchTree[int], | ||
traverse: Callable[[BinaryTree[int] | BinarySearchTree[int]], List[int]], | ||
) -> None: | ||
assert traverse(empty_tree).is_empty | ||
|
||
|
||
def test_inorder_traversal_on_binary_tree(binary_tree: BinaryTree[int]) -> None: | ||
expected_result: Iterator[int] = iter((0, 1, 2)) | ||
result: List[int] = inorder(binary_tree) | ||
|
||
result.to_first() | ||
while result.has_access: | ||
assert result.content == next(expected_result) | ||
result.next() | ||
|
||
|
||
def test_postorder_traversal_on_binary_tree(binary_tree: BinaryTree[int]) -> None: | ||
expected_result: Iterator[int] = iter((0, 2, 1)) | ||
result: List[int] = postorder(binary_tree) | ||
|
||
result.to_first() | ||
while result.has_access: | ||
assert result.content == next(expected_result) | ||
result.next() | ||
|
||
|
||
def test_preorder_traversal_on_binary_tree(binary_tree: BinaryTree[int]) -> None: | ||
expected_result: Iterator[int] = iter((1, 0, 2)) | ||
result: List[int] = preorder(binary_tree) | ||
|
||
result.to_first() | ||
while result.has_access: | ||
assert result.content == next(expected_result) | ||
result.next() | ||
|
||
|
||
def test_reverse_inorder_traversal_on_binary_tree(binary_tree: BinaryTree[int]) -> None: | ||
expected_result: Iterator[int] = iter((2, 1, 0)) | ||
result: List[int] = reverse_inorder(binary_tree) | ||
|
||
result.to_first() | ||
while result.has_access: | ||
assert result.content == next(expected_result) | ||
result.next() | ||
|
||
|
||
def test_levelorder_traversal_on_binary_tree(binary_tree: BinaryTree[int]) -> None: | ||
expected_result: Iterator[int] = iter((1, 0, 2)) | ||
result: List[int] = levelorder(binary_tree) | ||
|
||
result.to_first() | ||
while result.has_access: | ||
assert result.content == next(expected_result) | ||
result.next() | ||
|
||
|
||
def test_inorder_traversal_on_binary_search_tree(bst: BinarySearchTree[int]) -> None: | ||
expected_result: Iterator[int] = iter((0, 1, 2)) | ||
result: List[int] = inorder(bst) | ||
|
||
result.to_first() | ||
while result.has_access: | ||
assert result.content == next(expected_result) | ||
result.next() | ||
|
||
|
||
def test_postorder_traversal_on_binary_search_tree(bst: BinarySearchTree[int]) -> None: | ||
expected_result: Iterator[int] = iter((0, 2, 1)) | ||
result: List[int] = postorder(bst) | ||
|
||
result.to_first() | ||
while result.has_access: | ||
assert result.content == next(expected_result) | ||
result.next() | ||
|
||
|
||
def test_preorder_traversal_on_binary_search_tree(bst: BinarySearchTree[int]) -> None: | ||
expected_result: Iterator[int] = iter((1, 0, 2)) | ||
result: List[int] = preorder(bst) | ||
|
||
result.to_first() | ||
while result.has_access: | ||
assert result.content == next(expected_result) | ||
result.next() | ||
|
||
|
||
def test_reverse_inorder_traversal_on_binary_search_tree( | ||
bst: BinarySearchTree[int], | ||
) -> None: | ||
expected_result: Iterator[int] = iter((2, 1, 0)) | ||
result: List[int] = reverse_inorder(bst) | ||
|
||
result.to_first() | ||
while result.has_access: | ||
assert result.content == next(expected_result) | ||
result.next() | ||
|
||
|
||
def test_levelorder_traversal_on_binary_search_tree( | ||
bst: BinarySearchTree[int], | ||
) -> None: | ||
expected_result: Iterator[int] = iter((1, 0, 2)) | ||
result: List[int] = levelorder(bst) | ||
|
||
result.to_first() | ||
while result.has_access: | ||
assert result.content == next(expected_result) | ||
result.next() | ||
|
||
|
||
if __name__ == "__main__": | ||
raise SystemExit(pytest.main()) |
Empty file.
Oops, something went wrong.