Skip to content

Commit 14bb73c

Browse files
Add A000120 (#340)
1 parent 4a0eca2 commit 14bb73c

File tree

3 files changed

+198
-0
lines changed

3 files changed

+198
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
using System.Collections.Generic;
2+
using System.Linq;
3+
using System.Numerics;
4+
using Algorithms.Sequences;
5+
using FluentAssertions;
6+
using NUnit.Framework;
7+
8+
namespace Algorithms.Tests.Sequences;
9+
10+
[TestFixture]
11+
public class OnesCountingSequenceTest
12+
{
13+
/// <summary>
14+
/// <para>
15+
/// Values taken from http://oeis.org/A000120/b000120.txt.
16+
/// </para>
17+
/// <para>
18+
/// While the file contains 10,000 values, this only tests 1000.
19+
/// </para>
20+
/// </summary>
21+
private readonly BigInteger[] oeisValues = {
22+
0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, 3, 4, 2,
23+
3, 3, 4, 3, 4, 4, 5, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3,
24+
3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3,
25+
4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4,
26+
3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5,
27+
6, 6, 7, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4,
28+
4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5,
29+
6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3, 4, 4, 5,
30+
3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3,
31+
4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6,
32+
6, 7, 6, 7, 7, 8, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3,
33+
4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5,
34+
4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3,
35+
4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6,
36+
6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6,
37+
7, 5, 6, 6, 7, 6, 7, 7, 8, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
38+
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4,
39+
5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 3, 4,
40+
4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6,
41+
7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7,
42+
6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3,
43+
4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4,
44+
4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6,
45+
7, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6,
46+
4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4,
47+
5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4,
48+
4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4,
49+
5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7,
50+
6, 7, 7, 8, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5,
51+
6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7,
52+
7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 2, 3, 3, 4, 3, 4, 4,
53+
5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
54+
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5,
55+
6, 6, 7, 6, 7, 7, 8, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5,
56+
5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6,
57+
7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 3, 4, 4, 5,
58+
4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6,
59+
7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7,
60+
7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7,
61+
8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9, 5, 6, 6, 7, 6, 7, 7, 8,
62+
};
63+
64+
/// <summary>
65+
/// <para>
66+
/// Performs number of ones in the binary representation of a BigInteger.
67+
/// </para>
68+
/// <para>
69+
/// This is used as a check to compare the provided values from OEIS.
70+
/// </para>
71+
/// </summary>
72+
/// <param name="i">BigInteger value to count 1s in</param>
73+
/// <returns>Number of 1s in binary representation of number.</returns>
74+
private int CountOnes(BigInteger i)
75+
{
76+
var temp = i;
77+
BigInteger remainder = 0;
78+
var result = 0;
79+
80+
while (temp != BigInteger.Zero) {
81+
temp = BigInteger.DivRem(temp, 2, out remainder);
82+
result += remainder.IsOne ? 1 : 0;
83+
}
84+
85+
return result;
86+
}
87+
88+
89+
[Test]
90+
public void Count1000()
91+
{
92+
// Compare generated sequence against provided data
93+
var sequence = new OnesCountingSequence().Sequence.Take(oeisValues.Length);
94+
sequence.SequenceEqual(oeisValues).Should().BeTrue();
95+
}
96+
97+
[Test]
98+
public void CompareAgainstCalculated()
99+
{
100+
// Calculate 1s in binary value the old fashioned way.
101+
var calculated = new List<BigInteger>();
102+
for (var i = 0; i < oeisValues.Length; i++) {
103+
calculated.Add(CountOnes(new BigInteger(i)));
104+
}
105+
106+
calculated.SequenceEqual(oeisValues).Should().BeTrue();
107+
}
108+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
using System.Collections.Generic;
2+
using System.Numerics;
3+
4+
namespace Algorithms.Sequences;
5+
6+
/// <summary>
7+
/// <para>
8+
/// 1's-counting sequence: number of 1's in binary expression of n.
9+
/// </para>
10+
/// <para>
11+
/// OEIS: https://oeis.org/A000120.
12+
/// </para>
13+
/// </summary>
14+
public class OnesCountingSequence : ISequence
15+
{
16+
/// <summary>
17+
/// <para>
18+
/// Gets the generated sequence of the 1's contained in the binary representation of n.
19+
/// </para>
20+
/// <para>
21+
/// The sequence is generated as follows.
22+
/// 1. The initial 0 value is provided.
23+
/// 2. A recursively generated sequence is iterated, starting with a length of 1 (i.e., 2^0),
24+
/// followed by increasing 2^x length values.
25+
/// 3. Each sequence starts with the value 1, and a targeted value of depths that it will recurse
26+
/// for the specific iteration.
27+
/// 4. If the call depth to the recursive function is met, it returns the value argument received.
28+
/// 5. If the call depth has not been met, it recurses to create 2 sequences, one starting with the
29+
/// value argument, and the following with the value argument + 1.
30+
/// 6. Using ':' as a visual separator for each sequence, this results in the following sequences
31+
/// that are returned sequentially after the initial 0.
32+
/// 1 : 1, 2 : 1, 2, 2, 3 : 1, 2, 2, 3, 2, 3, 3, 4.
33+
/// </para>
34+
/// <remarks>
35+
/// <para>
36+
/// This one comes from thinking over information contained within the COMMENTS section of the OEIS page.
37+
/// </para>
38+
/// <para>
39+
/// Using the comments provided by Benoit Cloitre, Robert G. Wilson v, and Daniel Forgues, the above
40+
/// algorithm was coded.
41+
/// </para>
42+
/// </remarks>
43+
/// </summary>
44+
public IEnumerable<BigInteger> Sequence
45+
{
46+
get
47+
{
48+
yield return 0;
49+
var depth = 0;
50+
while (true)
51+
{
52+
foreach (var count in GenerateFractalCount(BigInteger.One, depth))
53+
{
54+
yield return count;
55+
}
56+
57+
depth++;
58+
}
59+
}
60+
}
61+
62+
/// <summary>
63+
/// <para>
64+
/// Recursive function to generate sequences.
65+
/// </para>
66+
/// </summary>
67+
/// <param name="i">The value that will start off the current IEnumerable sequence.</param>
68+
/// <param name="depth">The remaining depth of recursion. Value of 0 is the stop condition.</param>
69+
/// <returns>An IEnumerable sequence of BigInteger values that can be iterated over.</returns>
70+
private static IEnumerable<BigInteger> GenerateFractalCount(BigInteger i, int depth)
71+
{
72+
// Terminal condition
73+
if (depth == 0)
74+
{
75+
yield return i;
76+
yield break;
77+
}
78+
79+
foreach (var firstHalf in GenerateFractalCount(i, depth - 1))
80+
{
81+
yield return firstHalf;
82+
}
83+
84+
foreach (var secondHalf in GenerateFractalCount(i + 1, depth - 1))
85+
{
86+
yield return secondHalf;
87+
}
88+
}
89+
}

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ find more than one implementation for the same objective but using different alg
131131
* [A000045 Fibonacci](./Algorithms/Sequences/FibonacciSequence.cs)
132132
* [A000079 Powers of 2](./Algorithms/Sequences/PowersOf2Sequence.cs)
133133
* [A000108 Catalan](./Algorithms/Sequences/CatalanSequence.cs)
134+
* [A000120 1's Counting](./Algorithms/Sequences/OnesCountingSequence.cs)
134135
* [A000142 Factorial](./Algorithms/Sequences/FactorialSequence.cs)
135136
* [A000215 Fermat Numbers](./Algorithms/Sequences/FermatNumbersSequence.cs)
136137
* [A000290 Squares](./Algorithms/Sequences/SquaresSequence.cs)

0 commit comments

Comments
 (0)