Skip to content

Commit

Permalink
Merge pull request #20 from FranzDiebold/feat/add-solution-for-proble…
Browse files Browse the repository at this point in the history
…m-57

Add solution for problem 57.
  • Loading branch information
FranzDiebold authored Jun 29, 2020
2 parents 1d9bf71 + 6bddc22 commit 0c9e55b
Show file tree
Hide file tree
Showing 3 changed files with 127 additions and 1 deletion.
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: 56 problems](https://img.shields.io/badge/solved-56_problems-f93.svg)](./src)
[![solved: 57 problems](https://img.shields.io/badge/solved-57_problems-f93.svg)](./src)
![Python: 3.8](https://img.shields.io/badge/Python-3.8-3776ab.svg)
[![Lint and Test](https://github.com/FranzDiebold/project-euler-solutions/workflows/Lint%20and%20Test/badge.svg)](https://github.com/FranzDiebold/project-euler-solutions/actions?query=workflow%3A%22Lint+and+Test%22)
[![license: MIT](https://img.shields.io/badge/license-MIT-brightgreen.svg)](./LICENSE.md)
Expand Down
69 changes: 69 additions & 0 deletions src/p057_square_root_convergents.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
"""
Problem 57: Square root convergents
https://projecteuler.net/problem=57
It is possible to show that the square root of two can be expressed
as an infinite continued fraction.
sqrt(2) = 1 + (1 / (2 + (1 / (2 + (1 / (2 + ...))))))
By expanding this for the first four iterations, we get:
1 + (1 / 2) = 3 / 2 = 1.5
1 + (1 / (2 + (1 / 2))) = 7 / 5 = 1.4
1 + (1 / (2 + (1 / (2 + (1 / 2))))) = 17 / 12 = 1.41666...
1 + (1 / (2 + (1 / (2 + (1 / (2 + (1 / 2))))))) = 41 / 29 = 1.41379...
The next three expansions are 99/70, 239/169, and 577/408,
but the eighth expansion, 1393/985, is the first example where the number of digits
in the numerator exceeds the number of digits in the denominator.
In the first one-thousand expansions,
how many fractions contain a numerator with more digits than the denominator?
"""

from typing import Iterable, Tuple

from src.common.calculations import calculate_large_product, calculate_large_sum


def get_square_root_expansions() -> Iterable[Tuple[str, str]]:
"""Get square root expansions for `sqrt(2)` as tuples `(numerator, denominator)`."""
previous_numerator = '1'
previous_denominator = '1'
numerator = '3'
denominator = '2'
while True:
yield numerator, denominator
numerator, previous_numerator = calculate_large_sum(
[calculate_large_product(numerator, '2'), previous_numerator]
), numerator
denominator, previous_denominator = calculate_large_sum(
[calculate_large_product(denominator, '2'), previous_denominator]
), denominator


def count_larger_numerator_expansions(threshold: int) -> int:
"""
Count the number of expansion fractions, where the numerator contains more digits
than the denominator in the first `threshold` square root expansions.
"""
square_root_expansions_iter = get_square_root_expansions()
count = 0
for _ in range(threshold):
numerator, denominator = next(square_root_expansions_iter)
if len(numerator) > len(denominator):
count += 1
return count


def main() -> None:
"""Main function."""
threshold = 1000
count = count_larger_numerator_expansions(threshold)
print(f'In the first {threshold:,} expansions, {count:,} fractions contain ' \
f'a numerator with more digits than the denominator.')


if __name__ == '__main__':
main()
57 changes: 57 additions & 0 deletions test/test_p057_square_root_convergents.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
"""
Problem 57: Square root convergents
https://projecteuler.net/problem=57
It is possible to show that the square root of two can be expressed
as an infinite continued fraction.
sqrt(2) = 1 + (1 / (2 + (1 / (2 + (1 / (2 + ...))))))
By expanding this for the first four iterations, we get:
1 + (1 / 2) = 3 / 2 = 1.5
1 + (1 / (2 + (1 / 2))) = 7 / 5 = 1.4
1 + (1 / (2 + (1 / (2 + (1 / 2))))) = 17 / 12 = 1.41666...
1 + (1 / (2 + (1 / (2 + (1 / (2 + (1 / 2))))))) = 41 / 29 = 1.41379...
The next three expansions are 99/70, 239/169, and 577/408,
but the eighth expansion, 1393/985, is the first example where the number of digits
in the numerator exceeds the number of digits in the denominator.
In the first one-thousand expansions,
how many fractions contain a numerator with more digits than the denominator?
"""


def test_get_square_root_expansions():
# arrange
from src.p057_square_root_convergents import get_square_root_expansions

# act
actual_result_iter = get_square_root_expansions()

# assert
expected_result = [
('3', '2'),
('7', '5'),
('17', '12'),
('41', '29'),
('99', '70'),
('239', '169'),
('577', '408'),
('1393', '985'),
]
for expected_expansion in expected_result:
assert next(actual_result_iter) == expected_expansion


def test_count_larger_numerator_expansions():
# arrange
from src.p057_square_root_convergents import count_larger_numerator_expansions

# act
actual_result = count_larger_numerator_expansions(8)

# assert
expected_result = 1
assert actual_result == expected_result

0 comments on commit 0c9e55b

Please sign in to comment.