kolakoski/lib.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
#[cfg_attr(not(feature = "num-traits"), no_std)]
#[cfg(feature = "num-traits")]
extern crate num;
#[cfg(test)]
mod test;
/// An Iterator that returns numbers from the Kolakoski sequence
///
/// Information about the Kolakoski sequence and the first 108 numbers
/// can be found at https://oeis.org/A000002. The source of the numbers
/// used for testing in `test.rs` is also https://oeis.org/A000002.
///
/// This sequence is self-refrential, and the implementation is recursive.
/// Attempts to get a large number of items from the sequence may overflow
/// the stack, depending on the machine. Use with caution!
pub struct Kolakoski
{
run: usize,
run_length: u8,
is_one: bool,
}
#[cfg(feature = "num-traits")]
pub struct KolakoskiNum<N>
{
run: usize,
run_length: N,
is_one: bool,
}
impl Kolakoski
{
/// Creates a new Kolakoski iterator
pub fn new() -> Kolakoski
{
Kolakoski
{
run: 0,
run_length: 1,
is_one: true,
}
}
}
#[cfg(feature = "num-traits")]
impl<N: Num> KolakoskiNum<N>
{
/// Creates a new Kolakoski iterator
pub fn new() -> KolakoskiNum<N>
{
KolakoskiNum
{
run: 0,
run_length: N::one(),
is_one: true,
}
}
}
impl Iterator for Kolakoski
{
type Item = u8;
fn next(&mut self) -> Option<Self::Item>
{
if self.run_length == 0
{
self.is_one = !self.is_one;
self.run += 1;
if self.run == 1
{
self.run_length = 2;
}
else
{
self.run_length = Kolakoski::new().nth(self.run).unwrap();
}
}
self.run_length -= 1;
if self.is_one
{
Some(1)
}
else
{
Some(2)
}
}
}
#[cfg(feature = "num-traits")]
use num::traits::Num;
#[cfg(feature = "num-traits")]
impl<N: Num + Clone> Iterator for KolakoskiNum<N>
{
type Item = N;
fn next(&mut self) -> Option<Self::Item>
{
if self.run_length == N::zero()
{
self.is_one = !self.is_one;
self.run += 1;
if self.run == 1
{
self.run_length = N::one() + N::one()
}
else
{
self.run_length = KolakoskiNum::<N>::new().nth(self.run).unwrap();
}
}
self.run_length = self.run_length.clone() - N::one();
if self.is_one
{
Some(N::one())
}
else
{
Some(N::one() + N::one())
}
}
}