summaryrefslogtreecommitdiffstats
path: root/Doc
diff options
context:
space:
mode:
authorRaymond Hettinger <rhettinger@users.noreply.github.com>2023-12-14 19:15:29 (GMT)
committerGitHub <noreply@github.com>2023-12-14 19:15:29 (GMT)
commit93cf7358d996e0e296046526bf9bc44755d597d1 (patch)
tree07716e9dc96c1a41d4929a0524ac92621a9e0eac /Doc
parent22511f77c2818a138a252e6ddae89725d082f8b0 (diff)
downloadcpython-93cf7358d996e0e296046526bf9bc44755d597d1.zip
cpython-93cf7358d996e0e296046526bf9bc44755d597d1.tar.gz
cpython-93cf7358d996e0e296046526bf9bc44755d597d1.tar.bz2
Add recipe for totient() to demonstrate unique_justseen() and factor(). (gh-113131)
Diffstat (limited to 'Doc')
-rw-r--r--Doc/library/itertools.rst27
1 files changed, 27 insertions, 0 deletions
diff --git a/Doc/library/itertools.rst b/Doc/library/itertools.rst
index 56c66f6..83e2a9f 100644
--- a/Doc/library/itertools.rst
+++ b/Doc/library/itertools.rst
@@ -1128,6 +1128,14 @@ The following recipes have a more mathematical flavor:
if n > 1:
yield n
+ def totient(n):
+ "Count of natural numbers up to n that are coprime to n."
+ # https://mathworld.wolfram.com/TotientFunction.html
+ # totient(12) --> 4 because len([1, 5, 7, 11]) == 4
+ for p in unique_justseen(factor(n)):
+ n = n // p * (p - 1)
+ return n
+
def nth_combination(iterable, r, index):
"Equivalent to list(combinations(iterable, r))[index]"
pool = tuple(iterable)
@@ -1429,6 +1437,25 @@ The following recipes have a more mathematical flavor:
>>> all(list(factor(n)) == sorted(factor(n)) for n in range(2_000))
True
+ >>> totient(0) # https://www.wolframalpha.com/input?i=totient+0
+ 0
+ >>> first_totients = [1, 1, 2, 2, 4, 2, 6, 4, 6, 4, 10, 4, 12, 6, 8, 8, 16, 6,
+ ... 18, 8, 12, 10, 22, 8, 20, 12, 18, 12, 28, 8, 30, 16, 20, 16, 24, 12, 36, 18,
+ ... 24, 16, 40, 12, 42, 20, 24, 22, 46, 16, 42, 20, 32, 24, 52, 18, 40, 24, 36,
+ ... 28, 58, 16, 60, 30, 36, 32, 48, 20, 66, 32, 44] # https://oeis.org/A000010
+ ...
+ >>> list(map(totient, range(1, 70))) == first_totients
+ True
+ >>> reference_totient = lambda n: sum(math.gcd(t, n) == 1 for t in range(1, n+1))
+ >>> all(totient(n) == reference_totient(n) for n in range(1000))
+ True
+ >>> totient(128_884_753_939) == 128_884_753_938 # large prime
+ True
+ >>> totient(999953 * 999983) == 999952 * 999982 # large semiprime
+ True
+ >>> totient(6 ** 20) == 1 * 2**19 * 2 * 3**19 # repeated primes
+ True
+
>>> list(flatten([('a', 'b'), (), ('c', 'd', 'e'), ('f',), ('g', 'h', 'i')]))
['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i']