ネタ元 → FizzBuzzを解いてみた
FizzBuzz問題を試験官が頭抱えるくらいにワザとややこしく解け、と。
ふははは、おもしれぇぢゃねぇか。
TBBにはパイプラインを簡単に作れるクラスが用意されています。
コレ使って、FizzBuzz検出フィルタ/Fizz検出フィルタ/Buzz検出フィルタを
パイプラインに載せてわしゃわしゃわしゃーと動かしてみるなり。
/*
cl -EHsc -MD -I<TBB_INC_DIR> fizzbuzz.cpp -link -libpath:<TBB_LIB_DIR>
*/
#include <iostream>
#include <list>
#include <tbb/tbb.h>
tbb::mutex mutex;
/*
* listから要素を取り出して後段に送る
*/
class entry : public tbb::filter {
std::list<int>& list_;
public:
entry(std::list<int>& l) : tbb::filter(true), list_(l) {}
void* operator()(void*) {
if ( list_.empty() ) return 0;
int* n = new int(list_.front());
list_.pop_front();
return n;
}
};
/*
* 前段からもらった数 n が割り切れたら -1、
* さもなくば n を後段に送る
*/
class fizzbuzz_filter : public tbb::filter {
int mod_;
std::string str_;
public:
fizzbuzz_filter(int m, std::string s) : tbb::filter(true), mod_(m), str_(s) {}
void* operator()(void* p) {
int* n = static_cast<int*>(p);
if ( *n < 0 ) {
return n;
} else
if ( *n % mod_ ) {
return p;
} else {
tbb::mutex::scoped_lock lock(mutex);
std::cout << str_ << '(' << *n << ") " << std::flush;
*n = -1;
return n;
}
}
};
/*
* 前段からもらった数 n が 負でなければ出力する
*/
class terminator : public tbb::filter {
public:
terminator() : tbb::filter(true) {}
void* operator()(void* p) {
int* n = static_cast<int*>(p);
if ( *n > 0 ) {
tbb::mutex::scoped_lock lock(mutex);
std::cout << *n << ' ' << std::flush;
}
delete n;
return 0;
}
};
int main() {
// 入力系列とパイプラインを生成
std::list<int> source;
for ( int i = 1; i <= 100; ++i ) {
source.push_back(i);
}
tbb::pipeline pipeline;
// 初段をパイプラインに接続
entry first(source);
pipeline.add_filter(first);
// FizzBuzz, Fizz, Buzz をパイプラインに接続
fizzbuzz_filter fizzbuzz(15,"FizzBuzz");
pipeline.add_filter(fizzbuzz);
fizzbuzz_filter fizz(3,"Fizz");
pipeline.add_filter(fizz);
fizzbuzz_filter buzz(5,"Buzz");
pipeline.add_filter(buzz);
// 最終段をパイプラインに接続
terminator last;
pipeline.add_filter(last);
// runの引数を2以上にすると複数のパイプラインが
// 並行動作する(ので出力順が乱れます)
pipeline.run(1);
pipeline.clear();
}
TBBおもろいなりー♪