JavaScript バージョンができたので、昔取った杵柄よろしく、C++ でも書いてみた。多分、コンパイル時に全て計算できているはず。
# include <iostream>
# include <tuple>
void dump_inner(int term) {
switch (term) {
case '+':
case '-':
std::cout << " " << static_cast<char>(term) << " ";
break;
case '#':
break;
default:
std::cout << term;
break;
}
}
template <typename Tuple, int N>
struct tuple_dumper {
static void dump(const Tuple& exp) {
tuple_dumper<Tuple, N-1>::dump(exp);
dump_inner(std::get<N-1>(exp));
}
};
template <typename Tuple>
struct tuple_dumper<Tuple, 1> {
static void dump(const Tuple& exp) {
dump_inner(std::get<0>(exp));
}
};
template <typename Tuple, int N>
struct calc_inner {
static std::tuple<int, int> calc(const Tuple& exp) {
std::tuple<int, int> ret = calc_inner<Tuple, N-2>::calc(exp);
auto tmp = std::get<0>(ret);
auto sum = std::get<1>(ret);
auto op = std::get<N-2>(exp);
auto val = std::get<N-1>(exp);
if (op == '+') return std::make_tuple(+val, sum + tmp);
if (op == '-') return std::make_tuple(-val, sum + tmp);
auto sign = (tmp > 0) ? 1 : -1;
return std::make_tuple(tmp * 10 + sign * val, sum);
}
};
template <typename Tuple>
struct calc_inner<Tuple, 1> {
static std::tuple<int, int> calc(const Tuple& exp) {
auto sum = std::get<0>(exp);
return std::make_tuple(sum, 0);
};
};
template <typename Tuple>
int calc(const Tuple& exp) {
std::tuple<int, int> ret = calc_inner<Tuple, std::tuple_size<Tuple>::value>::calc(exp);
return std::get<0>(ret) + std::get<1>(ret);
}
template <typename Tuple,
typename T>
void solve(const Tuple& result, const T& head) {
auto exp = std::tuple_cat(result, std::make_tuple(head));
if (calc(exp) == 100) {
tuple_dumper<decltype(exp), std::tuple_size<decltype(exp)>::value>::dump(exp);
std::cout << std::endl;
}
}
template <typename Tuple,
typename T,
typename ... Types>
void solve(const Tuple& result, const T& head, Types ... rest) {
for (auto op: { '+', '-', '#' }) {
solve(std::tuple_cat(result, std::make_tuple(head, op)), rest ...);
}
}
int main() {
solve(std::make_tuple(), 1, 2, 3, 4, 5, 6, 7, 8, 9);
}
書いてはみたものの、まあ、なんというか、なんの役にも立たないという気がする。再利用性もないしなぁ。
普通の再帰なら引数でなんとかできるところを、テンプレートメタプログラミングの再帰は戻り値で工夫しないといけないところがあり、ちょっと苦労した。
でも、Tuple の柔軟さはやはり素晴らしい。今のところ仕事で使う場面はないけど、いつか使える職場が見つかるといいなぁ。