-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Moved iterators into
src/utils/iterators
.
- Loading branch information
Showing
13 changed files
with
414 additions
and
380 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
pub mod fibonacci; | ||
pub mod polygonal; | ||
pub mod cubes; | ||
pub mod collatz; | ||
pub mod divisors; | ||
pub mod prime_divisors; | ||
pub mod digits; | ||
pub mod bits; | ||
pub mod pythagorean_triplets; | ||
pub mod potential_primes; | ||
pub mod continued_fraction; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
/// Bits iterator. Generates the binary digits of a number from least | ||
/// significant to most significant. Positive numbers only! | ||
pub struct Bits { | ||
num: i64, | ||
} | ||
impl Bits { | ||
pub fn new(num: i64) -> Bits { | ||
Bits { num } | ||
} | ||
} | ||
impl Iterator for Bits { | ||
type Item = i64; | ||
fn next(&mut self) -> Option<i64> { | ||
if self.num == 0 { | ||
None | ||
} else { | ||
let bit = self.num & 1; | ||
self.num >>= 1; | ||
Some(bit) | ||
} | ||
} | ||
} | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
/// Collatz sequence iterator. | ||
pub struct Collatz { | ||
num: i64, | ||
done: bool, | ||
} | ||
impl Collatz { | ||
pub fn new(num: i64) -> Collatz { | ||
Collatz { num, done: false } | ||
} | ||
} | ||
impl Iterator for Collatz { | ||
type Item = i64; | ||
fn next(&mut self) -> Option<i64> { | ||
if self.done { | ||
return None; | ||
} | ||
let num = self.num; | ||
self.num = if self.num % 2 == 0 { | ||
self.num / 2 | ||
} else { | ||
3 * self.num + 1 | ||
}; | ||
self.done = num == 1; | ||
Some(num) | ||
} | ||
} | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
use crate::utils; | ||
|
||
/// Generate the continued fraction representation of the square root of a | ||
/// number. The elements generated after the first shall constitute the | ||
/// repeating terms in the continued fraction. | ||
pub struct ContinuedFraction { | ||
num: i64, | ||
a0: i64, | ||
numerator_addend: i64, | ||
denominator: i64, | ||
} | ||
impl ContinuedFraction { | ||
pub fn new(num: i64) -> ContinuedFraction { | ||
ContinuedFraction { | ||
num, | ||
a0: utils::isqrt(num), | ||
numerator_addend: 0, | ||
denominator: 1, | ||
} | ||
} | ||
} | ||
impl Iterator for ContinuedFraction { | ||
type Item = i64; | ||
fn next(&mut self) -> Option<i64> { | ||
// This will happen if the given number was a perfect square. We will | ||
// also use this as the condition for detecting repeating terms. | ||
if self.denominator == 0 { | ||
return None; | ||
} | ||
|
||
// If a part of the continued fraction is | ||
// (num.sqrt() + numerator_addend) / denominator | ||
// then the next term of the continued fraction, `numerator_addend` and | ||
// `denominator` can be found using a recurrence relation. | ||
let a = (self.a0 + self.numerator_addend) / self.denominator; | ||
self.numerator_addend = a * self.denominator - self.numerator_addend; | ||
self.denominator = (self.num - self.numerator_addend.pow(2)) / self.denominator; | ||
|
||
// When this happens, the terms will start repeating. | ||
if a == self.a0 * 2 { | ||
self.denominator = 0; | ||
} | ||
Some(a) | ||
} | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
|
||
/// Cubes iterator. Generates cubes of integers without multiplication or | ||
/// exponentiation. | ||
pub struct Cubes { | ||
increment: i64, | ||
offset: i64, | ||
num: i64, | ||
} | ||
impl Cubes { | ||
pub fn new() -> Cubes { | ||
Cubes { | ||
increment: 6, | ||
offset: 1, | ||
num: 0, | ||
} | ||
} | ||
} | ||
impl Iterator for Cubes { | ||
type Item = i64; | ||
fn next(&mut self) -> Option<i64> { | ||
self.num += self.offset; | ||
self.offset += self.increment; | ||
self.increment += 6; | ||
Some(self.num) | ||
} | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
/// Digits iterator. Generates the decimal digits of a number from least | ||
/// significant to most significant. Positive numbers only! | ||
pub struct Digits { | ||
num: i64, | ||
} | ||
impl Digits { | ||
pub fn new(num: i64) -> Digits { | ||
Digits { num } | ||
} | ||
} | ||
impl Iterator for Digits { | ||
type Item = i64; | ||
fn next(&mut self) -> Option<i64> { | ||
if self.num == 0 { | ||
None | ||
} else { | ||
let digit = self.num % 10; | ||
self.num /= 10; | ||
Some(digit) | ||
} | ||
} | ||
} | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
use crate::utils; | ||
|
||
/// Divisors iterator. Generates all divisors of a number in an unspecified | ||
/// order. Positive numbers only! | ||
pub struct Divisors { | ||
dividend: i64, | ||
limit: i64, | ||
current: i64, | ||
other: i64, | ||
} | ||
impl Divisors { | ||
pub fn new(dividend: i64) -> Divisors { | ||
Divisors { | ||
dividend, | ||
limit: utils::isqrt(dividend), | ||
current: 0, | ||
other: 0, | ||
} | ||
} | ||
} | ||
impl Iterator for Divisors { | ||
type Item = i64; | ||
fn next(&mut self) -> Option<i64> { | ||
if self.other > 0 { | ||
let other = self.other; | ||
self.other = 0; | ||
return Some(other); | ||
} | ||
loop { | ||
self.current += 1; | ||
if self.current > self.limit { | ||
return None; | ||
} | ||
if self.dividend % self.current == 0 { | ||
let other = self.dividend / self.current; | ||
if other != self.current { | ||
self.other = other; | ||
} | ||
return Some(self.current); | ||
} | ||
} | ||
} | ||
} | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
/// Fibonacci sequence iterator. | ||
pub struct Fibonacci { | ||
a: i64, | ||
b: i64, | ||
} | ||
impl Fibonacci { | ||
pub fn new(a: i64, b: i64) -> Fibonacci { | ||
Fibonacci { a, b } | ||
} | ||
} | ||
impl Iterator for Fibonacci { | ||
type Item = i64; | ||
fn next(&mut self) -> Option<i64> { | ||
let a = self.a; | ||
(self.a, self.b) = (self.b, self.a + self.b); | ||
Some(a) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
|
||
/// Triangular, pentagonal, hexagonal, etc. number iterator. Specify the | ||
/// number of sides of the polygon as the argument to the constructor. | ||
pub struct Polygonal { | ||
increment: i64, | ||
offset: i64, | ||
num: i64, | ||
} | ||
impl Polygonal { | ||
pub fn new(sides: i64) -> Polygonal { | ||
Polygonal { | ||
increment: sides - 2, | ||
offset: 1, | ||
num: 0, | ||
} | ||
} | ||
/// Find the index at which the given number would appear in a sequence of | ||
/// polygonal numbers (if it is a polygonal number). | ||
/// | ||
/// * `sides` - Number of sides of the polygon the sequence is based on. | ||
/// * `num` - Number whose index is to be found. | ||
/// | ||
/// -> Index. | ||
pub fn invert(sides: i64, num: i64) -> Result<i64, i64> { | ||
// A polygonal number is a quadratic function of the index it appears | ||
// at. Solve for the positive root of the corresponding quadratic | ||
// equation. | ||
let a = sides - 2; | ||
let b = 4 - sides; | ||
let c = -2 * num; | ||
let discriminant = b.pow(2) - 4 * a * c; | ||
let idx = (-b as f64 + (discriminant as f64).sqrt()) / (2.0 * a as f64); | ||
let idx_rounded = idx.round() as i64; | ||
if idx.fract() == 0.0 { | ||
Ok(idx_rounded) | ||
} else { | ||
Err(idx_rounded) | ||
} | ||
} | ||
} | ||
impl Iterator for Polygonal { | ||
type Item = i64; | ||
fn next(&mut self) -> Option<i64> { | ||
self.num += self.offset; | ||
self.offset += self.increment; | ||
Some(self.num) | ||
} | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
/// Potential prime numbers. Generates some small prime numbers and numbers | ||
/// coprime to 30. Used for wheel factorisation with 2, 3 and 5. | ||
pub struct PotentialPrimes { | ||
limit: i64, | ||
num: i64, | ||
offset: std::iter::Cycle<std::array::IntoIter<i64, 8>>, | ||
} | ||
impl PotentialPrimes { | ||
pub fn new(limit: i64) -> PotentialPrimes { | ||
PotentialPrimes { | ||
limit, | ||
num: 1, | ||
offset: [4, 2, 4, 2, 4, 6, 2, 6].into_iter().cycle(), | ||
} | ||
} | ||
} | ||
impl Iterator for PotentialPrimes { | ||
type Item = i64; | ||
fn next(&mut self) -> Option<i64> { | ||
self.num += match self.num { | ||
1 => 1, | ||
2 => 1, | ||
3 | 5 => 2, | ||
_ => self.offset.next().unwrap(), | ||
}; | ||
if self.num > self.limit { | ||
None | ||
} else { | ||
Some(self.num) | ||
} | ||
} | ||
} | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
use crate::utils; | ||
|
||
/// Prime divisors iterator. Generates all prime divisors of a number in | ||
/// ascending order. Positive numbers only! | ||
pub struct PrimeDivisors { | ||
// If I actually find all prime numbers to iterate over (instead of just | ||
// using potential prime numbers), performance drops significantly. | ||
potential_primes: utils::PotentialPrimes, | ||
num: i64, | ||
} | ||
impl PrimeDivisors { | ||
pub fn new(num: i64) -> PrimeDivisors { | ||
PrimeDivisors { | ||
potential_primes: utils::PotentialPrimes::new(num), | ||
num, | ||
} | ||
} | ||
} | ||
impl Iterator for PrimeDivisors { | ||
type Item = (i64, u32); | ||
fn next(&mut self) -> Option<(i64, u32)> { | ||
loop { | ||
let potential_prime = match self.potential_primes.next() { | ||
Some(potential_prime) if potential_prime <= self.num => potential_prime, | ||
_ => return None, | ||
}; | ||
let mut power = 0; | ||
while self.num % potential_prime == 0 { | ||
self.num /= potential_prime; | ||
power += 1; | ||
} | ||
// Since I divide out the number by all potential primes I find, | ||
// the potential primes I do find are actually prime. | ||
if power > 0 { | ||
return Some((potential_prime, power)); | ||
} | ||
} | ||
} | ||
} | ||
|
||
|
Oops, something went wrong.