Skip to content

Commit

Permalink
Digitsum sequences (#42)
Browse files Browse the repository at this point in the history
  • Loading branch information
VascoSch92 authored Mar 31, 2024
2 parents 9e56635 + 72f1ecc commit e01461f
Show file tree
Hide file tree
Showing 7 changed files with 223 additions and 15 deletions.
12 changes: 11 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,17 @@ The version is represented by three digits: a.b.c.
## Unreleased

ENHANCEMENT:
- sequentium.sequence.sequences.explicit.py: add sequence A010060 (Thue-Morse Sequence)
- sequentium.sequence.sequences.explicit: add sequence A010060 (Thue-Morse Sequence)
- sequentium.sequence.sequences.explicit_generalised: add class DigitSumSequence (https://mathworld.wolfram.com/DigitSum.html)
- sequentium.sequence.sequences.explicit: add sequence A000120 (Number of 1's in binary expansion of n)
- sequentium.sequence.sequences.explicit: add sequence A053735 (Sum of digits of n written in base 3)
- sequentium.sequence.sequences.explicit: add sequence A053737 (Sum of digits of n written in base 4)
- sequentium.sequence.sequences.explicit: add sequence A053824 (Sum of digits of n written in base 5)
- sequentium.sequence.sequences.explicit: add sequence A053827 (Sum of digits of n written in base 6)
- sequentium.sequence.sequences.explicit: add sequence A053828 (Sum of digits of n written in base 7)
- sequentium.sequence.sequences.explicit: add sequence A053829 (Sum of digits of n written in base 8)
- sequentium.sequence.sequences.explicit: add sequence A053830 (Sum of digits of n written in base 9)
- sequentium.sequence.sequences.explicit: add sequence A007953 (digit sum)

---

Expand Down
12 changes: 10 additions & 2 deletions sequence/SEQUENCES_LIST.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ List of implemented integer sequences.
| A000045 | The Fibonacci numbers | `A000045`, `FibonacciNumbers`, `FibonacciSequence` | https://oeis.org/A000045 |
| A000073 | The Tribonacci numbers | `A000073`, `TribonacciNumbers` | https://oeis.org/A000073 |
| A000078 | The Tetranacci numbers | `A000078`, `TetranacciNumbers` | https://oeis.org/A000078 |
| A000120 | Sequence A000120 | `A000120`, | https://oeis.org/A000120 |
| A000129 | The Pell numbers | `A000129`, `PellNumbers`, `LambdaNumbers` | https://oeis.org/A000129 |
| A000217 | The triangular numbers | `A000217`, `TriangularNumbers` | https://oeis.org/A000217 |
| A000290 | The square numbers | `A000290`, `SquareNumbers` | https://oeis.org/A000290 |
Expand All @@ -39,6 +40,7 @@ List of implemented integer sequences.
| A003173 | The Heegner numbers | `A003173`, `HeegnerNumbers` | https://oeis.org/A003173 |
| A003215 | The hex numbers | `A003215`, `HexNumbers`, `CenteredHexagonalNumbers` | https://oeis.org/A003215 |
| A005408 | The odd numbers | `A005408`, `OddNumbers` | https://oeis.org/A005408 |
| A007953 | The digit sum | `A007953`, `Digsum` | https://oeis.org/A007953 |
| A010060 | The Thue-Morse sequence | `A010060`, `ThueMorseSequence` | https://oeis.org/A010060 |
| A014551 | Jacobsthal-Lucas numbers | `A014551`, `JachobsthalLucasNumbers` | https://oeis.org/A014551 |
| A033999 | Sequence of powers of -1 | `A033999` | https://oeis.org/A033999 |
Expand All @@ -56,6 +58,13 @@ List of implemented integer sequences.
| A051874 | The icosidigonal numbers | `A051874`, `IcosidigonalNumbers` | https://oeis.org/A051874 |
| A051875 | The icositrigonal numbers | `A051875`, `IcositrigonalNumbers` | https://oeis.org/A051875 |
| A051876 | The icositetragonal numbers | `A051876`, `IcositetragonalNumbers` | https://oeis.org/A051876 |
| A053735 | Sequence A053735 | `A053735` | https://oeis.org/A053735 |
| A053737 | Sequence A053737 | `A053737` | https://oeis.org/A053737 |
| A053824 | Sequence A053824 | `A053824` | https://oeis.org/A053824 |
| A053827 | Sequence A053827 | `A053827` | https://oeis.org/A053827 |
| A053828 | Sequence A053828 | `A053828` | https://oeis.org/A053828 |
| A053829 | Sequence A053829 | `A053829` | https://oeis.org/A053829 |
| A053830 | Sequence A053830 | `A053830` | https://oeis.org/A053830 |
| A079262 | The Octanacci numbers | `A079262`, `OctanacciNumbers` | https://oeis.org/A079262 |
| A087204 | Sequence A087204 | `A087204` | https://oeis.org/A087204 |
| A104144 | The Enneanacci numbers | `A104144`, `EnneanacciNumebrs` | https://oeis.org/A104144 |
Expand All @@ -75,11 +84,10 @@ List of implemented generalised integer sequences.
| Sequence Name | Sequence class name(s) | Reference |
|--------------------------------|-----------------------------|--------------------------------------------------------------------|
| The constant sequence | `ConstantSequence` | - |
| The digit sum sequence | `DigitSumSequence` | https://mathworld.wolfram.com/DigitSum.html |
| The generalised Nexus numbers | `GeneralisedNexusNumbers` | https://mathworld.wolfram.com/NexusNumber.html |
| High order Fibonacci numbers | `HighOrderFibonacciNumbers` | https://en.wikipedia.org/wiki/Generalizations_of_Fibonacci_numbers |
| The Lucas sequence U_n | `LucasSequenceU` | https://en.wikipedia.org/wiki/Lucas_sequence |
| The Lucas sequence V_n | `LucasSequenceV` | https://en.wikipedia.org/wiki/Lucas_sequence |
| The primes of a given sequence | `PrimesOfSequence` | - |
| The polygonal numbers | `PolygonalNumbers` | https://en.m.wikipedia.org/wiki/Polygonal_number |


85 changes: 85 additions & 0 deletions sequence/sequences/integer/explicit.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from sequence.core.infinite_type import Explicit
from sequence.core.utils.functions import digit_sum
from sequence.sequences.integer.explicit_generalised import (
DigitSumSequence,
PolygonalNumbers,
GeneralisedNexusNumbers,
)
Expand All @@ -25,6 +26,15 @@ def formula(self, index: int) -> int:
NaturalNumbers = A000027


class A000120(DigitSumSequence):
"""Number of 1's in binary expansion of n (https://oeis.org/A000120)."""

sequence_name = "sequence A000120"

def __init__(self) -> None:
super().__init__(base=2)


class A000217(PolygonalNumbers):
"""Triangular numbers (https://oeis.org/A000217)."""

Expand Down Expand Up @@ -171,6 +181,18 @@ def formula(self, index: int) -> int:
OddNumbers = A005408


class A007953(DigitSumSequence):
"""Digital sum (i.e., sum of digits) of n (https://oeis.org/A007953)."""

sequence_name = "digsum"

def __init__(self) -> None:
super().__init__(base=10)


Digsum = A007953


class A010060(Explicit):
"""Thue-Morse sequence (https://oeis.org/A010060)."""

Expand Down Expand Up @@ -383,6 +405,69 @@ def __init__(self) -> None:
IcositetragonalNumbers = A051876


class A053735(DigitSumSequence):
"""Sum of digits of n written in base 3 (https://oeis.org/A053735)."""

sequence_name = "sequence A053735"

def __init__(self) -> None:
super().__init__(base=3)


class A053737(DigitSumSequence):
"""Sum of digits of n written in base 4 (https://oeis.org/A053737)."""

sequence_name = "sequence A053737"

def __init__(self) -> None:
super().__init__(base=4)


class A053824(DigitSumSequence):
"""Sum of digits of n written in base 5 (https://oeis.org/A053824)."""

sequence_name = "sequence A053824"

def __init__(self) -> None:
super().__init__(base=5)


class A053827(DigitSumSequence):
"""Sum of digits of n written in base 6 (https://oeis.org/A053827)."""

sequence_name = "sequence A053827"

def __init__(self) -> None:
super().__init__(base=6)


class A053828(DigitSumSequence):
"""Sum of digits of n written in base 7 (https://oeis.org/A053828)."""

sequence_name = "sequence A053828"

def __init__(self) -> None:
super().__init__(base=7)


class A053829(DigitSumSequence):
"""Sum of digits of n written in base 8 (https://oeis.org/A053829)."""

sequence_name = "sequence A053829"

def __init__(self) -> None:
super().__init__(base=8)


class A053830(DigitSumSequence):
"""Sum of digits of n written in base 9 (htpps://oeis.org/A053830)."""

sequence_name = "sequence A053830"

def __init__(self) -> None:
super().__init__(base=9)


class A167149(PolygonalNumbers):
"""Myriagonal numbers (https://oeis.org/A167149)."""

Expand Down
22 changes: 22 additions & 0 deletions sequence/sequences/integer/explicit_generalised.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,31 @@

from sequence.core.mixin import MonotonicIncreasingMixin
from sequence.core.infinite_type import Explicit
from sequence.core.utils.functions import digit_sum
from sequence.core.utils.validation import validate_positive_integer


class DigitSumSequence(Explicit):
"""
Class representing digit sum sequences
Attributes:
- base (int): The base of the number to sum the digits
"""

sequence_name = "digit sum sequence"

def __init__(self, base: int) -> None:
super().__init__()
self.base = validate_positive_integer(integer=base)

def __contains__(self, item: Any) -> bool:
return True

def formula(self, index: int) -> int:
return digit_sum(number=index, base=self.base)


class GeneralisedNexusNumbers(MonotonicIncreasingMixin, Explicit):
"""
Class representing a sequence of Generalised Nexus Numbers (https://mathworld.wolfram.com/NexusNumber.html).
Expand Down
11 changes: 1 addition & 10 deletions tests/sequence_test_suite.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def test_is_finite(self) -> None:
"""Test if the sequence's finiteness matches the expected value."""
if self.sequence.is_finite != self.is_finite:
raise ValueError(
f"Expected {self.is_finite} as output of the method `is_finite`. " f"But got {self.sequence.is_finite}."
f"Expected {self.is_finite} as output of the method `is_finite`. But got {self.sequence.is_finite}."
)

def test_is_periodic(self) -> None:
Expand Down Expand Up @@ -73,15 +73,6 @@ def test_in_operator(self) -> None:
if error_msg:
raise ValueError(error_msg)

def test_not_in_operator(self) -> None:
"""Test if elements not in the ground truth are correctly identified as not in the sequence."""
error_msg = ""
for element in range(len(self.ground_truth)):
if element not in self.ground_truth and (element not in self.sequence) is False:
error_msg += f"- The expression ({element} in sequence) must be False, but it is not.\n"
if error_msg:
raise ValueError(error_msg)

def test_as_list(self) -> None:
"""Test if the as_list method returns the expected subsequence for various start and stop indices."""
error_msg = ""
Expand Down
91 changes: 91 additions & 0 deletions tests/tests_integer_sequences/test_explicit.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,16 @@ class TestA000027(SequenceTestSuite):
ground_truth = list(range(100))


class TestA000120(SequenceTestSuite):
sequence = A000120()
sequence_name = "sequence A000120"
ground_truth = [
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, 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, 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, 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, 3, 4, 4, 5, 3,
]


class TestA000217(SequenceTestSuite):
sequence = A000217()
sequence_name = "triangular numbers"
Expand Down Expand Up @@ -107,6 +117,16 @@ class TestA005408(SequenceTestSuite):
ground_truth = [2 * index + 1 for index in range(50)]


class TestA007953(SequenceTestSuite):
sequence = A007953()
sequence_name = "digsum"
ground_truth = [
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 3, 4, 5, 6, 7, 8,
9, 10, 11, 12, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 6, 7, 8, 9, 10, 11, 12, 13,
14, 15, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 8, 9, 10, 11, 12, 13, 14, 15,
]


class TestA010060(SequenceTestSuite):
sequence = A010060()
sequence_name = "Thue-Morse sequence"
Expand All @@ -116,6 +136,7 @@ class TestA010060(SequenceTestSuite):
0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0
]


class TestA014551(SequenceTestSuite):
sequence = A014551()
sequence_name = "Jacobsthal-Lucas numbers"
Expand Down Expand Up @@ -272,6 +293,76 @@ class TestA051876(SequenceTestSuite):
]


class TestA053735(SequenceTestSuite):
sequence = A053735()
sequence_name = "sequence A053735"
ground_truth = [
0, 1, 2, 1, 2, 3, 2, 3, 4, 1, 2, 3, 2, 3, 4, 3, 4, 5, 2, 3, 4, 3, 4, 5, 4, 5, 6, 1, 2, 3, 2, 3, 4, 3, 4, 5, 2,
3, 4, 3, 4, 5, 4, 5, 6, 3, 4, 5, 4, 5, 6, 5, 6, 7, 2, 3, 4, 3, 4, 5, 4, 5, 6, 3, 4, 5, 4, 5, 6, 5, 6, 7, 4, 5,
6, 5, 6, 7, 6, 7, 8, 1, 2, 3, 2, 3, 4, 3, 4, 5, 2, 3, 4, 3, 4, 5, 4, 5, 6, 3, 4, 5, 4, 5, 6,
]


class TestA053737(SequenceTestSuite):
sequence = A053737()
sequence_name = "sequence A053737"
ground_truth = [
0, 1, 2, 3, 1, 2, 3, 4, 2, 3, 4, 5, 3, 4, 5, 6, 1, 2, 3, 4, 2, 3, 4, 5, 3, 4, 5, 6, 4, 5, 6, 7, 2, 3, 4, 5, 3,
4, 5, 6, 4, 5, 6, 7, 5, 6, 7, 8, 3, 4, 5, 6, 4, 5, 6, 7, 5, 6, 7, 8, 6, 7, 8, 9, 1, 2, 3, 4, 2, 3, 4, 5, 3, 4,
5, 6, 4, 5, 6, 7, 2, 3, 4, 5, 3, 4, 5, 6, 4, 5, 6, 7, 5, 6, 7, 8, 3, 4, 5, 6, 4, 5, 6, 7, 5,
]


class TestA053824(SequenceTestSuite):
sequence = A053824()
sequence_name = "sequence A053824"
ground_truth = [
0, 1, 2, 3, 4, 1, 2, 3, 4, 5, 2, 3, 4, 5, 6, 3, 4, 5, 6, 7, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 2, 3, 4, 5, 6, 3, 4,
5, 6, 7, 4, 5, 6, 7, 8, 5, 6, 7, 8, 9, 2, 3, 4, 5, 6, 3, 4, 5, 6, 7, 4, 5, 6, 7, 8, 5, 6, 7, 8, 9, 6, 7, 8, 9,
10, 3, 4, 5, 6, 7, 4, 5, 6, 7, 8, 5, 6, 7, 8, 9, 6, 7, 8, 9, 10, 7, 8, 9, 10, 11, 4, 5, 6,
]


class TestA053827(SequenceTestSuite):
sequence = A053827()
sequence_name = "sequence A053827"
ground_truth = [
0, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 6, 2, 3, 4, 5, 6, 7, 3, 4, 5, 6, 7, 8, 4, 5, 6, 7, 8, 9, 5, 6, 7, 8, 9, 10, 1,
2, 3, 4, 5, 6, 2, 3, 4, 5, 6, 7, 3, 4, 5, 6, 7, 8, 4, 5, 6, 7, 8, 9, 5, 6, 7, 8, 9, 10, 6, 7, 8, 9, 10, 11, 2,
3, 4, 5, 6, 7, 3, 4, 5, 6, 7, 8, 4, 5, 6, 7, 8, 9, 5, 6, 7, 8, 9, 10, 6, 7, 8, 9, 10,
]


class TestA053828(SequenceTestSuite):
sequence = A053828()
sequence_name = "sequence A053828"
ground_truth = [
0, 1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 8, 3, 4, 5, 6, 7, 8, 9, 4, 5, 6, 7, 8, 9, 10, 5, 6,
7, 8, 9, 10, 11, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 8, 3, 4, 5, 6, 7, 8, 9, 4, 5, 6,
7, 8, 9, 10, 5, 6, 7, 8, 9, 10, 11, 6, 7, 8, 9, 10, 11, 12, 7, 8, 9, 10, 11,
]


class TestA053829(SequenceTestSuite):
sequence = A053829()
sequence_name = "sequence A053829"
ground_truth = [
0, 1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 8, 2, 3, 4, 5, 6, 7, 8, 9, 3, 4, 5, 6, 7, 8, 9, 10, 4, 5, 6, 7, 8,
9, 10, 11, 5, 6, 7, 8, 9, 10, 11, 12, 6, 7, 8, 9, 10, 11, 12, 13, 7, 8, 9, 10, 11, 12, 13, 14, 1, 2, 3, 4, 5, 6,
7, 8, 2, 3, 4, 5, 6, 7, 8, 9, 3, 4, 5, 6, 7, 8, 9, 10, 4, 5, 6, 7, 8, 9, 10,
]


class TestA053830(SequenceTestSuite):
sequence = A053830()
sequence_name = "sequence A053830"
ground_truth = [
0, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 9, 2, 3, 4, 5, 6, 7, 8, 9, 10, 3, 4, 5, 6, 7, 8, 9, 10, 11,
4, 5, 6, 7, 8, 9, 10, 11, 12, 5, 6, 7, 8, 9, 10, 11, 12, 13, 6, 7, 8, 9, 10, 11, 12, 13, 14, 7, 8, 9, 10, 11,
12, 13, 14, 15, 8, 9, 10, 11, 12, 13, 14, 15, 16, 1, 2, 3, 4, 5, 6, 7, 8, 9,
]


class TestA167149(SequenceTestSuite):
sequence = A167149()
sequence_name = "myriagonal numbers"
Expand Down
5 changes: 3 additions & 2 deletions tests/tests_meta/test_scripts.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,15 @@ def test_markdown() -> None:

sequences_in_markdown_but_not_in_scripts = sequence_markdown.difference(sequence_scripts)
error_msg = ""
if sequences_in_markdown_but_not_in_scripts != set():
sequences_in_markdown_but_not_in_scripts = {entry for entry in sequences_in_markdown_but_not_in_scripts if entry}
if len(sequences_in_markdown_but_not_in_scripts) > 0:
error_msg += (
f"The following sequences are in the SEQUENCE_LIST.md, "
f"but are not implemented: {', '.join(list(sequences_in_markdown_but_not_in_scripts))}\n"
)

sequences_in_scripts_but_not_in_markdown = sequence_scripts.difference(sequence_markdown)
if sequences_in_scripts_but_not_in_markdown != set():
if len(sequences_in_scripts_but_not_in_markdown) > 0:
error_msg += (
f"The following sequences are implemented, "
f"but are not in SEQUENCE_LIST.md: {', '.join(list(sequences_in_scripts_but_not_in_markdown))}"
Expand Down

0 comments on commit e01461f

Please sign in to comment.