Created
December 30, 2021 15:40
-
-
Save carrascomj/9720111916f1fec36866741c8c21ffe6 to your computer and use it in GitHub Desktop.
Rust FizzBuzz Iterator
This file contains hidden or 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
#[derive(Debug, PartialEq, PartialOrd)] | |
pub enum FizzBuzz<T> { | |
Fizz, | |
Buzz, | |
FizzBuzz, | |
Value(T), | |
} | |
#[must_use = "iterators are lazy and must be consumed"] | |
pub struct FBIt<I> { | |
iter: I, | |
count: usize, | |
} | |
impl<I> FBIt<I> { | |
fn new(iter: I) -> Self { | |
Self { iter, count: 0 } | |
} | |
} | |
impl<I> Iterator for FBIt<I> | |
where | |
I: Iterator, | |
{ | |
type Item = FizzBuzz<I::Item>; | |
fn next(&mut self) -> Option<Self::Item> { | |
let res = self.iter.next().map(|arg| { | |
if self.count % 15 == 0 { | |
FizzBuzz::FizzBuzz | |
} else if self.count % 3 == 0 { | |
FizzBuzz::Fizz | |
} else if self.count % 5 == 0 { | |
FizzBuzz::Buzz | |
} else { | |
FizzBuzz::Value(arg) | |
} | |
}); | |
self.count += 1; | |
res | |
} | |
} | |
pub trait IntoFizzIterator<I> { | |
fn fizz(self) -> FBIt<I>; | |
} | |
impl<I> IntoFizzIterator<I> for I | |
where | |
I: Iterator, | |
{ | |
fn fizz(self) -> FBIt<I> { | |
FBIt::new(self) | |
} | |
} | |
#[cfg(test)] | |
mod tests { | |
use super::*; | |
// testing can also be overengineered | |
impl FizzBuzz<i32> { | |
pub fn number(i: usize) -> FizzBuzz<i32> { | |
match i { | |
15 => FizzBuzz::FizzBuzz, | |
3 => FizzBuzz::Fizz, | |
5 => FizzBuzz::Buzz, | |
_ => FizzBuzz::Value(0), | |
} | |
} | |
} | |
#[test] | |
fn get_fizz_buzz_constructs() { | |
assert!(FBIt::new(1i32..100i32) | |
.enumerate() | |
.filter(|(i, _)| i % 15 == 0) | |
.all(|(_, x)| x == FizzBuzz::FizzBuzz)) | |
} | |
#[test] | |
fn get_fizz_buzz_flows_from_iter() { | |
assert!((1i32..100i32) | |
.fizz() | |
.enumerate() | |
.filter(|(i, _)| i % 15 == 0) | |
.all(|(_, x)| x == FizzBuzz::FizzBuzz)) | |
} | |
#[test] | |
fn all_fizz_cases_are_satisfied() { | |
for count in [3, 5, 15] { | |
assert!((1i32..100i32) | |
.fizz() | |
.enumerate() | |
// count case except when count != 15 and i is a 15 multiple | |
.filter(|(i, _)| (i % count == 0) & ((i % 15 != 0) & (count != 15))) | |
.all(|(_, x)| x == FizzBuzz::number(count))) | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment