diff --git a/README.rst b/README.rst index e72593e0..c240fa5d 100644 --- a/README.rst +++ b/README.rst @@ -107,7 +107,7 @@ Olivia's Project Euler Solutions | | | | |Lu-Cov| |br| | | | | | |LuaCheck| | +------------+----------------------------+--------+-------------------+ - | Python | CPython 3.6+ |br| | 84 | |Python| |br| | + | Python | CPython 3.6+ |br| | 85 | |Python| |br| | | | Pypy 3.6+ |br| | | |Py-Cov| |br| | | | GraalPy 23.1+ |br| | | |CodeQL| |br| | | | Browser [#]_ | | |PythonLint| | diff --git a/_data/answers.tsv b/_data/answers.tsv index 5316e7d3..6dcb7fe2 100644 --- a/_data/answers.tsv +++ b/_data/answers.tsv @@ -64,6 +64,7 @@ ID type size answer 69 int 32 510510 70 int 64 8319823 71 int 32 428570 +72 int 64 303963552391 73 int 32 7295372 74 int 16 402 76 int 32 190569291 diff --git a/docs/index.rst b/docs/index.rst index 23f3c449..fcec2f99 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -208,6 +208,8 @@ Problems Solved +-----------+-----------+------------+------------+------------+------------+------------+------------+------------+------------+ |:prob:`071`| | | | | | | |:py-d:`0071`| | +-----------+-----------+------------+------------+------------+------------+------------+------------+------------+------------+ + |:prob:`072`| | | | | | | |:py-d:`0072`| | + +-----------+-----------+------------+------------+------------+------------+------------+------------+------------+------------+ |:prob:`073`| | | | | | | |:py-d:`0073`| | +-----------+-----------+------------+------------+------------+------------+------------+------------+------------+------------+ |:prob:`074`| | | | | | | |:py-d:`0074`| | diff --git a/docs/src/python/lib/primes.rst b/docs/src/python/lib/primes.rst index 6ec5626e..30220630 100644 --- a/docs/src/python/lib/primes.rst +++ b/docs/src/python/lib/primes.rst @@ -6,6 +6,8 @@ View source code :source:`python/src/lib/primes.py` Includes -------- +- :external:py:class:`fractions.Fraction` +- :external:py:func:`functools.reduce` - :external:py:func:`itertools.count` - :external:py:func:`itertools.filterfalse` - :external:py:func:`itertools.takewhile` diff --git a/docs/src/python/p0070.rst b/docs/src/python/p0070.rst index a0ef571c..951b1395 100644 --- a/docs/src/python/p0070.rst +++ b/docs/src/python/p0070.rst @@ -6,6 +6,7 @@ View source code :source:`python/src/p0070.py` Includes -------- +- :py:func:`~python.src.lib.primes.fast_totient` - :external:py:func:`itertools.chain` - :external:py:func:`functools.reduce` diff --git a/docs/src/python/p0072.rst b/docs/src/python/p0072.rst new file mode 100644 index 00000000..7b8c0bf1 --- /dev/null +++ b/docs/src/python/p0072.rst @@ -0,0 +1,24 @@ +Python Implementation of Problem 72 +=================================== + +View source code :source:`python/src/p0072.py` + +Includes +-------- + +- :py:func:`~python.src.lib.primes.totient` +- :external:py:func:`itertools.chain` +- :external:py:func:`functools.reduce` + +Problem Solution +---------------- + +.. automodule:: python.src.p0072 + :members: + :undoc-members: + +.. literalinclude:: ../../../python/src/p0072.py + :language: python + :linenos: + +.. tags:: fraction, gcd, stern-brocot-tree, coprime-numbers, totient-function diff --git a/python/README.rst b/python/README.rst index e9c0a3bd..dc9757a9 100644 --- a/python/README.rst +++ b/python/README.rst @@ -191,6 +191,7 @@ Problems Solved - ☒ `69 <./src/p0069.py>`__ - ☒ `70 <./src/p0070.py>`__ - ☒ `71 <./src/p0071.py>`__ +- ☒ `72 <./src/p0072.py>`__ - ☒ `73 <./src/p0073.py>`__ - ☒ `74 <./src/p0074.py>`__ - ☒ `76 <./src/p0076.py>`__ diff --git a/python/src/lib/primes.py b/python/src/lib/primes.py index ce3d3660..ce9cf3e1 100644 --- a/python/src/lib/primes.py +++ b/python/src/lib/primes.py @@ -1,3 +1,5 @@ +from fractions import Fraction +from functools import reduce from itertools import count, filterfalse, takewhile from math import ceil, sqrt from pathlib import Path @@ -138,3 +140,13 @@ def primes_and_negatives(*args: int) -> Iterator[int]: for p in primes(*args): yield p yield -p + + +def fast_totient(n: int) -> int: + """A shortcut method to calculate Euler's totient function which assumes n has *distinct* prime factors.""" + return reduce(lambda x, y: x * (y - 1), prime_factors(n), 1) + + +def totient(n: int) -> int: + """Calculates Euler's totient function in the general case.""" + return int(n * reduce(lambda x, y: x * (1 - Fraction(1, y)), set(prime_factors(n)), 1)) diff --git a/python/src/p0070.py b/python/src/p0070.py index f5d72f3e..edecc023 100644 --- a/python/src/p0070.py +++ b/python/src/p0070.py @@ -15,14 +15,9 @@ Find the value of $n$, $1 \\lt n \\lt 10^7$, for which $\\phi(n)$ is a permutation of $n$ and the ratio $n/\\phi(n)$ produces a minimum. """ -from functools import reduce from itertools import chain -from .lib.primes import prime_factors - - -def totient(n: int) -> int: - return reduce(lambda x, y: x * (y - 1), prime_factors(n), 1) +from .lib.primes import fast_totient def main() -> int: @@ -42,7 +37,7 @@ def main() -> int: range(6 + 17, stop, 30), # 6k - 1, x ≡ 4 (mod 5) range(6 + 19, stop, 30) # 6k + 1, x ≡ 4 (mod 5) )): - t = totient(x) + t = fast_totient(x) strx = str(x) strt = str(t) if not all(strx.count(d) == strt.count(d) for d in set(strx)): diff --git a/python/src/p0072.py b/python/src/p0072.py new file mode 100644 index 00000000..3093a715 --- /dev/null +++ b/python/src/p0072.py @@ -0,0 +1,21 @@ +""" +Project Euler Problem 72 + +Problem: + +Consider the fraction, n / d, where n and d are positive integers. If n < d and HCF(n,d)=1, it is +called a reduced proper fraction. + +If we list the set of reduced proper fractions for d <= 8 in ascending order of size, we get: + +(1 / 8), (1 / 7), (1 / 6), (1 / 5), (1 / 4), (2 / 7), (1 / 3), (3 / 8), (2 / 5), (3 / 7), (1 / 2), +(4 / 7), (3 / 5), (5 / 8), (2 / 3), (5 / 7), (3 / 4), (4 / 5), (5 / 6), (6 / 7), (7 / 8) + +It can be seen that there are 21 elements in this set. +How many elements would be contained in the set of reduced proper fractions for d <= 1000000? +""" +from .lib.primes import totient + + +def main() -> int: + return sum(totient(n) for n in range(2, 1000001)) diff --git a/python/test_euler.py b/python/test_euler.py index c7e1dda9..e5b07f3a 100644 --- a/python/test_euler.py +++ b/python/test_euler.py @@ -23,8 +23,7 @@ *range(55, 61), 63, 67, - *range(69, 72), - *range(73, 75), + *range(69, 75), *range(76, 78), 79, 81,