0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

今更:1 時間以内に解けなければプログラマ失格問題 5 をテンプレートメタプログラミングで解いてみた

Last updated at Posted at 2016-05-08

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 の柔軟さはやはり素晴らしい。今のところ仕事で使う場面はないけど、いつか使える職場が見つかるといいなぁ。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?