"""Project Euler problem 12 solution

The sequence of triangle numbers is generated by adding the natural numbers.
So the 7th triangle number would be 1 + 2 + 3 + 4 + 5 + 6 + 7 = 28. The first
ten terms would be:

1, 3, 6, 10, 15, 21, 28, 36, 45, 55, ...

Let us list the factors of the first seven triangle numbers:

> **1** : 1
>  **3** : 1,3
>  **6** : 1,2,3,6
>  **10** : 1,2,5,10
>  **15** : 1,3,5,15
>  **21** : 1,3,7,21
>  **28** : 1,2,4,7,14,28

We can see that 28 is the first triangle number to have over five divisors.

What is the value of the first triangle number to have over five hundred
divisors?

"""
from typing import Generator, List


def get_divisors(number: int) -> List[int]:
    """
    Get list of divisors for a given number.

    :param number: list
    :return: list[int]
    """
    divisors_list = []
    candidate_divisor = 1
    while candidate_divisor <= number:
        if number % candidate_divisor == 0:
            divisors_list.append(candidate_divisor)
        candidate_divisor += 1
    return divisors_list


def triangle_number_generator() -> Generator[int, None, None]:
    """
    Generate a sequence of triangle numbers.

    :return: Generator[int, None, None]
    """
    triangle_number = 1
    sequence_number = 1
    while True:
        yield triangle_number
        sequence_number += 1
        triangle_number += sequence_number


def smallest_triangle_number_with_n_divisors(min_number_of_divisors) -> int:
    """
    Get smallest triangle number with at least min_number_of_divisors.

    :param min_number_of_divisors:
    :return: int
    """
    triangle_number = 0
    for triangle_number in triangle_number_generator():
        number_of_divisors = len(get_divisors(triangle_number))
        if number_of_divisors >= min_number_of_divisors:
            break
    return triangle_number


"""
# Solution to problem 3
smallest_triangle_number_with_n_divisors(500) = 76576500


NB This took several hours. I'm sure there is a much more efficient algorithm.
"""
