use num_traits::{ConstOne, ConstZero, NumCast, PrimInt};
pub trait Sequence<T>: Iterator<Item = T>
where
T: ConstZero,
{
fn sum_next_n(&mut self, n: usize) -> T {
let mut sum = T::ZERO;
for _ in 0..n {
match self.next() {
Some(x) => {
sum = sum + x;
}
None => {
break;
}
}
}
sum
}
}
#[cfg_attr(doc, katexit::katexit)]
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub struct CollatzSeq<T> {
current: T,
}
impl<T> CollatzSeq<T>
where
T: PrimInt + ConstOne,
{
pub fn new(n: T) -> Self {
if n < T::ONE {
panic!("Collatz sequence requires a positive integer starting point.");
}
Self { current: n }
}
}
impl<T> Iterator for CollatzSeq<T>
where
T: PrimInt + ConstZero + ConstOne,
{
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
if self.current == T::ZERO {
return None;
}
let value = self.current;
let t2 = T::from(2).unwrap();
if self.current % t2 == T::ZERO {
self.current = self.current / t2;
} else if self.current == T::ONE {
self.current = T::ZERO; } else {
self.current = T::from(3).unwrap() * self.current + T::ONE;
}
Some(value)
}
}
impl<T> Sequence<T> for CollatzSeq<T> where T: PrimInt + ConstZero + ConstOne {}
#[cfg_attr(doc, katexit::katexit)]
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub struct FibonacciSeq<T> {
curr: T,
next: T,
index: usize,
}
impl<T> Default for FibonacciSeq<T>
where
T: ConstZero + ConstOne,
{
fn default() -> Self {
Self::new()
}
}
impl<T> FibonacciSeq<T>
where
T: ConstZero + ConstOne,
{
pub fn new() -> Self {
Self {
curr: T::ZERO,
next: T::ONE,
index: 0,
}
}
}
impl<T> Iterator for FibonacciSeq<T>
where
T: PrimInt,
{
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
let value = self.curr;
[self.curr, self.next] = [self.next, self.curr + self.next];
self.index += 1;
Some(value)
}
fn nth(&mut self, n: usize) -> Option<Self::Item> {
self.index += n;
let n = self.index as f64;
let sqrt5 = 5f64.sqrt();
let a = (1.0 + sqrt5) / 2.0;
let b = (1.0 - sqrt5) / 2.0;
self.curr = T::from(((a.powf(n) - b.powf(n)) / sqrt5).round())
.expect("Overflow in Fibonacci calculation");
self.next = T::from(((a.powf(n + 1.0) - b.powf(n + 1.0)) / sqrt5).round())
.expect("Overflow in Fibonacci calculation");
self.next()
}
}
impl<T> Sequence<T> for FibonacciSeq<T> where T: PrimInt + ConstZero {}
#[cfg_attr(doc, katexit::katexit)]
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub struct NaturalNumbersSeq<T> {
current: T,
}
impl<T> Default for NaturalNumbersSeq<T>
where
T: ConstOne,
{
fn default() -> Self {
Self::new()
}
}
impl<T> NaturalNumbersSeq<T>
where
T: ConstOne,
{
pub fn new() -> Self {
Self { current: T::ONE }
}
}
impl<T> Iterator for NaturalNumbersSeq<T>
where
T: PrimInt + ConstOne,
{
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
let value = self.current;
self.current = self.current + T::ONE;
Some(value)
}
fn nth(&mut self, n: usize) -> Option<Self::Item> {
self.current =
self.current + T::from(n).expect("Overflow in nth calculation in NaturalNumbersSeq");
self.next()
}
}
impl<T> Sequence<T> for NaturalNumbersSeq<T>
where
T: PrimInt + ConstZero + ConstOne,
{
fn sum_next_n(&mut self, n: usize) -> T {
if n == 0 {
return T::ZERO;
}
let t2 = T::from(2).unwrap();
let tn = T::from(n).unwrap() + self.current - T::ONE;
let curr_sum = self.current * (self.current - T::ONE) / t2;
let next_sum = tn * (tn + T::ONE) / t2;
self.nth(n - 1);
next_sum - curr_sum
}
}
#[cfg_attr(doc, katexit::katexit)]
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub struct NaturalNumbersWithZeroSeq<T> {
current: T,
}
impl<T> Default for NaturalNumbersWithZeroSeq<T>
where
T: ConstZero,
{
fn default() -> Self {
Self::new()
}
}
impl<T> NaturalNumbersWithZeroSeq<T>
where
T: ConstZero,
{
pub fn new() -> Self {
Self { current: T::ZERO }
}
}
impl<T> Iterator for NaturalNumbersWithZeroSeq<T>
where
T: PrimInt + ConstOne,
{
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
let value = self.current;
self.current = self.current + T::ONE;
Some(value)
}
fn nth(&mut self, n: usize) -> Option<Self::Item> {
self.current = self.current
+ T::from(n).expect("Overflow in nth calculation in NaturalNumbersWithZeroSeq");
self.next()
}
}
impl<T> Sequence<T> for NaturalNumbersWithZeroSeq<T>
where
T: PrimInt + ConstZero + ConstOne,
{
fn sum_next_n(&mut self, n: usize) -> T {
if n == 0 {
return T::ZERO;
}
let tn = self.current + T::from(n).unwrap() - T::ONE;
let t2 = T::from(2).unwrap();
if self.current == T::ZERO {
self.nth(n - 1);
tn * (tn + T::ONE) / t2
} else {
let curr_sum = self.current * (self.current - T::ONE) / t2;
let next_sum = tn * (tn + T::ONE) / t2;
self.nth(n - 1);
next_sum - curr_sum
}
}
}
#[cfg_attr(doc, katexit::katexit)]
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub struct OddNaturalNumbersSeq<T> {
current: T,
}
impl<T> Default for OddNaturalNumbersSeq<T>
where
T: ConstOne,
{
fn default() -> Self {
Self::new()
}
}
impl<T> OddNaturalNumbersSeq<T>
where
T: ConstOne,
{
pub fn new() -> Self {
Self { current: T::ONE }
}
}
impl<T> Iterator for OddNaturalNumbersSeq<T>
where
T: PrimInt,
{
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
let value = self.current;
self.current = self.current + T::from(2).unwrap(); Some(value)
}
fn nth(&mut self, n: usize) -> Option<Self::Item> {
self.current = self.current
+ T::from(2).unwrap()
* T::from(n).expect("Overflow in nth calculation in OddNaturalNumbersSeq");
self.next()
}
}
impl<T> Sequence<T> for OddNaturalNumbersSeq<T>
where
T: PrimInt + ConstZero + ConstOne,
{
fn sum_next_n(&mut self, n: usize) -> T {
if n == 0 {
return T::ZERO;
}
let t2 = T::from(2).unwrap();
let n_curr = self.current / t2 + T::ONE;
let n_next = n_curr + T::from(n).unwrap() - T::ONE;
let curr_sum = (n_curr - T::ONE) * (n_curr - T::ONE);
let next_sum = n_next * n_next;
self.nth(n - 1);
next_sum - curr_sum
}
}
#[cfg_attr(doc, katexit::katexit)]
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub struct EvenNaturalNumbersSeq<T> {
current: T,
}
impl<T> Default for EvenNaturalNumbersSeq<T>
where
T: NumCast,
{
fn default() -> Self {
Self::new()
}
}
impl<T> EvenNaturalNumbersSeq<T>
where
T: NumCast,
{
pub fn new() -> Self {
Self {
current: T::from(2).unwrap(),
}
}
}
impl<T> Iterator for EvenNaturalNumbersSeq<T>
where
T: PrimInt,
{
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
let value = self.current;
self.current = self.current + T::from(2).unwrap(); Some(value)
}
fn nth(&mut self, n: usize) -> Option<Self::Item> {
self.current = self.current
+ T::from(2).unwrap()
* T::from(n).expect("Overflow in nth calculation in EvenNaturalNumbersSeq");
self.next()
}
}
impl<T> Sequence<T> for EvenNaturalNumbersSeq<T>
where
T: PrimInt + ConstZero + ConstOne,
{
fn sum_next_n(&mut self, n: usize) -> T {
if n == 0 {
return T::ZERO;
}
let t2 = T::from(2).unwrap();
let n_curr = self.current / t2;
let n_next = n_curr + T::from(n).unwrap() - T::ONE;
let curr_sum = n_curr * (n_curr - T::ONE);
let next_sum = n_next * (n_next + T::ONE);
self.nth(n - 1);
next_sum - curr_sum
}
}
#[cfg_attr(doc, katexit::katexit)]
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub struct EvenNaturalNumbersWithZeroSeq<T> {
current: T,
}
impl<T> Default for EvenNaturalNumbersWithZeroSeq<T>
where
T: ConstZero,
{
fn default() -> Self {
Self::new()
}
}
impl<T> EvenNaturalNumbersWithZeroSeq<T>
where
T: ConstZero,
{
pub fn new() -> Self {
Self { current: T::ZERO }
}
}
impl<T> Iterator for EvenNaturalNumbersWithZeroSeq<T>
where
T: PrimInt,
{
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
let value = self.current;
self.current = self.current + T::from(2).unwrap(); Some(value)
}
fn nth(&mut self, n: usize) -> Option<Self::Item> {
self.current = self.current
+ T::from(2).unwrap()
* T::from(n).expect("Overflow in nth calculation in EvenNaturalNumbersWithZeroSeq");
self.next()
}
}
impl<T> Sequence<T> for EvenNaturalNumbersWithZeroSeq<T>
where
T: PrimInt + ConstZero + ConstOne,
{
fn sum_next_n(&mut self, n: usize) -> T {
if n == 0 {
return T::ZERO;
}
let t2 = T::from(2).unwrap();
let n_curr = self.current / t2;
let n_next = n_curr + T::from(n).unwrap() - T::ONE;
if n_curr == T::ZERO {
self.nth(n - 1);
n_next * (n_next + T::ONE)
} else {
let curr_sum = n_curr * (n_curr - T::ONE);
let next_sum = n_next * (n_next + T::ONE);
self.nth(n - 1);
next_sum - curr_sum
}
}
}
#[cfg_attr(doc, katexit::katexit)]
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub struct NaturalNumbersSquaredSeq<T> {
current: T,
}
impl<T> Default for NaturalNumbersSquaredSeq<T>
where
T: ConstOne,
{
fn default() -> Self {
Self::new()
}
}
impl<T> NaturalNumbersSquaredSeq<T>
where
T: ConstOne,
{
pub fn new() -> Self {
Self { current: T::ONE }
}
}
impl<T> Iterator for NaturalNumbersSquaredSeq<T>
where
T: PrimInt + ConstOne,
{
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
let value = self.current * self.current;
self.current = self.current + T::ONE;
Some(value)
}
fn nth(&mut self, n: usize) -> Option<Self::Item> {
self.current = self.current
+ T::from(n).expect("Overflow in nth calculation in NaturalNumbersSquaredSeq");
self.next()
}
}
impl<T> Sequence<T> for NaturalNumbersSquaredSeq<T>
where
T: PrimInt + ConstZero + ConstOne,
{
fn sum_next_n(&mut self, n: usize) -> T {
if n == 0 {
return T::ZERO;
}
let t2 = T::from(2).unwrap();
let t6 = T::from(6).unwrap();
let n_next = self.current + T::from(n).unwrap() - T::ONE;
let curr_sum = (self.current - T::ONE) * self.current * (t2 * self.current - T::ONE) / t6;
let next_sum = n_next * (n_next + T::ONE) * (n_next * t2 + T::ONE) / t6;
self.nth(n - 1);
next_sum - curr_sum
}
}
#[cfg_attr(doc, katexit::katexit)]
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub struct NaturalNumbersWithZeroSquaredSeq<T> {
current: T,
}
impl<T> Default for NaturalNumbersWithZeroSquaredSeq<T>
where
T: ConstZero,
{
fn default() -> Self {
Self::new()
}
}
impl<T> NaturalNumbersWithZeroSquaredSeq<T>
where
T: ConstZero,
{
pub fn new() -> Self {
Self { current: T::ZERO }
}
}
impl<T> Iterator for NaturalNumbersWithZeroSquaredSeq<T>
where
T: PrimInt + ConstOne,
{
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
let value = self.current * self.current;
self.current = self.current + T::ONE;
Some(value)
}
fn nth(&mut self, n: usize) -> Option<Self::Item> {
self.current = self.current
+ T::from(n).expect("Overflow in nth calculation in NaturalNumbersWithZeroSquaredSeq");
self.next()
}
}
impl<T> Sequence<T> for NaturalNumbersWithZeroSquaredSeq<T>
where
T: PrimInt + ConstZero + ConstOne,
{
fn sum_next_n(&mut self, n: usize) -> T {
if n == 0 {
return T::ZERO;
}
let t2 = T::from(2).unwrap();
let t6 = T::from(6).unwrap();
let n_next = self.current + T::from(n).unwrap() - T::ONE;
if self.current == T::ZERO {
self.nth(n - 1);
n_next * (n_next + T::ONE) * (n_next * t2 + T::ONE) / t6
} else {
let curr_sum =
self.current * (self.current - T::ONE) * (t2 * self.current - T::ONE) / t6;
let next_sum = n_next * (n_next + T::ONE) * (n_next * t2 + T::ONE) / t6;
self.nth(n - 1);
next_sum - curr_sum
}
}
}
#[cfg_attr(doc, katexit::katexit)]
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub struct OddNaturalNumbersSquaredSeq<T> {
current: T,
}
impl<T> Default for OddNaturalNumbersSquaredSeq<T>
where
T: ConstOne,
{
fn default() -> Self {
Self::new()
}
}
impl<T> OddNaturalNumbersSquaredSeq<T>
where
T: ConstOne,
{
pub fn new() -> Self {
Self { current: T::ONE }
}
}
impl<T> Iterator for OddNaturalNumbersSquaredSeq<T>
where
T: PrimInt,
{
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
let value = self.current * self.current; self.current = self.current + T::from(2).unwrap(); Some(value)
}
fn nth(&mut self, n: usize) -> Option<Self::Item> {
self.current = self.current
+ T::from(2).unwrap()
* T::from(n).expect("Overflow in nth calculation in OddNaturalNumbersSquaredSeq");
self.next()
}
}
impl<T> Sequence<T> for OddNaturalNumbersSquaredSeq<T>
where
T: PrimInt + ConstZero + ConstOne,
{
fn sum_next_n(&mut self, n: usize) -> T {
if n == 0 {
return T::ZERO;
}
let t2 = T::from(2).unwrap();
let t3 = T::from(3).unwrap();
let n_curr = self.current / t2 + T::ONE;
let n_next = n_curr + T::from(n).unwrap() - T::ONE;
let curr_sum = if n_curr > T::ONE {
(n_curr - T::ONE) * (t2 * n_curr - T::ONE) * (t2 * n_curr - t3) / t3
} else {
T::ZERO
};
let next_sum = n_next * (t2 * n_next + T::ONE) * (t2 * n_next - T::ONE) / t3;
self.nth(n - 1);
next_sum - curr_sum
}
}
#[cfg_attr(doc, katexit::katexit)]
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub struct EvenNaturalNumbersSquaredSeq<T> {
current: T,
}
impl<T> Default for EvenNaturalNumbersSquaredSeq<T>
where
T: NumCast,
{
fn default() -> Self {
Self::new()
}
}
impl<T> EvenNaturalNumbersSquaredSeq<T>
where
T: NumCast,
{
pub fn new() -> Self {
Self {
current: T::from(2).unwrap(),
}
}
}
impl<T> Iterator for EvenNaturalNumbersSquaredSeq<T>
where
T: PrimInt,
{
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
let value = self.current * self.current; self.current = self.current + T::from(2).unwrap(); Some(value)
}
fn nth(&mut self, n: usize) -> Option<Self::Item> {
self.current = self.current
+ T::from(2).unwrap()
* T::from(n).expect("Overflow in nth calculation in EvenNaturalNumbersSquaredSeq");
self.next()
}
}
impl<T> Sequence<T> for EvenNaturalNumbersSquaredSeq<T>
where
T: PrimInt + ConstZero + ConstOne,
{
fn sum_next_n(&mut self, n: usize) -> T {
if n == 0 {
return T::ZERO;
}
let t2 = T::from(2).unwrap();
let t3 = T::from(3).unwrap();
let n_curr = self.current / t2;
let n_next = n_curr + T::from(n).unwrap() - T::ONE;
let curr_sum = t2 * (n_curr - T::ONE) * n_curr * (t2 * n_curr - T::ONE) / t3;
let next_sum = t2 * n_next * (n_next + T::ONE) * (t2 * n_next + T::ONE) / t3;
self.nth(n - 1);
next_sum - curr_sum
}
}
#[cfg_attr(doc, katexit::katexit)]
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub struct EvenNaturalNumbersWithZeroSquaredSeq<T> {
current: T,
}
impl<T> Default for EvenNaturalNumbersWithZeroSquaredSeq<T>
where
T: ConstZero,
{
fn default() -> Self {
Self::new()
}
}
impl<T> EvenNaturalNumbersWithZeroSquaredSeq<T>
where
T: ConstZero,
{
pub fn new() -> Self {
Self { current: T::ZERO }
}
}
impl<T> Iterator for EvenNaturalNumbersWithZeroSquaredSeq<T>
where
T: PrimInt,
{
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
let value = self.current * self.current; self.current = self.current + T::from(2).unwrap(); Some(value)
}
fn nth(&mut self, n: usize) -> Option<Self::Item> {
self.current = self.current
+ T::from(2).unwrap()
* T::from(n)
.expect("Overflow in nth calculation in EvenNaturalNumbersWithZeroSquaredSeq");
self.next()
}
}
impl<T> Sequence<T> for EvenNaturalNumbersWithZeroSquaredSeq<T>
where
T: PrimInt + ConstZero + ConstOne,
{
fn sum_next_n(&mut self, n: usize) -> T {
if n == 0 {
return T::ZERO;
}
let t2 = T::from(2).unwrap();
let t3 = T::from(3).unwrap();
let n_curr = self.current / t2;
let n_next = n_curr + T::from(n).unwrap() - T::ONE;
let curr_sum = if n_curr > T::ZERO {
t2 * (n_curr - T::ONE) * n_curr * (t2 * n_curr - T::ONE) / t3
} else {
T::ZERO
};
let next_sum = t2 * n_next * (n_next + T::ONE) * (t2 * n_next + T::ONE) / t3;
self.nth(n - 1);
next_sum - curr_sum
}
}