Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 9 additions & 7 deletions searches/binary_search.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@
import bisect
from typing import List, Optional

from searches.comparable_type import ComparableType


def bisect_left(
sorted_collection: List[int], item: int, lo: int = 0, hi: int = -1
sorted_collection: List[ComparableType], item: ComparableType, lo: int = 0, hi: int = -1
) -> int:
"""
Locates the first element in a sorted array that is larger or equal to a given
Expand Down Expand Up @@ -60,7 +62,7 @@ def bisect_left(


def bisect_right(
sorted_collection: List[int], item: int, lo: int = 0, hi: int = -1
sorted_collection: List[ComparableType], item: ComparableType, lo: int = 0, hi: int = -1
) -> int:
"""
Locates the first element in a sorted array that is larger than a given value.
Expand Down Expand Up @@ -105,7 +107,7 @@ def bisect_right(


def insort_left(
sorted_collection: List[int], item: int, lo: int = 0, hi: int = -1
sorted_collection: List[ComparableType], item: ComparableType, lo: int = 0, hi: int = -1
) -> None:
"""
Inserts a given value into a sorted array before other values with the same value.
Expand Down Expand Up @@ -148,7 +150,7 @@ def insort_left(


def insort_right(
sorted_collection: List[int], item: int, lo: int = 0, hi: int = -1
sorted_collection: List[ComparableType], item: ComparableType, lo: int = 0, hi: int = -1
) -> None:
"""
Inserts a given value into a sorted array after other values with the same value.
Expand Down Expand Up @@ -190,7 +192,7 @@ def insort_right(
sorted_collection.insert(bisect_right(sorted_collection, item, lo, hi), item)


def binary_search(sorted_collection: List[int], item: int) -> Optional[int]:
def binary_search(sorted_collection: List[ComparableType], item: ComparableType) -> Optional[int]:
"""Pure implementation of binary search algorithm in Python

Be careful collection must be ascending sorted, otherwise result will be
Expand Down Expand Up @@ -228,7 +230,7 @@ def binary_search(sorted_collection: List[int], item: int) -> Optional[int]:
return None


def binary_search_std_lib(sorted_collection: List[int], item: int) -> Optional[int]:
def binary_search_std_lib(sorted_collection: List[ComparableType], item: ComparableType) -> Optional[int]:
"""Pure implementation of binary search algorithm in Python using stdlib

Be careful collection must be ascending sorted, otherwise result will be
Expand Down Expand Up @@ -258,7 +260,7 @@ def binary_search_std_lib(sorted_collection: List[int], item: int) -> Optional[i


def binary_search_by_recursion(
sorted_collection: List[int], item: int, left: int, right: int
sorted_collection: List[ComparableType], item: ComparableType, left: int, right: int
) -> Optional[int]:

"""Pure implementation of binary search algorithm in Python by recursion
Expand Down
2 changes: 1 addition & 1 deletion searches/binary_tree_traversal.py
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ def post_order_iter(node: TreeNode) -> None:
print(stack2.pop().data, end=",")


def prompt(s: str = "", width=50, char="*") -> str:
def prompt(s: str = "", width: int = 50, char: str = "*") -> str:
if not s:
return "\n" + width * char
left, extra = divmod(width - len(s) - 2, 2)
Expand Down
28 changes: 28 additions & 0 deletions searches/comparable_type.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
from abc import abstractmethod
from typing import Protocol, TypeVar

ComparableType = TypeVar('ComparableType', bound='Comparable')


class Comparable(Protocol):
@abstractmethod
def __lt__(self: ComparableType, other: ComparableType) -> bool:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As there is no test file in this pull request nor any test function or class in the file searches/comparable_type.py, please provide doctest for the function __lt__

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As there is no test file in this pull request nor any test function or class in the file searches/comparable_type.py, please provide doctest for the function __lt__

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As there is no test file in this pull request nor any test function or class in the file searches/comparable_type.py, please provide doctest for the function __lt__

pass

@abstractmethod
def __le__(self: ComparableType, other: ComparableType) -> bool:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As there is no test file in this pull request nor any test function or class in the file searches/comparable_type.py, please provide doctest for the function __le__

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As there is no test file in this pull request nor any test function or class in the file searches/comparable_type.py, please provide doctest for the function __le__

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As there is no test file in this pull request nor any test function or class in the file searches/comparable_type.py, please provide doctest for the function __le__

pass

@abstractmethod
def __gt__(self: ComparableType, other: ComparableType) -> bool:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As there is no test file in this pull request nor any test function or class in the file searches/comparable_type.py, please provide doctest for the function __gt__

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As there is no test file in this pull request nor any test function or class in the file searches/comparable_type.py, please provide doctest for the function __gt__

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As there is no test file in this pull request nor any test function or class in the file searches/comparable_type.py, please provide doctest for the function __gt__

pass

@abstractmethod
def __ge__(self: ComparableType, other: ComparableType) -> bool:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As there is no test file in this pull request nor any test function or class in the file searches/comparable_type.py, please provide doctest for the function __ge__

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As there is no test file in this pull request nor any test function or class in the file searches/comparable_type.py, please provide doctest for the function __ge__

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As there is no test file in this pull request nor any test function or class in the file searches/comparable_type.py, please provide doctest for the function __ge__

pass

@abstractmethod
def __eq__(self: ComparableType, other: object) -> bool:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As there is no test file in this pull request nor any test function or class in the file searches/comparable_type.py, please provide doctest for the function __eq__

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As there is no test file in this pull request nor any test function or class in the file searches/comparable_type.py, please provide doctest for the function __eq__

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As there is no test file in this pull request nor any test function or class in the file searches/comparable_type.py, please provide doctest for the function __eq__

if not isinstance(other, type(self)):
return False
raise NotImplemented
6 changes: 5 additions & 1 deletion searches/double_linear_search.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
from __future__ import annotations

from typing import TypeVar

def double_linear_search(array: list[int], search_item: int) -> int:
T = TypeVar('T')


def double_linear_search(array: list[T], search_item: T) -> int:
"""
Iterate through the array from both sides to find the index of search_item.

Expand Down
7 changes: 6 additions & 1 deletion searches/double_linear_search_recursion.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
def search(list_data: list, key: int, left: int = 0, right: int = 0) -> int:
from typing import TypeVar

T = TypeVar('T')


def search(list_data: list[T], key: T, left: int = 0, right: int = 0) -> int:
"""
Iterate through the array to find the index of key using recursion.
:param list_data: the list to be searched
Expand Down
5 changes: 4 additions & 1 deletion searches/fibonacci_search.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
python3 fibonacci_search.py
"""
from functools import lru_cache
from typing import TypeVar

from searches.comparable_type import Comparable, ComparableType


@lru_cache()
Expand Down Expand Up @@ -54,7 +57,7 @@ def fibonacci(k: int) -> int:
return fibonacci(k - 1) + fibonacci(k - 2)


def fibonacci_search(arr: list, val: int) -> int:
def fibonacci_search(arr: list[ComparableType], val: ComparableType) -> int:
"""A pure Python implementation of a fibonacci search algorithm.

Parameters
Expand Down
2 changes: 1 addition & 1 deletion searches/hill_climbing.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ def __str__(self):


def hill_climbing(
search_prob,
search_prob: SearchProblem,
find_max: bool = True,
max_x: float = math.inf,
min_x: float = -math.inf,
Expand Down
17 changes: 11 additions & 6 deletions searches/interpolation_search.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
"""
This is pure Python implementation of interpolation search algorithm
"""
from typing import Optional

from searches.comparable_type import ComparableType

def interpolation_search(sorted_collection, item):

def interpolation_search(sorted_collection: list[int], item: int) -> Optional[int]:
"""Pure implementation of interpolation search algorithm in Python
Be careful collection must be ascending sorted, otherwise result will be
unpredictable
Expand All @@ -23,7 +26,7 @@ def interpolation_search(sorted_collection, item):
return None

point = left + ((item - sorted_collection[left]) * (right - left)) // (
sorted_collection[right] - sorted_collection[left]
sorted_collection[right] - sorted_collection[left]
)

# out of range check
Expand All @@ -48,8 +51,10 @@ def interpolation_search(sorted_collection, item):
return None


def interpolation_search_by_recursion(sorted_collection, item, left, right):

def interpolation_search_by_recursion(sorted_collection: list[int],
item: int,
left: int,
right: int) -> Optional[int]:
"""Pure implementation of interpolation search algorithm in Python by recursion
Be careful collection must be ascending sorted, otherwise result will be
unpredictable
Expand All @@ -67,7 +72,7 @@ def interpolation_search_by_recursion(sorted_collection, item, left, right):
return None

point = left + ((item - sorted_collection[left]) * (right - left)) // (
sorted_collection[right] - sorted_collection[left]
sorted_collection[right] - sorted_collection[left]
)

# out of range check
Expand All @@ -91,7 +96,7 @@ def interpolation_search_by_recursion(sorted_collection, item, left, right):
)


def __assert_sorted(collection):
def __assert_sorted(collection: list[ComparableType]):
"""Check if collection is ascending sorted, if not - raises :py:class:`ValueError`
:param collection: collection
:return: True if collection is ascending sorted
Expand Down
4 changes: 3 additions & 1 deletion searches/jump_search.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@

import math

from searches.comparable_type import ComparableType

def jump_search(arr: list, x: int) -> int:

def jump_search(arr: list[ComparableType], x: ComparableType) -> int:
"""
Pure Python implementation of the jump search algorithm.
Examples:
Expand Down
7 changes: 5 additions & 2 deletions searches/linear_search.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,12 @@
For manual testing run:
python3 linear_search.py
"""
from typing import TypeVar

T = TypeVar('T')

def linear_search(sequence: list, target: int) -> int:

def linear_search(sequence: list[T], target: T) -> int:
"""A pure Python implementation of a linear search algorithm

:param sequence: a collection with comparable items (as sorted items not required
Expand All @@ -33,7 +36,7 @@ def linear_search(sequence: list, target: int) -> int:
return -1


def rec_linear_search(sequence: list, low: int, high: int, target: int) -> int:
def rec_linear_search(sequence: list[T], low: int, high: int, target: T) -> int:
"""
A pure Python implementation of a recursive linear search algorithm

Expand Down
10 changes: 8 additions & 2 deletions searches/quick_select.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,15 @@
https://en.wikipedia.org/wiki/Quickselect
"""
import random
from typing import Optional

from searches.comparable_type import ComparableType

def _partition(data: list, pivot) -> tuple:

def _partition(
data: list[ComparableType],
pivot: ComparableType
) -> tuple[list[ComparableType], list[ComparableType], list[ComparableType]]:
"""
Three way partition the data into smaller, equal and greater lists,
in relationship to the pivot
Expand All @@ -26,7 +32,7 @@ def _partition(data: list, pivot) -> tuple:
return less, equal, greater


def quick_select(items: list, index: int):
def quick_select(items: list[ComparableType], index: int) -> Optional[ComparableType]:
"""
>>> quick_select([2, 4, 5, 7, 899, 54, 32], 5)
54
Expand Down
5 changes: 4 additions & 1 deletion searches/sentinel_linear_search.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,12 @@
For manual testing run:
python sentinel_linear_search.py
"""
from typing import Optional

from searches.comparable_type import ComparableType

def sentinel_linear_search(sequence, target):

def sentinel_linear_search(sequence: list[ComparableType], target: ComparableType) -> Optional[int]:
"""Pure implementation of sentinel linear search algorithm in Python

:param sequence: some sequence with comparable items
Expand Down
4 changes: 3 additions & 1 deletion searches/simple_binary_search.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@
"""
from __future__ import annotations

from searches.comparable_type import ComparableType

def binary_search(a_list: list[int], item: int) -> bool:

def binary_search(a_list: list[ComparableType], item: ComparableType) -> bool:
"""
>>> test_list = [0, 1, 2, 8, 13, 17, 19, 32, 42]
>>> print(binary_search(test_list, 3))
Expand Down
38 changes: 21 additions & 17 deletions searches/simulated_annealing.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,16 @@


def simulated_annealing(
search_prob,
find_max: bool = True,
max_x: float = math.inf,
min_x: float = -math.inf,
max_y: float = math.inf,
min_y: float = -math.inf,
visualization: bool = False,
start_temperate: float = 100,
rate_of_decrease: float = 0.01,
threshold_temp: float = 1,
search_prob: SearchProblem,
find_max: bool = True,
max_x: float = math.inf,
min_x: float = -math.inf,
max_y: float = math.inf,
min_y: float = -math.inf,
visualization: bool = False,
start_temperate: float = 100,
rate_of_decrease: float = 0.01,
threshold_temp: float = 1,
) -> SearchProblem:
"""
Implementation of the simulated annealing algorithm. We start with a given state,
Expand Down Expand Up @@ -51,17 +51,17 @@ def simulated_annealing(
next_state = None
neighbors = current_state.get_neighbors()
while (
next_state is None and neighbors
next_state is None and neighbors
): # till we do not find a neighbor that we can move to
index = random.randint(0, len(neighbors) - 1) # picking a random neighbor
picked_neighbor = neighbors.pop(index)
change = picked_neighbor.score() - current_score

if (
picked_neighbor.x > max_x
or picked_neighbor.x < min_x
or picked_neighbor.y > max_y
or picked_neighbor.y < min_y
picked_neighbor.x > max_x
or picked_neighbor.x < min_x
or picked_neighbor.y > max_y
or picked_neighbor.y < min_y
):
continue # neighbor outside our bounds

Expand All @@ -71,7 +71,7 @@ def simulated_annealing(
next_state = picked_neighbor
else:
probability = (math.e) ** (
change / current_temp
change / current_temp
) # probability generation function
if random.random() < probability: # random number within probability
next_state = picked_neighbor
Expand All @@ -90,14 +90,16 @@ def simulated_annealing(
plt.xlabel("Iterations")
plt.ylabel("Function values")
plt.show()

assert best_state is not None # This is a mypy issue, it does not recognize the none being set at the start of the loop
return best_state


if __name__ == "__main__":

def test_f1(x, y):
return (x ** 2) + (y ** 2)


# starting the problem with initial coordinates (12, 47)
prob = SearchProblem(x=12, y=47, step_size=1, function_to_optimize=test_f1)
local_min = simulated_annealing(
Expand All @@ -118,9 +120,11 @@ def test_f1(x, y):
f"and 50 > y > - 5 found via hill climbing: {local_min.score()}"
)


def test_f2(x, y):
return (3 * x ** 2) - (6 * y)


prob = SearchProblem(x=3, y=4, step_size=1, function_to_optimize=test_f1)
local_min = simulated_annealing(prob, find_max=False, visualization=True)
print(
Expand Down
Loading