Project Euler Problem 1
10未満の自然数のうち, 3 もしくは 5 の倍数になっているものは 3, 5, 6, 9 の4つがあり, これらの合計は 23 になる.
同じようにして, 1000 未満の 3 か 5 の倍数になっている数字の合計を求めよ.
auto list = std::vector<int>(999); std::iota(list.begin(), list.end(), 1); auto new_iterator = std::remove_if(list.begin(), list.end(), [](int n) { return !(n % 3 == 0 || n % 5 == 0); }); auto result = std::accumulate(list.begin(), new_iterator, 0); printf("%d", result);
でも、「なっているもの」っていっているのに、「なっていないものを削除する」という問題を性格に表現していないこのコードはなんか気持ち悪い。
追記
リスト〔vector〕を用意しちゃうところが最高にダサいよね……。できれば、こんなふうに書きたい :
auto result = Range(1, 999) .filter([](int n) { return n % 3 == 0 || n % 5 == 0; }) .reduce([](int m, int n) { return m + n; });
そしてこうやって動いて欲しい :
int sum = 0; for(int i = 1; i <= 999; ++i) { if(i % 3 == 0 || i % 5 == 0) { sum += i; } }
できました
Rangeクラスは、reduceインターフェース及びfilterトレイトを実装します。filterトレイトは、フィルターをセットするだけです。reduceインターフェースは、2つの値をある関数を用いて計算し、その結果を返します。
テストケース
Range<int> range(1, 9); auto ret = range .filter([](const int& it) { return it % 3 == 0 || it % 5 == 0; }) .reduce(std::plus<int>()); printf("%d", ret); // 23
実装
using std::function; template <typename T> struct Reduce_i { virtual T reduce(function<T(const T&, const T&)> func) const = 0; }; template <typename SELF, typename T> struct Filter_t { Filter_t() : filter_function([](const T&) { return true; }) { } SELF& filter(function<bool(const T&)> filter_function) { this->filter_function = filter_function; return *static_cast<SELF*>(this); } bool operator()(const T& it) const { return filter_function(it); } protected: function<bool(const T&)> filter_function; }; template <typename T> class Range : Reduce_i<T>, public Filter_t<Range<T>, T> { public: Range(T m, T n) : m(m), n(n) { } T reduce(function<T(const T&, const T&)> func) const { T ret; T value; for(value = m; value <= n; ++value) { if(filter_function(value)) { ret = value; break; } } for(++value; value <= n; ++value) { if(filter_function(value)) { ret = func(ret, value); } } return ret; } private: T m; T n; };