Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FizzBuzz #1

Open
ErikLambrechts opened this issue Apr 13, 2023 · 3 comments
Open

FizzBuzz #1

ErikLambrechts opened this issue Apr 13, 2023 · 3 comments

Comments

@ErikLambrechts
Copy link

This is a nice project. I just would like to add that the FizzBuzz example could be done with a match construction. So it may not be the best example of control flow.
Here is my take on the FizzBuzz code

fn main() {
    for i in 1..=100 {
        match i {
            i if i % 3 == 0 && i % 5 == 0 => println!("FizzBuzz"),
            i if i % 3 == 0 => println!("Fizz"),
            i if i % 5 == 0 => println!("Buzz"),
            i => println!("{}", i),
        }
    }
}
@joelparkerhenderson
Copy link
Member

Great point. I'll add that to the next version.

You're inspiring me to use FizzBuzz as a way to explain generic traits too... something like this...

pub trait FizzBuzz {
    fn fizzbuzz(&self) -> String;
}

impl<T> FizzBuzz for T
where 
    T: num::traits::int::PrimInt,
    T: std::fmt::Display,
{
    fn fizzbuzz(&self) -> String {
        let t0 = T::zero();
        let t3 = T::from(3).unwrap();
        let t5 = T::from(5).unwrap();
        match (*self % t3 == t0, *self % t5 == t0) {
            (true, true) => String::from("FizzBuzz"),
            (true, _) => String::from("Fizz"),
            (_, true) => String::from("Buzz"),
            _ => format!("{}", self),
        }
    }
}

fn main() {
    for i in 1..=100 {
        println!("{}", i.fizzbuzz())
    }
}

@ErikLambrechts
Copy link
Author

Great example.

Here is my take on FizzBuzz using some other features

Using iterators and closures

fn main() {
    let max_iterations = 100;

    (1..=max_iterations).map(|n| {
        match (n % 3, n % 5) {
            (0, 0) => "FizzBuzz".to_string(),
            (0, _) => "Fizz".to_string(),
            (_, 0) => "Buzz".to_string(),
            _ => n.to_string(),
        }
    }).for_each(|result| println!("{}", result));
}

Implementing your own iterator

struct FizzBuzz {
    current: u32,
    max: u32,
}

impl FizzBuzz {
    fn new(max: u32) -> Self {
        Self {
            current: 1,
            max,
        }
    }
}

impl Iterator for FizzBuzz {
    type Item = String;

    fn next(&mut self) -> Option<Self::Item> {
        if self.current > self.max {
            return None;
        }

        let result = match (self.current % 3 == 0, self.current % 5 == 0) {
            (true, true) => "FizzBuzz".to_string(),
            (true, false) => "Fizz".to_string(),
            (false, true) => "Buzz".to_string(),
            _ => self.current.to_string(),
        };

        self.current += 1;
        Some(result)
    }
}

fn main() {
    for fb in FizzBuzz::new(100) {
        println!("{}", fb);
    }
}

@joelparkerhenderson
Copy link
Member

That's great! What a fun code golf. :-)

I wonder how much faster the code could be with refactoring the to_string to a constant str slice, or to a clone-on-write String.

Or how much faster the code could be with pre-filled 15-item array of Option, and an index = n % 15 that returns Some(n) => n, or None => n as a string?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants