第五回オフラインリアルタイムどう書くの問題(C++)

問題：http://nabetani.sakura.ne.jp/hena/ord5dahimi/
解答例：http://qiita.com/Nabetani/items/5c10c132e1f78131563f

```cpp
#define TEST(a,b) do{if((a)!=(b)){std::cout << "[" <<__LINE__ << "]   " << (a) << " != " << (b) << std::endl;}}while(0)

#include <iostream>
#include <string>
#include <vector>

using namespace std;

namespace
{
struct Card
{
  // カードの値は強さ順にしたいので0→3, 12→2, 13→Joとする
  int c; //場に出てるカードの値
  size_t n; //場に出てるカードの枚数
  vector<string> m[14]; //手持ちカード強さ順
  bool Joker() const
  {
    return 0 < m[13].size();
  }
};

int GetNumberImpl(char c)
{
  if ('1' <= c && c <= '9')
  {
    return c - '0';
  }
  switch (c)
  {
  default:
    return 14;
  case 'T':
    return 10;
  case 'J':
    return 11;
  case 'Q':
    return 12;
  case 'K':
    return 13;
  case 'A':
    return 1;
  }
}

int GetNumber(char c)
{
  int number = GetNumberImpl(c);
  if (number == 14)
  {
    return 13;
  }
  if (number <= 2)
  {
    return number + 10;
  }
  return number - 3;
}

Card GetCard(string const & src)
{
  Card dest =
  { 0 };
  string::const_iterator it = src.begin();
  for (; *it != ','; it += 2)
  {
    int number = GetNumber(*(it + 1));
    if (number != 13 || dest.n == 0)
    {
      dest.c = number;
    }
    ++dest.n;
  }
  ++it;
  for (; it != src.end(); it += 2)
  {
    int number = GetNumber(*(it + 1));
    char text[3] =
    { *it, *(it + 1) };
    dest.m[number].push_back(text);
  }
  return dest;
}

void GetOutText(int n, int m, int i, vector<string> const & src, bool joker,
    string & text, string & tmp)
{
  tmp += src[i];
  if (n == m)
  {
    text += tmp + ",";
  }
  if (joker && n == m + 1)
  {
    text += "Jo" + tmp + ",";
  }
  for (size_t j = i + 1; m + 1 <= n && j < src.size(); ++j)
  {
    GetOutText(n, m + 1, j, src, joker, text, tmp);
  }
}

string GetOutText(int n, vector<string> const & src, bool joker)
{
  string dest;
  for (size_t i = 0; i < src.size(); ++i)
  {
    string tmp;
    GetOutText(n, 1, i, src, joker, dest, tmp);
  }
  return 0 < dest.size() ? dest.substr(0, dest.size() - 1) : dest;
}

string calc(string const & src)
{
  Card const card = GetCard(src);
  string dest;
  for (size_t i = card.c + 1; i < 14; ++i)
  {
    if ((i < 13 || card.n == 1)
        && card.n <= card.m[i].size() + card.Joker() ? 1 : 0)
    {
      string text = GetOutText(card.n, card.m[i], card.Joker());
      if (text.size())
        dest += text + ",";
    }
  }
  return dest.size() == 0 ? "-" : dest.substr(0, dest.size() - 1);
}
}

int main(int argc, char const* argv[])
{
  TEST( calc("DJ,"), "-");
  TEST( calc("H7,HK"), "HK");
  TEST( calc("S3,D4D2"), "D4,D2");
  TEST( calc("S9,C8H4"), "-");
  TEST( calc("S6,S7STCK"), "CK,ST,S7");
  TEST( calc("H4,SAS8CKH6S4"), "S8,CK,H6,SA");
  TEST( calc("ST,D6S8JoC7HQHAC2CK"), "Jo,C2,CK,HA,HQ");
  TEST( calc("SA,HAD6S8S6D3C4H2C5D4CKHQS7D5"), "H2");
  TEST( calc("S2,D8C9D6HQS7H4C6DTS5S6C7HAD4SQ"), "-");
  TEST( calc("Jo,HAC8DJSJDTH2"), "-");
  TEST( calc("S4Jo,CQS6C9DQH9S2D6S3"), "DQCQ,D6S6,H9C9");
  TEST( calc("CTDT,S9C2D9D3JoC6DASJS4"), "JoC2,SJJo,DAJo");
  TEST( calc("H3D3,DQS2D6H9HAHTD7S6S7Jo"),
      "JoHA,JoD6,JoH9,D6S6,D7S7,JoS6,HTJo,JoDQ,S2Jo,JoD7,JoS7");
  TEST( calc("D5Jo,CQDAH8C6C9DQH7S2SJCKH5"), "CQDQ");
  TEST( calc("C7H7,S7CTH8D5HACQS8JoD6SJS5H4"),
      "HAJo,JoSJ,H8S8,H8Jo,CQJo,CTJo,JoS8");
  TEST( calc("SAHA,S7SKCTS3H9DJHJH7S5H2DKDQS4"), "-");
  TEST( calc("JoC8,H6D7C5S9CQH9STDTCAD9S5DAS2CT"),
      "CTDT,H9D9,S9D9,DACA,CTST,H9S9,DTST");
  TEST( calc("HTST,SJHJDJCJJoS3D2"),
      "DJCJ,SJDJ,JoHJ,CJHJ,SJJo,HJSJ,DJJo,JoCJ,JoD2,SJCJ,DJHJ");
  TEST( calc("C7D7,S8D8JoCTDTD4CJ"), "D8S8,JoS8,CTJo,DTJo,JoCJ,CTDT,D8Jo");
  TEST( calc("DJSJ,DTDKDQHQJoC2"), "JoDK,HQDQ,DQJo,C2Jo,JoHQ");
  TEST( calc("C3H3D3,CKH2DTD5H6S4CJS5C6H5S9CA"), "S5H5D5");
  TEST( calc("D8H8S8,CQHJCJJoHQ"), "JoCQHQ,JoHJCJ");
  TEST( calc("H6D6S6,H8S8D8C8JoD2H2"),
      "D2H2Jo,D8JoS8,D8S8C8,C8D8H8,JoC8S8,H8JoC8,S8H8C8,JoS8H8,C8JoD8,D8H8S8,D8JoH8");
  TEST( calc("JoD4H4,D3H3S3C3CADASAD2"), "DACASA");
  TEST( calc("DJHJSJ,SQDQJoHQCQC2CA"),
      "SQJoCQ,DQCQJo,JoSQHQ,SQCQHQ,DQHQSQ,HQDQCQ,HQDQJo,SQDQCQ,CQJoHQ,SQJoDQ");
  TEST( calc("H3D3Jo,D4SKH6CTS8SAS2CQH4HAC5DADKD9"), "HASADA");
  TEST( calc("C3JoH3D3,S2S3H7HQCACTC2CKC6S7H5C7"), "-");
  TEST( calc("H5C5S5D5,C7S6D6C3H7HAH6H4C6HQC9"), "C6D6S6H6");
  TEST( calc("H7S7C7D7,S5SAH5HAD5DAC5CA"), "SADACAHA");
  TEST( calc("D4H4S4C4,S6SAH6HAD6DAC6CAJo"),
      "C6H6S6D6,SAJoDACA,S6H6C6Jo,SACAJoHA,HADASAJo,HADAJoCA,CADAHASA,D6C6JoH6,S6D6C6Jo,H6JoS6D6");
  TEST( calc("DTCTSTHT,S3SQH3HQD3DQC3CQJo"),
      "HQSQJoDQ,SQCQDQJo,DQCQHQJo,SQHQJoCQ,CQDQHQSQ");
  TEST( calc("JoS8D8H8,S9DTH9CTD9STC9CAC2"), "H9C9D9S9");
  return 0;
}
```