QOJ.ac
QOJ
ID | 题目 | 提交者 | 结果 | 用时 | 内存 | 语言 | 文件大小 | 提交时间 | 测评时间 |
---|---|---|---|---|---|---|---|---|---|
#297670 | #4859. Poker Game: Construction | ucup-team087# | WA | 0ms | 3740kb | C++14 | 19.6kb | 2024-01-04 22:25:42 | 2024-01-04 22:25:42 |
Judging History
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 %s\n", tos(ans[1 + z]).c_str());
} else {
puts("NO");
}
}
}
#ifndef LOCAL
break;
#endif
}
return 0;
}
詳細信息
Test #1:
score: 0
Wrong Answer
time: 0ms
memory: 3740kb
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:
wrong answer Token parameter [name=s] equals to "[4C,", doesn't correspond to pattern "[23456789TJQKA][SHCD]" (test case 1)