Skip to content

Commit 58135f4

Browse files
Add A000010 Euler's totient sequence (#246)
1 parent 54af98e commit 58135f4

File tree

3 files changed

+150
-0
lines changed

3 files changed

+150
-0
lines changed
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
using System.Linq;
2+
using System.Numerics;
3+
using Algorithms.Sequences;
4+
using FluentAssertions;
5+
using NUnit.Framework;
6+
7+
namespace Algorithms.Tests.Sequences
8+
{
9+
public class EulerTotientSequenceTests
10+
{
11+
[Test]
12+
public void FirstElementsCorrect()
13+
{
14+
// Let's be thorough. 500 phi values!
15+
// Initial test of 69 number from table at https://oeis.org/A000010/list and passed test.
16+
// Extended out to 500 values from https://primefan.tripod.com/Phi500.html and passed initial 69
17+
// along with remaining values.
18+
var check = new BigInteger[]
19+
{
20+
1, 1, 2, 2, 4, 2, 6, 4, 6, 4, 10, 4, 12, 6, 8, 8, 16, 6, 18, 8,
21+
12, 10, 22, 8, 20, 12, 18, 12, 28, 8, 30, 16, 20, 16, 24, 12, 36, 18, 24, 16,
22+
40, 12, 42, 20, 24, 22, 46, 16, 42, 20, 32, 24, 52, 18, 40, 24, 36, 28, 58, 16,
23+
60, 30, 36, 32, 48, 20, 66, 32, 44, 24, 70, 24, 72, 36, 40, 36, 60, 24, 78, 32,
24+
54, 40, 82, 24, 64, 42, 56, 40, 88, 24, 72, 44, 60, 46, 72, 32, 96, 42, 60, 40,
25+
100, 32, 102, 48, 48, 52, 106, 36, 108, 40, 72, 48, 112, 36, 88, 56, 72, 58, 96, 32,
26+
110, 60, 80, 60, 100, 36, 126, 64, 84, 48, 130, 40, 108, 66, 72, 64, 136, 44, 138, 48,
27+
92, 70, 120, 48, 112, 72, 84, 72, 148, 40, 150, 72, 96, 60, 120, 48, 156, 78, 104, 64,
28+
132, 54, 162, 80, 80, 82, 166, 48, 156, 64, 108, 84, 172, 56, 120, 80, 116, 88, 178, 48,
29+
180, 72, 120, 88, 144, 60, 160, 92, 108, 72, 190, 64, 192, 96, 96, 84, 196, 60, 198, 80,
30+
132, 100, 168, 64, 160, 102, 132, 96, 180, 48, 210, 104, 140, 106, 168, 72, 180, 108, 144, 80,
31+
192, 72, 222, 96, 120, 112, 226, 72, 228, 88, 120, 112, 232, 72, 184, 116, 156, 96, 238, 64,
32+
240, 110, 162, 120, 168, 80, 216, 120, 164, 100, 250, 72, 220, 126, 128, 128, 256, 84, 216, 96,
33+
168, 130, 262, 80, 208, 108, 176, 132, 268, 72, 270, 128, 144, 136, 200, 88, 276, 138, 180, 96,
34+
280, 92, 282, 140, 144, 120, 240, 96, 272, 112, 192, 144, 292, 84, 232, 144, 180, 148, 264, 80,
35+
252, 150, 200, 144, 240, 96, 306, 120, 204, 120, 310, 96, 312, 156, 144, 156, 316, 104, 280, 128,
36+
212, 132, 288, 108, 240, 162, 216, 160, 276, 80, 330, 164, 216, 166, 264, 96, 336, 156, 224, 128,
37+
300, 108, 294, 168, 176, 172, 346, 112, 348, 120, 216, 160, 352, 116, 280, 176, 192, 178, 358, 96,
38+
342, 180, 220, 144, 288, 120, 366, 176, 240, 144, 312, 120, 372, 160, 200, 184, 336, 108, 378, 144,
39+
252, 190, 382, 128, 240, 192, 252, 192, 388, 96, 352, 168, 260, 196, 312, 120, 396, 198, 216, 160,
40+
400, 132, 360, 200, 216, 168, 360, 128, 408, 160, 272, 204, 348, 132, 328, 192, 276, 180, 418, 96,
41+
420, 210, 276, 208, 320, 140, 360, 212, 240, 168, 430, 144, 432, 180, 224, 216, 396, 144, 438, 160,
42+
252, 192, 442, 144, 352, 222, 296, 192, 448, 120, 400, 224, 300, 226, 288, 144, 456, 228, 288, 176,
43+
460, 120, 462, 224, 240, 232, 466, 144, 396, 184, 312, 232, 420, 156, 360, 192, 312, 238, 478, 128,
44+
432, 240, 264, 220, 384, 162, 486, 240, 324, 168, 490, 160, 448, 216, 240, 240, 420, 164, 498, 200,
45+
};
46+
47+
var sequence = new EulerTotientSequence().Sequence.Take(check.Length);
48+
sequence.SequenceEqual(check).Should().BeTrue();
49+
}
50+
}
51+
}
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
using System.Collections.Generic;
2+
using System.Linq;
3+
using System.Numerics;
4+
5+
namespace Algorithms.Sequences
6+
{
7+
/// <summary>
8+
/// <para>
9+
/// Sequence of Euler totient function phi(n).
10+
/// </para>
11+
/// <para>
12+
/// Wikipedia: https://en.wikipedia.org/wiki/Euler%27s_totient_function.
13+
/// </para>
14+
/// <para>
15+
/// OEIS: https://oeis.org/A000010.
16+
/// </para>
17+
/// </summary>
18+
public class EulerTotientSequence : ISequence
19+
{
20+
/// <summary>
21+
/// <para>
22+
/// Gets sequence of Euler totient function phi(n).
23+
/// </para>
24+
/// <para>
25+
/// 'n' is copied from value of the loop of i that's being enumerated over.
26+
/// 1) Initialize result as n
27+
/// 2) Consider every number 'factor' (where 'factor' is a prime divisor of n).
28+
/// If factor divides n, then do following
29+
/// a) Subtract all multiples of factor from 1 to n [all multiples of factor
30+
/// will have gcd more than 1 (at least factor) with n]
31+
/// b) Update n by repeatedly dividing it by factor.
32+
/// 3) If the reduced n is more than 1, then remove all multiples
33+
/// of n from result.
34+
/// </para>
35+
/// <para>
36+
/// Base code was from https://www.geeksforgeeks.org/eulers-totient-function/.
37+
/// </para>
38+
/// <para>
39+
/// Implementation avoiding floating point operations was used for base
40+
/// and replacement of loop going from 1 to sqrt(n) was replaced with
41+
/// List of prime factors.
42+
/// </para>
43+
/// </summary>
44+
public IEnumerable<BigInteger> Sequence
45+
{
46+
get
47+
{
48+
yield return BigInteger.One;
49+
50+
for (BigInteger i = 2; ; i++)
51+
{
52+
var n = i;
53+
var result = n;
54+
55+
var factors = PrimeFactors(i);
56+
foreach (var factor in factors)
57+
{
58+
while (n % factor == 0)
59+
{
60+
n /= factor;
61+
}
62+
63+
result -= result / factor;
64+
}
65+
66+
if (n > 1)
67+
{
68+
result -= result / n;
69+
}
70+
71+
yield return result;
72+
}
73+
}
74+
}
75+
76+
/// <summary>
77+
/// <para>
78+
/// Uses the prime sequence to find all prime factors of the
79+
/// number we're looking at.
80+
/// </para>
81+
/// <para>
82+
/// The prime sequence is examined until its value squared is
83+
/// less than or equal to target, and checked to make sure it
84+
/// evenly divides the target. If it evenly divides, it's added
85+
/// to the result which is returned as a List.
86+
/// </para>
87+
/// </summary>
88+
/// <param name="target">Number that is being factored.</param>
89+
/// <returns>List of prime factors of target.</returns>
90+
private static IEnumerable<BigInteger> PrimeFactors(BigInteger target)
91+
{
92+
return new PrimesSequence()
93+
.Sequence.TakeWhile(prime => prime * prime <= target)
94+
.Where(prime => target % prime == 0)
95+
.ToList();
96+
}
97+
}
98+
}

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ This repository contains algorithms and data structures implemented in C# for ed
8585
* [A000004 Zero](./Algorithms/Sequences/ZeroSequence.cs)
8686
* [A000005 Count of Divisors](./Algorithms/Sequences/DivisorsCountSequence.cs)
8787
* [A000008 Make Change](./Algorithms/Sequences/MakeChangeSequence.cs)
88+
* [A000010 Euler's Totient](./Algorithms/Sequences/EulerTotientSequence.cs)
8889
* [A000027 Natural](./Algorithms/Sequences/NaturalSequence.cs)
8990
* [A000040 Primes](./Algorithms/Sequences/PrimesSequence.cs)
9091
* [A000045 Fibonacci](./Algorithms/Sequences/FibonacciSequence.cs)

0 commit comments

Comments
 (0)