Skip to content

Commit

Permalink
Add solution for problem 23.
Browse files Browse the repository at this point in the history
  • Loading branch information
FranzDiebold committed Oct 3, 2019
1 parent a598302 commit 0d103dc
Show file tree
Hide file tree
Showing 4 changed files with 117 additions and 20 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# [Project Euler](https://projecteuler.net) Solutions

[![solved: 22 problems](https://img.shields.io/badge/solved-22_problems-f93.svg)](./src)
[![solved: 23 problems](https://img.shields.io/badge/solved-23_problems-f93.svg)](./src)
![Python: 3.7](https://img.shields.io/badge/Python-3.7-3776ab.svg)
[![Build Status](https://travis-ci.com/FranzDiebold/project-euler-solutions.svg?branch=master)](https://travis-ci.com/FranzDiebold/project-euler-solutions)
[![license: MIT](https://img.shields.io/badge/license-MIT-brightgreen.svg)](./LICENSE.md)
Expand Down
54 changes: 54 additions & 0 deletions src/common/divisors.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
"""
Proper divisor utility functions.
"""

from typing import Iterable
import math


def divisors(number: int) -> Iterable[int]:
"""Get proper divisors for given number `number`.
Example:
220 -> [1, 2, 4, 5, 10, 11, 20, 22, 44, 55, 110]
The numbers may be in a random order.
"""
yield 1
for i in range(2, math.floor(math.sqrt(number)) + 1):
if number % i == 0:
yield i
if i**2 < number:
yield number // i


def get_sum_of_divisors(number: int) -> int:
"""Get sum of proper divisors of number `number`."""
return sum(divisors(number))


def is_perferct_number(number: int) -> bool:
"""Check if a given number `number` is a perfect number.
A perfect number is a number for which the sum of its proper divisors
is exactly equal to the number.
For example, the sum of the proper divisors of 28 would be
`1 + 2 + 4 + 7 + 14 = 28`,
which means that 28 is a perfect number.
"""
return get_sum_of_divisors(number) == number


def is_deficient_number(number: int) -> bool:
"""Check if a given number `number` is a deficient number.
A number n is called deficient if the sum of its proper divisors is less than n.
"""
return get_sum_of_divisors(number) < number


def is_abundant_number(number: int) -> bool:
"""Check if a given number `number` is a abundant number.
A number n is called abundant if the sum of its proper divisors exceeds n.
"""
return get_sum_of_divisors(number) > number
20 changes: 1 addition & 19 deletions src/p021_amicable_numbers.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,26 +15,8 @@
"""

from typing import Iterable, Tuple
import math


def divisors(number: int) -> Iterable[int]:
"""Get proper divisors for given number `number`.
Example:
220 -> [1, 2, 4, 5, 10, 11, 20, 22, 44, 55, 110]
The numbers may be in a random order.
"""
yield 1
for i in range(2, math.floor(math.sqrt(number))):
if number % i == 0:
yield i
yield number // i


def get_sum_of_divisors(number: int) -> int:
"""Get sum of proper divisors of number `number`."""
return sum(divisors(number))
from src.common.divisors import get_sum_of_divisors


def get_amicable_pairs(threshold: int) -> Iterable[Tuple[int, int]]:
Expand Down
61 changes: 61 additions & 0 deletions src/p023_non_abundant_sums.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
"""
Problem 23: Non-abundant sums
https://projecteuler.net/problem=23
A perfect number is a number for which the sum of its proper divisors
is exactly equal to the number.
For example, the sum of the proper divisors of 28 would be
1 + 2 + 4 + 7 + 14 = 28,
which means that 28 is a perfect number.
A number n is called deficient if the sum of its proper divisors is less than n and
it is called abundant if this sum exceeds n.
As 12 is the smallest abundant number, 1 + 2 + 3 + 4 + 6 = 16,
the smallest number that can be written as the sum of two abundant numbers is 24.
By mathematical analysis, it can be shown that all integers greater than 28123
can be written as the sum of two abundant numbers.
However, this upper limit cannot be reduced any further by analysis
even though it is known that the greatest number that cannot be expressed
as the sum of two abundant numbers is less than this limit.
Find the sum of all the positive integers
which cannot be written as the sum of two abundant numbers.
"""

from typing import Set

from src.common.divisors import is_abundant_number


def get_abundant_numbers(threshold: int) -> Set[int]:
"""Get set of abundant numbers below given threshold `threshold'."""
abundant_numbers = set()
for i in range(1, threshold + 1):
if is_abundant_number(i):
abundant_numbers.add(i)
return abundant_numbers


def is_sum_of_numbers(number: int, numbers: Set[int]) -> bool:
"""Check if a given number `number` is the sum of any two numbers from `numbers`."""
for i in range(1, number):
if i in numbers and (number - i) in numbers:
return True
return False


def main() -> None:
"""Main function."""
threshold = 28123
total_sum = 0
abundant_numbers = get_abundant_numbers(threshold)
for i in range(1, threshold + 1):
if not is_sum_of_numbers(i, abundant_numbers):
total_sum += i
print(f'The sum of all the positive integers which cannot be written as the sum ' \
f'of two abundant numbers is {total_sum:,}.')


if __name__ == '__main__':
main()

0 comments on commit 0d103dc

Please sign in to comment.