2009年3月28日土曜日

ErlangでFizzBuzz問題、それをC++のテンプレートで表現する

このブログ記事をはてなブックマークに追加

今更ながらFizzBuzz問題を解いてみる。今回はErlangで解いてみた。それだけだとつまらないので、それをC++のテンプレートで表現してみた。因みにErlangを使っているけど並列処理はしていない。

まずは普通に何の工夫もなく書いてみた。

-module(fizzbuzz). -export([fb/1]). fb(0) -> ok; fb(N) -> fb(N - 1), if N rem 15 =:= 0 -> io:put_chars("FizzBuzz"); N rem 3 =:= 0 -> io:put_chars("Fizz"); N rem 5 =:= 0 -> io:put_chars("Buzz"); true -> io:write(N) end, io:nl().

うーん、面白くない。どうせなら if をなくしてしまおう。というわけで、今度は以下のように書いた。

-module(fizzbuzz). -export([fb/3, fizzbuzz/1]). fb(_, 0, 0) -> io:put_chars("FizzBuzz\n"); fb(_, 0, _) -> io:put_chars("Fizz\n"); fb(_, _, 0) -> io:put_chars("Buzz\n"); fb(N, _, _) -> io:write(N), io:nl(). fizzbuzz(0) -> ok; fizzbuzz(N) -> fizzbuzz(N - 1), fb(N, N rem 3, N rem 5).

少しは関数型プログラミングっぽいかなぁ? これをC++のテンプレートで書いてみると以下のようになる。

#include <iostream> template<int N, int M3, int M5> struct FB { FB() { std::cout << N << std::endl; } }; template<int N, int M5> struct FB<N, 0, M5> { FB() { std::cout << "Fizz" << std::endl; } }; template<int N, int M3> struct FB<N, M3, 0> { FB() { std::cout << "Buzz" << std::endl; } }; template<int N> struct FB<N, 0, 0> { FB() { std::cout << "FizzBuzz" << std::endl; } }; template<int N> struct FizzBuzz { FizzBuzz() { FizzBuzz<N-1>(); FB<N, N%3, N%5>(); } }; template<> struct FizzBuzz<0> {}; int main() { FizzBuzz<100>(); return 0; }

どうせなら2つある関数(C++ならクラス)を1つにしてみよう。

-module(fizzbuzz). -export([fb/1]). fb(0, 0, 0) -> ok; fb(N, 0, 0) -> fb(N-1, (N-1) rem 3, (N-1) rem 5), io:put_chars("FizzBuzz\n"); fb(N, 0, _) -> fb(N-1, (N-1) rem 3, (N-1) rem 5), io:put_chars("Fizz\n"); fb(N, _, 0) -> fb(N-1, (N-1) rem 3, (N-1) rem 5), io:put_chars("Buzz\n"); fb(N, _, _) -> fb(N-1, (N-1) rem 3, (N-1) rem 5), io:write(N), io:nl(). fb(N) -> fb(N, N rem 3, N rem 5).

C++のテンプレートでは以下の通り。

#include <iostream> template<int N, int M3=N%3, int M5=N%5> struct FB { FB() { FB<N-1, (N-1)%3, (N-1)%5>(); std::cout << N << std::endl; } }; template<int N, int M5> struct FB<N, 0, M5> { FB() { FB<N-1, (N-1)%3, (N-1)%5>(); std::cout << "Fizz" << std::endl; } }; template<int N, int M3> struct FB<N, M3, 0> { FB() { FB<N-1, (N-1)%3, (N-1)%5>(); std::cout << "Buzz" << std::endl; } }; template<int N> struct FB<N, 0, 0> { FB() { FB<N-1, (N-1)%3, (N-1)%5>(); std::cout << "FizzBuzz" << std::endl; } }; template<> struct FB<0, 0, 0> {}; int main() { FB<100>(); return 0; }

何だかちょっとやり過ぎな気がするなぁ。

0 コメント: