Rust で FizzBuzz 問題を解いてました!
いろいろな実装方法で試してみました!
- if 文
- match とタプル
- トレイトで判定結果を返す関数を実装
- (無駄に)Enum を定義
Rust で FizzBuzz 問題を解いてみた
FizzBuzz 問題とは、1以上の自然数を順に標準出力し、3の倍数のときにはFizz
、5の倍数のときにはBuzz
、3の倍数かつ5の倍数(= 15の倍数)のときにはFizzBuzz
を出力するプログラムを作成する問題のことです。
今回は1から100までの範囲でやってみます。
if 文で実装してみた
if
で問題文の通りに条件分岐させました。
これが1番シンプルで誰が見ても、やっていることがわかりやすいですね。
fn fizzbuzz(x: usize) -> String {
return if x % 3 == 0 && x % 5 == 0 {
"FizzBuzz".to_string()
} else if x % 3 == 0 {
"Fizz".to_string()
} else if x % 5 == 0 {
"Buzz".to_string()
} else {
x.to_string()
};
}
fn main() {
let limit = 100usize;
for x in 1..=limit {
println!("{}", fizzbuzz(x));
}
}
if x % 3 == 0 && x % 5 == 0
はif x % 15 == 0
でも同じ結果が得られます。
for_each とクロージャで実装してみた
FizzBuzz
の判定はif
のまま、繰り返し処理の部分を for_each とクロージャで置き換えました。
fn fizzbuzz(x: usize) -> String {
return if x % 3 == 0 && x % 5 == 0 {
"FizzBuzz".to_string()
} else if x % 3 == 0 {
"Fizz".to_string()
} else if x % 5 == 0 {
"Buzz".to_string()
} else {
x.to_string()
};
}
fn main() {
let limit = 100usize;
(1..=limit).for_each(|x| {
println!("{}", fizzbuzz(x));
});
}
文字列結合で実装してみた
文字列を出力すればOKなので、文字列結合するパターンで実装しました。
3の倍数と5の倍数の場合は、Fizz
にBizz
を結合することでFizzBuzz
を返します。
fn fizzbuzz(x: usize) -> String {
let mut result = if x % 3 == 0 {
"Fizz".to_string()
} else {
"".to_string()
};
if x % 5 == 0 {
result = result + "Buzz";
}
if result == "".to_string() {
result = x.to_string();
}
result
}
fn main() {
let limit = 100usize;
for x in 1..=limit {
println!("{}", fizzbuzz(x));
}
}
match とタプルで実装してみた
match
を使ってみました。
3と5それぞれで割ったときの剰余をタプルで持たせ、条件に一致するかをみています。
スッキリ書くことができて好印象です。
ただ、わかりやすさはif
には劣るかなと思います。
fn fizzbuzz(x: usize) -> String {
return match (x % 3, x % 5) {
(0, 0) => "FizzBuzz".to_string(),
(0, _) => "Fizz".to_string(),
(_, 0) => "Buzz".to_string(),
(_, _) => x.to_string(),
};
}
fn main() {
let limit = 100usize;
for x in 1..=limit {
println!("{}", fizzbuzz(x));
}
}
トレイトを使って実装してみた
トレイトFizzBuzz
を定義して、FizzBuzz の判定結果を文字列で返す関数の実装を強制させました。
単純に問題を解くだけなら、ここまでする必要はないでしょうね!笑
trait FizzBuzz {
fn fizzbuzz(&self) -> String;
}
impl FizzBuzz for usize {
fn fizzbuzz(&self) -> String {
return match (self % 3, self % 5) {
(0, 0) => "FizzBuzz".to_string(),
(0, _) => "Fizz".to_string(),
(_, 0) => "Buzz".to_string(),
(_, _) => self.to_string(),
};
}
}
fn main() {
let limit = 100usize;
for x in 1..=limit {
println!("{}", x.fizzbuzz());
}
}
Enum を定義してみた
Enum を文字列に変換させる方法 を調べたばかりなので、やってみました。
これも、単純に問題を解くだけなら、ここまでする必要はないですね笑
use std::fmt;
#[derive(Debug)]
enum FizzBuzzResult {
Fizz,
Buzz,
FizzBuzz,
Num(usize),
}
impl fmt::Display for FizzBuzzResult {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
FizzBuzzResult::Fizz => write!(f, "Fizz"),
FizzBuzzResult::Buzz => write!(f, "Buzz"),
FizzBuzzResult::FizzBuzz => write!(f, "FizzBuzz"),
FizzBuzzResult::Num(ref value) => write!(f, "{}", value),
}
}
}
trait FizzBuzz {
fn fizzbuzz(&self) -> FizzBuzzResult;
}
impl FizzBuzz for usize {
fn fizzbuzz(&self) -> FizzBuzzResult {
return match (self % 3, self % 5) {
(0, 0) => FizzBuzzResult::FizzBuzz,
(0, _) => FizzBuzzResult::Fizz,
(_, 0) => FizzBuzzResult::Buzz,
(_, _) => FizzBuzzResult::Num(*self),
};
}
}
fn main() {
let limit = 100usize;
for x in 1..=limit {
println!("{}", x.fizzbuzz().to_string());
}
}
Enum を文字列に変換する方法については以下の記事を見てみてください!
まとめ
いろいろな方法で実装できる、答えは1つではないのがプログラミングって感じがしますね。
FizzBuzz 問題では、剰余演算禁止や1行(ワンライナー)で記述するなどの縛りありで解くこともあるみたいです。
また挑戦してみようかな〜。
それにしても、新入社員研修で FizzBuzz 問題を C# を使って解いたなぁ。懐かしい。
コメント