QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#297672#4859. Poker Game: Constructionucup-team087#WA 230ms3780kbC++1419.6kb2024-01-04 22:26:262024-01-04 22:26:26

Judging History

你现在查看的是最新测评结果

  • [2024-01-04 22:26:26]
  • 评测
  • 测评结果:WA
  • 用时:230ms
  • 内存:3780kb
  • [2024-01-04 22:26:26]
  • 提交

answer

#include <cassert>
#include <cmath>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <bitset>
#include <complex>
#include <deque>
#include <functional>
#include <iostream>
#include <limits>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <sstream>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>

using namespace std;

using Int = long long;

template <class T1, class T2> ostream &operator<<(ostream &os, const pair<T1, T2> &a) { return os << "(" << a.first << ", " << a.second << ")"; };
template <class T> ostream &operator<<(ostream &os, const vector<T> &as) { const int sz = as.size(); os << "["; for (int i = 0; i < sz; ++i) { if (i >= 256) { os << ", ..."; break; } if (i > 0) { os << ", "; } os << as[i]; } return os << "]"; }
template <class T> void pv(T a, T b) { for (T i = a; i != b; ++i) cerr << *i << " "; cerr << endl; }
template <class T> bool chmin(T &t, const T &f) { if (t > f) { t = f; return true; } return false; }
template <class T> bool chmax(T &t, const T &f) { if (t < f) { t = f; return true; } return false; }
#define COLOR(s) ("\x1b[" s "m")


int bsr(int a) {
  return 31 - __builtin_clz(a);
}

// Returns the submask containing highest k bits set.
// Returns -1 instead if  popcnt(a) < k.
int highBits(int a, int k) {
  int b = 0;
  for (int i = 0; i < k; ++i) {
    if (!a) return -1;
    b |= 1 << (31 - __builtin_clz(a));
    a &= ~b;
  }
  return b;
}

constexpr char RANKS_STR[16] = "0123456789TJQKA";
constexpr char SUITS_STR[5] = "CDHS";
enum Poker {
  HIGH_CARD,
  ONE_PAIR,
  TWO_PAIR,
  THREE_OF_A_KIND,
  STRAIGHT,
  FLUSH,
  FULL_HOUSE,
  FOUR_OF_A_KIND,
  STRAIGHT_FLUSH,
};
constexpr char POKER_STR[9][20] = {
  "HIGH_CARD",
  "ONE_PAIR",
  "TWO_PAIR",
  "THREE_OF_A_KIND",
  "STRAIGHT",
  "FLUSH",
  "FULL_HOUSE",
  "FOUR_OF_A_KIND",
  "STRAIGHT_FLUSH",
};

// Parses a card in a format as "2C" or "C2".
// Returns  card = 4 (rank - 2) + suit  (2 <= rank <= 14)
int parseCard(const char *str) {
  int r, s;
  for (s = 0; s < 4; ++s) if (SUITS_STR[s] == str[1]) break;
  if (s < 4) {
    // "2C"
    for (r = 2; r < 15; ++r) if (RANKS_STR[r] == str[0]) break;
    assert(r < 15);
  } else {
    // "C2"
    for (s = 0; s < 4; ++s) if (SUITS_STR[s] == str[0]) break;
    assert(s < 4);
    for (r = 2; r < 15; ++r) if (RANKS_STR[r] == str[1]) break;
    assert(r < 15);
  }
  return (r - 2) << 2 | s;
}

// Read a card from standard input.
int readCard() {
  static char buf[3];
  scanf("%s", buf);
  return parseCard(buf);
}

// Transforms a card in a format as "2C" (or "C2" if rev).
string cardString(int card, bool rev = false) {
  const int r = card / 4 + 2, s = card % 4;
  return rev ? (string() + SUITS_STR[s] + RANKS_STR[r]) : (string() + RANKS_STR[r] + SUITS_STR[s]);
}

// Returns the best poker hand with the tie-breaker in [0, 2^20).
//   cards must be distinct.
pair<Poker, int> poker(const vector<int> &cards) {
  assert(cards.size() >= 5);
  // a: ranks for all, bs[suit]: ranks, cs[rank]: count, ds[count]: ranks
  int a = 0, bs[4] = {}, cs[15] = {}, ds[5] = {};
  for (const int card : cards) { const int r = (card >> 2) + 2, s = card & 3; a |= bs[s] |= 1 << r; ++cs[r]; }
  for (int r = 2; r < 15; ++r) ds[cs[r]] |= 1 << r;
  // 8. STRAIGHT_FLUSH: highest (5 for A2345)
  {
    int straightFlush = 0;
    for (int s = 0; s < 4; ++s) straightFlush |= bs[s] & bs[s] << 1 & bs[s] << 2 & bs[s] << 3 & (bs[s] << 4 | bs[s] >> 14 << 5);
    if (straightFlush) return make_pair(STRAIGHT_FLUSH, bsr(straightFlush));
  }
  // 7. FOUR_OF_A_KIND: quadruple, other card
  if (ds[4]) {
    const int r4 = bsr(ds[4]);
    return make_pair(FOUR_OF_A_KIND, r4 << 4 | bsr(a ^ 1 << r4));
  }
  // 6. FULL_HOUSE: triple, pair
  if (ds[3]) {
    const int r3 = bsr(ds[3]);
    const int d = (ds[3] ^ 1 << r3) | ds[2];
    if (d) {
      const int r2 = bsr(d);
      return make_pair(FULL_HOUSE, r3 << 4 | r2);
    }
  }
  // 5. FLUSH: 5 highest cards
  {
    int flush = -1;
    for (int s = 0; s < 4; ++s) { const int h = highBits(bs[s], 5); if (flush < h) flush = h; }
    if (flush >= 0) return make_pair(FLUSH, flush);
  }
  // 4. STRAIGHT: highest (5 for A2345)
  {
    const int straight = a & a << 1 & a << 2 & a << 3 & (a << 4 | a >> 14 << 5);
    if (straight) return make_pair(STRAIGHT, bsr(straight));
  }
  // 3. THREE_OF_A_KIND: triple, 2 highest other cards
  if (ds[3]) {
    const int r3 = bsr(ds[3]);
    return make_pair(THREE_OF_A_KIND, r3 << 16 | highBits(a ^ 1 << r3, 2));
  }
  // 2. TWO_PAIR: larger pair, smaller pair, other card
  // 1. ONE_PAIR: pair, 3 highest other cards
  if (ds[2]) {
    const int r2 = bsr(ds[2]);
    const int d = ds[2] ^ 1 << r2;
    if (d) {
      const int r22 = bsr(d);
      return make_pair(TWO_PAIR, r2 << 8 | r22 << 4 | bsr(a ^ 1 << r2 ^ 1 << r22));
    }
    return make_pair(ONE_PAIR, r2 << 16 | highBits(a ^ 1 << r2, 3));
  }
  // 0. HIGH_CARD: 5 highest cards
  return make_pair(HIGH_CARD, highBits(a, 5));
}

////////////////////////////////////////////////////////////////////////////////


string tos(const vector<int> &C) {
  ostringstream os;
  os << "[";
  for (int i = 0; i < (int)C.size(); ++i) {
    if (i) os << ", ";
    os << cardString(C[i]);
  }
  os << "]";
  return os.str();
}

int simulate(int A0, int A1, int B0, int B1, const vector<int> &C) {
  constexpr int THREE[6 + 1] = {1, 3, 9, 27, 81, 243, 729};
  assert(C.size() == 6);
  vector<int> dp(THREE[6], 2);
  for (int p = THREE[6]; --p >= 0; ) {
    vector<int> xs(6);
    for (int i = 0; i < 6; ++i) xs[i] = p / THREE[i] % 3;
    int cnt[3] = {};
    for (int i = 0; i < 6; ++i) ++cnt[xs[i]];
    if (cnt[1] == 3 && cnt[2] == 3) {
      vector<int> as{A0, A1}, bs{B0, B1};
      for (int i = 0; i < 6; ++i) ((xs[i] == 1) ? as : bs).push_back(C[i]);
      const auto resA = poker(as);
      const auto resB = poker(bs);
      dp[p] = (resA > resB) ? +1 : (resA < resB) ? -1 : 0;
    } else if (cnt[1] == cnt[2]) {
      // A
      dp[p] = -1;
      for (int i = 0; i < 6; ++i) if (!xs[i]) chmax(dp[p], dp[p + THREE[i]]);
    } else if (cnt[1] == cnt[2] + 1) {
      // B
      dp[p] = +1;
      for (int i = 0; i < 6; ++i) if (!xs[i]) chmin(dp[p], dp[p + 2 * THREE[i]]);
    }
  }
  return dp[0];
}

vector<vector<int>> brute(int A0, int A1, int B0, int B1) {
// cerr<<COLOR("33")<<"[brute] "<<cardString(A0)<<" "<<cardString(A1)<<" "<<cardString(B0)<<" "<<cardString(B1)<<COLOR()<<endl;
  constexpr int NUM_TRIES = 100;
  mt19937_64 rng(58);
  vector<vector<int>> ans(3);
  for (int phase = 0; phase < 3; ++phase) {
    int numTries = 0;
    for (int iter = 0; ; ++iter) {
      if (phase == 0 && ans[1 + (+1)].size()) break;
      if (phase == 1 && ans[1 + (-1)].size()) break;
      if (phase == 2 && ans[1 + 0   ].size()) break;
      vector<int> C(6);
      if (phase == 0) {
        // random
        for (int i = 0; i < 6; ++i) {
          C[i] = rng() % 52;
        }
      } else if (phase == 1) {
        // in favor of Bob
        for (int i = 0; i < 6; ++i) {
          C[i] = (rng() & 1)
            ? (((rng() & 1) ? B1 : B0) ^ (1 + rng() % 3))
            : (rng() % 52);
        }
      } else if (phase == 2) {
        // in favor of Draw
        int cnt[13] = {};
        ++cnt[A0 >> 2];
        ++cnt[A1 >> 2];
        --cnt[B0 >> 2];
        --cnt[B1 >> 2];
        C.clear();
        for (int r = 0; r < 13; ++r) {
          for (int i = abs(cnt[r]); --i >= 0; ) {
            C.push_back(r << 2 | (rng() & 3));
          }
        }
        for (; C.size() < 6; ) {
          const int r = rng() % 13;
          C.push_back(r << 2 | (rng() & 3));
          C.push_back(r << 2 | (rng() & 3));
        }
        assert((int)C.size() == 6);
      } else {
        break;
      }
      set<int> ss{A0, A1, B0, B1};
      ss.insert(C.begin(), C.end());
      if (ss.size() == 10) {
        const int res = simulate(A0, A1, B0, B1, C);
        // cerr << res << " " << C << endl;
        ans[1 + res] = C;
        if (++numTries >= NUM_TRIES) {
          break;
        }
      }
    }
  }
  /*
  for (const int z : {+1, -1, 0}) {
    if (ans[1 + z].size()) {
      printf("YES");
      for (const int c : ans[1 + z]) {
        printf(" %s", cardString(c).c_str());
      }
      puts("");
    } else {
      puts("NO");
    }
  }
  */
  return ans;
}

int other(int A, int B, int k) {
  for (int u = 1; u < 4; ++u) if ((A ^ u) != B) {
    if (!k--) return A ^ u;
  }
  assert(false);
}

vector<vector<int>> solve(int A0, int A1, int B0, int B1) {
  if ((A0>>2) > (A1>>2)) swap(A0, A1);
  if ((B0>>2) > (B1>>2)) swap(B0, B1);
// cerr<<COLOR("33")<<"[solve] "<<cardString(A0)<<" "<<cardString(A1)<<" "<<cardString(B0)<<" "<<cardString(B1)<<COLOR()<<endl;
  const int a0 = A0 >> 2, a1 = A1 >> 2;
  const int b0 = B0 >> 2, b1 = B1 >> 2;
  int fs[13] = {};
  fs[a0] |= 1 << 0;
  fs[a1] |= 1 << 1;
  fs[b0] |= 1 << 2;
  fs[b1] |= 1 << 3;
  vector<vector<int>> ans(3);
  auto &alice = ans[1 + (+1)];
  auto &bob   = ans[1 + (-1)];
  auto &draw  = ans[1 + 0   ];
  {
    set<int> used{A0, A1, B0, B1};
    for (const int r : {a0, a1}) if ((fs[r] & 3) >= (fs[r] >> 2)) {
      for (int s = 0; s < 4; ++s) {
        const int c = r << 2 | s;
        if (used.insert(c).second) {
          alice.push_back(c);
        }
      }
    }
    if (alice.size() > 3) alice.resize(3);
    for (int r = 13; --r >= 0; ) if (!(fs[r] >> 2)) {
      for (int s = 0; s < 4; ++s) {
        const int c = r << 2 | s;
        if (used.insert(c).second) {
          alice.push_back(c);
          break;
        }
      }
    }
    assert(alice.size() >= 6);
    alice.resize(6);
  }
  if (a0 == a1) {
    if (b0 == b1) {
      ///////////////////////////////////////////////////// a0 == a1 && b0 == b1
      if (b0 < a0) {
        for (int r0 = 0; r0 < 13; ++r0) if (!fs[r0]) {
          for (int r1 = r0 + 1; r1 < 13; ++r1) if (!fs[r1]) {
            bob = {other(B0,B1,0), other(B0,B1,1), r0<<2|0, r0<<2|1, r1<<2|2, r1<<2|3};
            break;
          }
          break;
        }
      } else if (b0 == a0) {
        for (int r0 = 0; r0 < 13; ++r0) if (!fs[r0]) {
          for (int r1 = r0 + 1; r1 < 13; ++r1) if (!fs[r1]) {
            for (int r2 = r1 + 1; r2 < 13; ++r2) if (!fs[r2]) {
              draw = {r0<<2|0, r0<<2|1, r1<<2|0, r1<<2|1, r2<<2|2, r2<<2|3};
              break;
            }
            break;
          }
          break;
        }
      } else if (a0 < b0) {
        for (int r0 = 0; r0 < 13; ++r0) if (!fs[r0]) {
          for (int r1 = r0 + 1; r1 < 13; ++r1) if (!fs[r1]) {
            bob = {other(B0,B1,0), other(B0,B1,1), r0<<2|0, r0<<2|1, r1<<2|2, r1<<2|3};
            break;
          }
          break;
        }
      } else {
        assert(false);
      }
    } else {
      ///////////////////////////////////////////////////// a0 == a1 && b0 != b1
      if (a0 < b0) {
        bob = {B0^1, B0^2, B0^3, B1^1, B1^2, B1^3};
      } else if (a0 == b0) {
        for (int r0 = 0; r0 < 13; ++r0) if (!fs[r0]) {
          for (int r1 = r0 + 1; r1 < 13; ++r1) if (!fs[r1]) {
            for (int r2 = r1 + 1; r2 < 13; ++r2) if (!fs[r2]) {
              bob = {B1^1, B1^2, r0<<2|0, r0<<2|1, r1<<2|2, r2<<2|3};
              break;
            }
            break;
          }
          break;
        }
        for (int r = 0; r < 13; ++r) if (!fs[r]) {
          draw = {A0^A1^B0, B1^1, B1^2, B1^3, r<<2|0, r<<2|1};
          break;
        }
      } else if (b0 < a0 && a0 < b1) {
        bob = {B0^1, B0^2, B0^3, B1^1, B1^2, B1^3};
      } else if (a0 == b1) {
        if (a0 != 12) {
          bob = {B0^1, B0^2, B0^3, 12<<2|0, 12<<2|1, 12<<2|2};
        } else if ((B0 & 3) == (B1 & 3)) {
          for (int r = 0; r < 13; ++r) if (!fs[r]) {
            bob.push_back(r << 2 | (B0 & 3));
            if (bob.size() == 6) break;
          }
        }
      } else if (b1 < a0) {
        bob = {B0^1, B0^2, B0^3, B1^1, B1^2, B1^3};
      } else {
        assert(false);
      }
    }
  } else {
    if (b0 == b1) {
      ///////////////////////////////////////////////////// a0 != a1 && b0 == b1
      if (b0 < a0) {
        for (int r = 0; r < 13; ++r) if (!fs[r]) {
          bob = {A0^1, A1^1, other(B0,B1,0), other(B0,B1,1), r<<2|0, r<<2|1};
          break;
        }
      } else if (b0 == a0) {
        for (int r0 = 0; r0 < 13; ++r0) if (!fs[r0]) {
          for (int r1 = r0 + 1; r1 < 13; ++r1) if (!fs[r1]) {
            bob = {A0^B0^B1, r0<<2|0, r0<<2|1, r0<<2|2, r1<<2|2, r1<<2|3};
            break;
          }
          break;
        }
        for (int r0 = 0; r0 < 13; ++r0) if (!fs[r0]) {
          for (int r1 = r0 + 1; r1 < 13; ++r1) if (!fs[r1]) {
            draw = {A0^B0^B1, A1^1, r0<<2|0, r0<<2|1, r1<<2|2, r1<<2|3};
            break;
          }
          break;
        }
      } else if (a0 < b0 && b0 < a1) {
        /*
        for (int r0 = 0; r0 < 13; ++r0) if (!fs[r0]) {
          // for (int r1 = r0 + 1; r1 < 13; ++r1) if (!fs[r1]) {
          for (int r1 = 13; --r1 > r0; ) if (!fs[r1]) {
            bob = {other(B0,B1,0), other(B0,B1,1), r0<<2|0, r0<<2|1, r1<<2|2, r1<<2|3};
            break;
          }
          break;
        }
        */
        for (int r = 0; r < 13; ++r) if (!fs[r]) {
          bob = {A0^1, A1^1, other(B0,B1,0), other(B0,B1,1), r<<2|0, r<<2|1};
          break;
        }
      } else if (b0 == a1) {
        for (int r0 = 0; r0 < 13; ++r0) if (!fs[r0]) {
          for (int r1 = r0 + 1; r1 < 13; ++r1) if (!fs[r1]) {
            bob = {A1^B0^B1, r0<<2|0, r0<<2|1, r0<<2|2, r1<<2|2, r1<<2|3};
            break;
          }
          break;
        }
        for (int r = 0; r < 13; ++r) if (!fs[r]) {
          draw = {A0^1, A0^2, A0^3, A1^B0^B1, r<<2|0, r<<2|1};
          break;
        }
      } else if (a1 < b0) {
        for (int r = 0; r < 13; ++r) if (!fs[r]) {
          bob = {A0^1, A1^1, other(B0,B1,0), other(B0,B1,1), r<<2|0, r<<2|1};
          break;
        }
      } else {
        assert(false);
      }
    } else {
      ///////////////////////////////////////////////////// a0 != a1 && b0 != b1
      if (a0 == b0 && a1 == b1) {
        if ((B0 & 3) == (B1 & 3)) {
          for (int r = 0; r < 13; ++r) if (!fs[r]) {
            bob.push_back(r << 2 | (B0 & 3));
            if (bob.size() == 6) break;
          }
        }
        for (int r0 = 0; r0 < 13; ++r0) if (!fs[r0]) {
          for (int r1 = r0 + 1; r1 < 13; ++r1) if (!fs[r1]) {
            for (int r2 = r1 + 1; r2 < 13; ++r2) if (!fs[r2]) {
              draw = {r0<<2|0, r0<<2|1, r1<<2|0, r1<<2|1, r2<<2|2, r2<<2|3};
              break;
            }
            break;
          }
          break;
        }
      } else if (a0 == b0) {
        for (int r0 = 0; r0 < 13; ++r0) if (!fs[r0]) {
          for (int r1 = r0 + 1; r1 < 13; ++r1) if (!fs[r1]) {
            bob = {other(A0,B0,0), B1^1, B1^2, B1^3, r0<<2|0, r1<<2|1};
            break;
          }
          break;
        }
        draw = {other(A0,B0,0), other(A0,B0,1), A1^1, B1^1, B1^2, B1^3};
      } else if (a0 == b1) {
        for (int r = 0; r < 13; ++r) if (!fs[r]) {
          bob = {B0^1, B0^2, B0^3, r<<2|0, r<<2|1, r<<2|2};
          break;
        }
        for (int r = 0; r < 13; ++r) if (!fs[r]) {
          draw = {A1^1, B0^1, B0^2, B0^3, r<<2|0, r<<2|1};
          break;
        }
      } else if (a1 == b0) {
        for (int r = 0; r < 13; ++r) if (!fs[r]) {
          bob = {B1^1, B1^2, B1^3, r<<2|0, r<<2|1, r<<2|2};
          break;
        }
        // for (int r0 = 0; r0 < 13; ++r0) if (!fs[r0]) {
          // for (int r1 = r0 + 1; r1 < 13; ++r1) if (!fs[r1]) {
        // for (int r0 = 13; --r0 >= 0; ) if (!fs[r0]) {
          // for (int r1 = r0; --r1 >= 0; ) if (!fs[r1]) {
        for (int r0 = 0; r0 < 13; ++r0) if (!fs[r0]) {
          for (int r1 = 13; --r1 > r0; ) if (!fs[r1]) {
            draw = {A0^1, B1^1, r0<<2|0, r0<<2|1, r1<<2|2, r1<<2|3};
            break;
          }
          break;
        }
      } else if (a1 == b1) {
        for (int r = 0; r < 13; ++r) if (!fs[r]) {
          bob = {B0^1, B0^2, B0^3, r<<2|0, r<<2|1, r<<2|2};
          break;
        }
        for (int r = 0; r < 13; ++r) if (!fs[r]) {
          draw = {A0^1, B0^1, B0^2, B0^3, r<<2|0, r<<2|1};
          break;
        }
      } else if (a0 < a1 && a1 < b0 && b0 < b1) {
        bob = {B0^1, B0^2, B0^3, B1^1, B1^2, B1^3};
      } else if (a0 < b0 && b0 < a1 && a1 < b1) {
        bob = {B0^1, B0^2, B0^3, B1^1, B1^2, B1^3};
        for (int r = 0; r < 13; ++r) if (!fs[r]) {
          draw = {A0^1, A1^1, B0^1, B1^1, r<<2|0, r<<2|1};
          break;
        }
      } else if (a0 < b0 && b0 < b1 && b1 < a1) {
        bob = {B0^1, B0^2, B0^3, B1^1, B1^2, B1^3};
        draw = {A0^1, A1^1, B0^1, B1^1, B1^2, B1^3};
      } else if (b0 < a0 && a0 < a1 && a1 < b1) {
        bob = {B0^1, B0^2, B0^3, B1^1, B1^2, B1^3};
      } else if (b0 < a0 && a0 < b1 && b1 < a1) {
        bob = {B0^1, B0^2, B0^3, B1^1, B1^2, B1^3};
        draw = {A0^1, A1^1, B0^1, B0^2, B0^3, B1^1};
      } else if (b0 < b1 && b1 < a0 && a0 < a1) {
        bob = {B0^1, B0^2, B0^3, B1^1, B1^2, B1^3};
      } else {
        assert(false);
      }
    }
  }
  return ans;
}

void stress() {
  mt19937_64 rng(233);
  for (int iter = 1; ; ++iter) {
    int A0, A1, B0, B1;
    for (; ; ) {
      A0 = rng() % 52;
      A1 = (rng() & 1) ? (A0 ^ (1 + rng() % 3)) : (rng() % 52);
      B0 = rng() % 52;
      B1 = (rng() & 1) ? (B0 ^ (1 + rng() % 3)) : (rng() % 52);
      if (set<int>{A0, A1, B0, B1}.size() == 4) {
        break;
      }
    }
    const string input = cardString(A0) + " " + cardString(A1) + " " + cardString(B0) + " " + cardString(B1);
    const auto brt = brute(A0, A1, B0, B1);
    const auto slv = solve(A0, A1, B0, B1);
    
    for (const int z : {+1, -1, 0}) {
      const auto &C = slv[1 + z];
      if (C.size()) {
        assert(C.size() == 6);
        for (int i = 0; i < 6; ++i) {
          assert(0 <= C[i]); assert(C[i] < 52);
        }
        set<int> ss{A0, A1, B0, B1};
        ss.insert(C.begin(), C.end());
        assert(ss.size() == 10);
        const int res = simulate(A0, A1, B0, B1, C);
        if (res != z) {
          cerr << "FAIL " << iter << " " << z << " " << input << " " << tos(brt[1 + z]) << " " << tos(C) << ": " << res << endl;
        }
        assert(res == z);
        if (!brt[1 + z].size()) {
          cerr << "WAO " << iter << " " << z << " " << input << " " << tos(brt[1 + z]) << " " << tos(C) << endl;
        }
      } else {
        if (brt[1 + z].size()) {
          cerr << "FAIL " << iter << " " << z << " " << input << " " << tos(brt[1 + z]) << " " << tos(C) << endl;
        }
        assert(!brt[1 + z].size());
      }
    }
    
    if (!(iter & (iter - 1))) {
      cerr << "PASSED iter = " << iter << endl;
    }
  }
}

int main() {
  // stress();
  
  for (int numCases; ~scanf("%d", &numCases); ) { for (int caseId = 1; caseId <= numCases; ++caseId) {
    const int A0 = readCard();
    const int A1 = readCard();
    const int B0 = readCard();
    const int B1 = readCard();
    
    const auto ans = solve(A0, A1, B0, B1);
    for (const int z : {+1, -1, 0}) {
      if (ans[1 + z].size()) {
        printf("YES");
        for (const int c : ans[1 + z]) {
          printf(" %s", cardString(c).c_str());
        }
        puts("");
      } else {
        puts("NO");
      }
    }
  }
#ifndef LOCAL
  break;
#endif
  }
  return 0;
}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 100
Accepted
time: 1ms
memory: 3780kb

input:

3
JC 4H
TS 5D
7C 3C
7H TH
2D KH
4D JC

output:

YES 4C 4D 4S AC KC QC
YES 5C 5S 5H TH TD TC
YES 4S JD 5C TH TD TC
YES 3D 3H 3S AC KC QC
YES TS TC TD 2C 2D 2H
YES 3D TS 2C 2D AH AS
YES 2C 2H 2S AC QC TC
YES 4C 4S 4H JD JH JS
YES 2C KS 4C JD JH JS

result:

ok 3 test cases (3 test cases)

Test #2:

score: 0
Accepted
time: 0ms
memory: 3776kb

input:

2
AS AH
AC AD
AS AH
2S 2H

output:

YES KC QC JC TC 9C 8C
NO
YES 2C 2D 3C 3D 4H 4S
YES AC AD KC QC JC TC
YES 2D 2C 3C 3D 4H 4S
NO

result:

ok 2 test cases (2 test cases)

Test #3:

score: 0
Accepted
time: 0ms
memory: 3780kb

input:

1
3C 3D
3H 5S

output:

YES 3S AC KC QC JC TC
YES 5H 5D 2C 2D 4H 6S
YES 3S 5H 5D 5C 2C 2D

result:

ok 1 test cases (1 test case)

Test #4:

score: 0
Accepted
time: 0ms
memory: 3768kb

input:

1
9C KC
JC 5D

output:

YES 9D 9H 9S AC QC TC
YES 5C 5S 5H JD JH JS
YES 9D KD 5C 5S 5H JD

result:

ok 1 test cases (1 test case)

Test #5:

score: -100
Wrong Answer
time: 230ms
memory: 3660kb

input:

100000
6S 7C
KH 3S
5S 2D
AC TS
QD 6H
TC JD
5C AD
4S TH
AD 3S
JC 5S
TH QH
9S JH
AD JC
JS 7H
3S 9S
JC 6S
4D 7S
3S JH
AD JS
7D 4D
7D QS
QH JC
4H JS
7H TS
5D AD
3S 8D
AC TH
5D 3S
9H TD
TS 7D
7D 8C
AD 5H
7C QS
2C TH
QD AS
4S 2H
8D JS
9S 5H
2C TC
2D 5S
TD 2C
AS 2D
6H 6S
AC 2S
2C 8D
4C KS
JD 9D
2D AD
AS QH...

output:

YES 6C 6D 6H AC QC JC
YES 3H 3D 3C KS KC KD
NO
YES 2C 2H 2S KC QC JC
YES TH TD TC AD AH AS
NO
YES 6C 6D 6S AC KC 9C
YES TD TH TS JC JS JH
YES 6S QC TD JC JS JH
YES 5D 5H 5S KC QC JC
YES 4H 4D 4C TS TC TD
YES 5D AC 4H 4D 4C TS
YES 3C 3D 3H KC QC TC
YES 5H 5D 5C JD JH JS
YES 3H AC 5H JD JH JS
YES TC T...

result:

wrong answer Jury find answer but partcitant not. (test case 12110)