예제 #1
0
def curious_fractions(numbers: Iterable[int]) -> Iterable[Fraction]:
    fractions_parts = permutations(numbers, r=2)
    filtered_fractions_parts = star_filter(
        non_trivial_fraction, star_filter(operator.lt, fractions_parts))
    for numerator, denominator in filtered_fractions_parts:
        numerator_digits = list(number_to_digits(numerator))
        denominator_digits = list(number_to_digits(denominator))
        try:
            common_digit, = set(numerator_digits) & set(denominator_digits)
        except ValueError:
            continue
        else:
            cancelled_numerator_digits = numerator_digits[:]
            cancelled_numerator_digits.remove(common_digit)

            cancelled_denominator_digits = denominator_digits[:]
            cancelled_denominator_digits.remove(common_digit)

            cancelled_numerator = digits_to_number(cancelled_numerator_digits)
            cancelled_denominator = digits_to_number(
                cancelled_denominator_digits)

            fraction = Fraction(numerator, denominator)
            cancelled_fraction = Fraction(cancelled_numerator,
                                          cancelled_denominator)
            fraction_is_curious = fraction == cancelled_fraction
            if fraction_is_curious:
                yield fraction
예제 #2
0
def square_root_convergents(stop: int) -> Iterable[bool]:
    for expansion in square_root_expansions(stop):
        numerator_digits_count = capacity(number_to_digits(
            expansion.numerator))
        denominator_digits_count = capacity(
            number_to_digits(expansion.denominator))
        yield numerator_digits_count > denominator_digits_count
예제 #3
0
def permuted_multiples(max_multiplier: int) -> Iterator[int]:
    for number in count(1):
        sorted_digits = sorted(number_to_digits(number))
        for multiplier in range(2, max_multiplier + 1):
            multiplied_number = multiplier * number
            if sorted(number_to_digits(multiplied_number)) != sorted_digits:
                break
        else:
            yield number
예제 #4
0
def prime_permutations(*,
                       start: int,
                       stop: int,
                       increment: int) -> Iterable[Tuple[int, int, int]]:
    prime_numbers_set = set(filter(partial(operator.le, start),
                                   prime_numbers(stop)))
    for number in filter(partial(operator.ge, 10_000 - increment * 2),
                         prime_numbers_set):
        sorted_digits = sorted(number_to_digits(number))
        second_number = number + increment
        third_number = second_number + increment
        second_number_digits = sorted(number_to_digits(second_number))
        third_number_digits = sorted(number_to_digits(third_number))
        if sorted_digits == second_number_digits == third_number_digits:
            if second_number in prime_numbers_set and third_number in prime_numbers_set:
                yield number, second_number, third_number
예제 #5
0
def is_pandigital(number: int) -> bool:
    digits = list(number_to_digits(number))
    digits_set = set(digits)
    if len(digits) > len(digits_set):
        return False
    max_digit = max(digits_set)
    return not (pandigits[max_digit] ^ digits_set)
예제 #6
0
def digits_sums(*, start: int = 1, stop: int, step: int = 1) -> Iterable[int]:
    if stop == 2:
        return 1,
    bases = filterfalse(ends_with_zero, range(start, stop, step))
    exponents = range(2, stop)
    for base, exponent in product(bases, exponents):
        yield sum(number_to_digits(base**exponent))
예제 #7
0
def pandigital_multiples(digits: Collection[int]) -> Iterator[int]:
    position_stop = ceil(len(digits) / 2)
    for digits in permutations(digits):
        for position in range(1, position_stop):
            base_digits = digits[:position]
            base = digits_to_number(base_digits)
            base_digits_set = set(base_digits)
            tail_start = position
            for multiplier in range(2, 10):
                tail = ''.join(map(str, digits[tail_start:]))
                if not tail:
                    continue
                step = base * multiplier
                step_digits = list(number_to_digits(step))
                step_digits_set = set(step_digits)
                step_digits_count = len(step_digits)
                if step_digits_count < len(step_digits_set):
                    break
                if step_digits_set & base_digits_set:
                    break
                if not tail.startswith(str(step)):
                    break
                tail_start += step_digits_count
            else:
                yield digits_to_number(digits)
예제 #8
0
 def circular(prime_number: int) -> bool:
     digits = tuple(number_to_digits(prime_number))
     rotated_digits = (rotate(digits, position)
                       for position in range(len(digits)))
     for rotated_prime in map(digits_to_number, rotated_digits):
         if rotated_prime not in primes_set:
             return False
     return True
예제 #9
0
def digits_factorials_chain(number: int) -> List[int]:
    chain = [number]
    while True:
        digits = number_to_digits(number)
        digits_factorials = map(factorial, digits)
        digits_factorials_sum = sum(digits_factorials)
        if digits_factorials_sum in chain:
            break
        number = digits_factorials_sum
        chain.append(number)
    return chain
예제 #10
0
def sub_string_divisible_numbers(*,
                                 digits: Iterable[int],
                                 slicers_by_divisors: Dict[int, slice]
                                 ) -> Iterable[int]:
    for digits in permutations(digits):
        number = digits_to_number(digits)
        digits = list(number_to_digits(number))
        for divisor, slicer in slicers_by_divisors.items():
            digits_slice = digits[slicer]
            sliced_number = digits_to_number(digits_slice)
            if sliced_number % divisor:
                break
        else:
            yield number
예제 #11
0
 def is_digits_powers_sum(number: int) -> bool:
     return sum(digit**exponent
                for digit in number_to_digits(number)) == number
예제 #12
0
def is_digits_factorials_sum_candidate(number: int) -> bool:
    digits = tuple(number_to_digits(number))
    zeros_count = digits.count(0)
    ones_count = digits.count(1)
    last_digit = digits[-1]
    return last_digit % 2 == (zeros_count + ones_count) % 2
예제 #13
0
def is_digits_factorials_sum(number: int) -> bool:
    digits_factorials_sum = sum(digits_factorials[digit]
                                for digit in number_to_digits(number))
    return digits_factorials_sum == number
예제 #14
0
    yield 2
    for index in count(1):
        yield 1
        yield 2 * index
        yield 1


def convergent(index: int) -> Fraction:
    coefficients = list(islice(continued_fraction(), index))
    # we are starting from the bottom to the top
    result = Fraction(coefficients.pop())
    for coefficient in reversed(coefficients):
        result = coefficient + Fraction(1, result)
    return result


assert [convergent(index) for index in range(1, 11)] == [
    Fraction(2),
    Fraction(3),
    Fraction(8, 3),
    Fraction(11, 4),
    Fraction(19, 7),
    Fraction(87, 32),
    Fraction(106, 39),
    Fraction(193, 71),
    Fraction(1264, 465),
    Fraction(1457, 536)
]
assert sum(number_to_digits(convergent(10).numerator)) == 17
assert sum(number_to_digits(convergent(100).numerator)) == 272
예제 #15
0
def number_to_sorted_digits_tuple(number: int) -> Tuple[int, ...]:
    return tuple(sorted(number_to_digits(number)))
예제 #16
0
def lychrel(number: int) -> bool:
    for _ in range(MAX_ITERATIONS_COUNT):
        number += digits_to_number(reversed(list(number_to_digits(number))))
        if is_palindrome(str(number)):
            return False
    return True