from typing import List, Optional


# Task 4.1: Write a code with recursion for calculating summ of all array entries
def calculate_recursion_summ(array_of_ints: List[int]) -> int:
    if len(array_of_ints) == 0:
        return 0
    return array_of_ints[0] + calculate_recursion_summ(array_of_ints[1:])


print(calculate_recursion_summ([5, 5, 5, 5, 5]))


# Task 4.2: Write a code with recursion for calculating the amount of elements in List
def calculate_list_length(array_of_ints: List[int]) -> int:
    if len(array_of_ints) == 1:
        return 1
    return 1 + calculate_list_length(array_of_ints[1:])


print(calculate_list_length([1, 2, 3, 4, 5, 6, 7, 8]))


# Task 4.3: Write a code to find a highest list value with recursion
def find_highest_value_in_lits(array_of_ints: List[int]) -> int:
    if len(array_of_ints) == 1:
        return array_of_ints[0]
    elif len(array_of_ints) == 2:
        return (
            array_of_ints[0]
            if array_of_ints[0] > array_of_ints[1]
            else array_of_ints[1]
        )
    else:
        sub_max = find_highest_value_in_lits(array_of_ints[1:])
        return array_of_ints[0] if array_of_ints[0] > sub_max else sub_max


print(find_highest_value_in_lits([1, 2, 3, 4, 5, 4, 3, 2, 1, 1231]))


# Task 4.4: Make binary search using recursion
def binary_search(array_of_ints: List[int], target_value: int) -> Optional[int]:
    array_len = len(array_of_ints)
    if array_len == 1:
        return array_of_ints[0] if array_of_ints[0] == target_value else None
    max_left = array_of_ints[array_len // 2]
    return (
        binary_search(array_of_ints[: array_len // 2], target_value)
        if target_value < max_left
        else binary_search(array_of_ints[array_len // 2:], target_value)
    )


print(binary_search([1, 2, 3, 4, 5], 4))
