FibBuzz で fibonacci をメモ化
前回の続き。
Boost.Flyweight を使用してfibonacci をメモ化しました。
これで実行速度が鬼のように早くなった。
[ソース]
#include <boost/flyweight.hpp> #include <boost/flyweight/key_value.hpp> #include <boost/flyweight/no_tracking.hpp> #include <boost/phoenix/bind.hpp> #include <boost/phoenix/operator.hpp> #include <boost/phoenix/core/argument.hpp> #include <boost/phoenix/object/construct.hpp> #include <boost/range/irange.hpp> #include <boost/range/algorithm/for_each.hpp> #include <boost/range/adaptor/transformed.hpp> #include <boost/lexical_cast.hpp> namespace fw = boost::flyweights; struct compute_fibonacci; typedef fw::flyweight< fw::key_value<unsigned long int, compute_fibonacci>, fw::no_tracking > fibonacci; struct compute_fibonacci{ compute_fibonacci(unsigned long int n) : result( n == 0 ? 0 : n == 1 ? 1 : fibonacci(n-1).get() + fibonacci(n-2).get() ){} operator unsigned long int() const{ return result; } private: unsigned long int result; }; std::string fizz_buzz(unsigned long int n){ return n % 15 == 0 ? "FizzBuzz" : n % 3 == 0 ? "Fizz" : n % 5 == 0 ? "Buzz" : boost::lexical_cast<std::string>(n); } int main(){ namespace phx = boost::phoenix; using phx::arg_names::arg1; using boost::adaptors::transformed; int size = 60; boost::for_each( boost::irange(1, size) |transformed(phx::bind(&fibonacci::get, phx::construct<fibonacci>(arg1))) |transformed(phx::bind(&fizz_buzz, arg1)), std::cout << arg1 << ", " ); return 0; }
[出力]
1, 1, 2, Fizz, Buzz, 8, 13, Fizz, 34, Buzz, 89, Fizz, 233, 377, Buzz, Fizz, 1597, 2584, 4181, FizzBuzz, 10946, 17711, 28657, Fizz, Buzz, 121393, 196418, Fizz, 514229, Buzz, 1346269, Fizz, 3524578, 5702887, Buzz, Fizz, 24157817, 39088169, 63245986, FizzBuzz, 165580141, 267914296, 433494437, Fizz, Buzz, 1836311903, 2971215073, Buzz, Fizz, 3996334433, Buzz, 2886509027, 1776683621, Fizz, 2144908973, Buzz, Fizz, 2876210327, 3239286329,
Boost.Flyweight でこんな事ができるのかー。
Boost には知らないことがまだまだ多い。