#include <iostream>
#include <sstream>
#include <vector>
#include <tuple>
#include <cstdint>
#include <string>
#include <algorithm>
#include <map>
typedef std::tuple<std::uint64_t, std::uint64_t> RData;
typedef std::tuple<char, char> Data;
typedef std::vector<Data> DType;
typedef std::tuple<Data, Data> Pair;
typedef std::vector<Pair> PType;
DType GetInput(std::istream& is) {
char A = 0;
char B = 0;
DType D;
while (is >> A) {
if (!(is >> B)) break;
D.push_back({A,B});
}
return D;
}
template<int N>
bool IsMatch(DType& D) {
for (std::size_t i = 0; i < D.size(); i++) {
if (std::get<N>(D.front()) != std::get<N>(D[i])) return false;
}
return true;
}
bool Calc_rec(DType A,DType B, RData& R, std::size_t Depth) {
if (Depth == 0) {
if (IsMatch<0>(A))std::get<0>(R)++;
if (IsMatch<1>(A))std::get<1>(R)++;
return true;
}
if (!(IsMatch<0>(A) || IsMatch<1>(A))) return false;
for (std::size_t i = 0; i < B.size(); i++) {
A.push_back(B[i]);
B.erase(B.begin()+i);
Calc_rec(A, B, R, Depth - 1);
B.push_back(A.back());
A.pop_back();
std::sort(B.begin(), B.end());
}
return false;
}
template<int N>
std::size_t Count(DType& D) {
std::map<char, std::size_t> M;
std::size_t C = 0;
for (auto& o : D) {
M[std::get<N>(o)]++;
}
for (auto& o : M) {
C = std::max(o.second, C);
}
return C;
}
bool IsPair(Data& A, Data& B) {
return (std::get<0>(A) == std::get<0>(B)) || (std::get<1>(A) == std::get<1>(B));
}
bool Calc_rec2(DType A,PType P, PType& R) {
for (std::size_t i = 0; i < A.size(); i++) {
for (std::size_t j = i + 1; j < A.size(); j++) {
if (i == j)continue;
if (IsPair(A[i], A[j])) {
P.push_back({ A[i],A[j] });
A.erase(A.begin() + j);
A.erase(A.begin() + i);
Calc_rec2(A, P, R);
A.push_back(std::get<0>(P.back()));
A.push_back(std::get<1>(P.back()));
std::sort(A.begin(), A.end());
P.pop_back();
}
}
}
if (P.size() > R.size()) R = P;
return true;
}
PType Calc2(DType& D) {
PType R;
std::sort(D.begin(), D.end());
Calc_rec2(D, PType(), R);
return R;
}
RData Calc(DType& D) {
RData R{ 0,0 };
std::sort(D.begin(), D.end());
std::size_t A = Count<0>(D);
std::size_t B = Count<1>(D);
std::size_t C = std::max(A, B);
for (std::size_t i = 2; i<C+1; i++) {
Calc_rec(DType(), D, R, i);
}
return R;
}
bool Show(std::string& S, RData& R) {
std::cout << S << ':' << std::get<0>(R) << ',' << std::get<1>(R) << std::endl;
return true;
}
bool Show2(std::string& S, PType& R) {
std::cout << S << ':'<<R.size()<<'@';
for (auto& o : R) {
std::cout << '[' << std::get<0>(std::get<0>(o)) << std::get<1>(std::get<0>(o)) << ',' << std::get<0>(std::get<1>(o)) << std::get<1>(std::get<1>(o)) << ']';
}
std::cout << std::endl;
return true;
}
int main() {
{
std::string S = "DAD2HAH3";
std::stringstream ss(S);
DType D = GetInput(ss);
PType R = Calc2(D);
Show2(S, R);
}
{
std::string S = "DAD3D8D9DJH5H8HKSASKCAC5C8CK";
std::stringstream ss(S);
DType D = GetInput(ss);
PType R = Calc2(D);
Show2(S, R);
}
{
std::string S = "SAS2S3S4S5S6S7S8S9C2C3C4C5C6C7C8C9CT";
std::stringstream ss(S);
DType D = GetInput(ss);
PType R = Calc2(D);
Show2(S, R);
}
/** //**/
return 0;
}
/** /
int main() {
{
std::string S = "DAD2HAH3";
std::stringstream ss(S);
DType D = GetInput(ss);
RData R = Calc(D);
Show(S, R);
}
{
std::string S = "DAD3D8D9DJH5H8HKSASKCAC5C8CK";
std::stringstream ss(S);
DType D = GetInput(ss);
RData R = Calc(D);
Show(S, R);
}
{
std::string S = "SAS2S3S4S5S6S7S8S9C2C3C4C5C6C7C8C9CT";
std::stringstream ss(S);
DType D = GetInput(ss);
RData R = Calc(D);
Show(S, R);
}
return 0;
}
/**/
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8c3N0cmVhbT4KI2luY2x1ZGUgPHZlY3Rvcj4KI2luY2x1ZGUgPHR1cGxlPgojaW5jbHVkZSA8Y3N0ZGludD4KI2luY2x1ZGUgPHN0cmluZz4KI2luY2x1ZGUgPGFsZ29yaXRobT4KI2luY2x1ZGUgPG1hcD4KCnR5cGVkZWYgc3RkOjp0dXBsZTxzdGQ6OnVpbnQ2NF90LCBzdGQ6OnVpbnQ2NF90PiBSRGF0YTsKdHlwZWRlZiBzdGQ6OnR1cGxlPGNoYXIsIGNoYXI+IERhdGE7CnR5cGVkZWYgc3RkOjp2ZWN0b3I8RGF0YT4gRFR5cGU7CnR5cGVkZWYgc3RkOjp0dXBsZTxEYXRhLCBEYXRhPiBQYWlyOwp0eXBlZGVmIHN0ZDo6dmVjdG9yPFBhaXI+IFBUeXBlOwoKRFR5cGUgR2V0SW5wdXQoc3RkOjppc3RyZWFtJiBpcykgewoJY2hhciBBID0gMDsKCWNoYXIgQiA9IDA7CglEVHlwZSBEOwoKCXdoaWxlIChpcyA+PiBBKSB7CgkJaWYgKCEoaXMgPj4gQikpIGJyZWFrOwoJCUQucHVzaF9iYWNrKHtBLEJ9KTsKCX0KCglyZXR1cm4gRDsKfQoKdGVtcGxhdGU8aW50IE4+CmJvb2wgSXNNYXRjaChEVHlwZSYgRCkgewoJZm9yIChzdGQ6OnNpemVfdCBpID0gMDsgaSA8IEQuc2l6ZSgpOyBpKyspIHsKCQlpZiAoc3RkOjpnZXQ8Tj4oRC5mcm9udCgpKSAhPSBzdGQ6OmdldDxOPihEW2ldKSkgcmV0dXJuIGZhbHNlOwoJfQoJcmV0dXJuIHRydWU7Cn0KCmJvb2wgQ2FsY19yZWMoRFR5cGUgQSxEVHlwZSBCLCBSRGF0YSYgUiwgc3RkOjpzaXplX3QgRGVwdGgpIHsKCglpZiAoRGVwdGggPT0gMCkgewoJCWlmIChJc01hdGNoPDA+KEEpKXN0ZDo6Z2V0PDA+KFIpKys7CgkJaWYgKElzTWF0Y2g8MT4oQSkpc3RkOjpnZXQ8MT4oUikrKzsKCQlyZXR1cm4gdHJ1ZTsKCX0KCWlmICghKElzTWF0Y2g8MD4oQSkgfHwgSXNNYXRjaDwxPihBKSkpIHJldHVybiBmYWxzZTsKCglmb3IgKHN0ZDo6c2l6ZV90IGkgPSAwOyBpIDwgQi5zaXplKCk7IGkrKykgewoJCUEucHVzaF9iYWNrKEJbaV0pOwoJCUIuZXJhc2UoQi5iZWdpbigpK2kpOwoJCUNhbGNfcmVjKEEsIEIsIFIsIERlcHRoIC0gMSk7CgkJQi5wdXNoX2JhY2soQS5iYWNrKCkpOwoJCUEucG9wX2JhY2soKTsKCQlzdGQ6OnNvcnQoQi5iZWdpbigpLCBCLmVuZCgpKTsKCX0KCglyZXR1cm4gZmFsc2U7Cn0KCnRlbXBsYXRlPGludCBOPgpzdGQ6OnNpemVfdCBDb3VudChEVHlwZSYgRCkgewoJc3RkOjptYXA8Y2hhciwgc3RkOjpzaXplX3Q+IE07CglzdGQ6OnNpemVfdCBDID0gMDsKCWZvciAoYXV0byYgbyA6IEQpIHsKCQlNW3N0ZDo6Z2V0PE4+KG8pXSsrOwoJfQoKCWZvciAoYXV0byYgbyA6IE0pIHsKCQlDID0gc3RkOjptYXgoby5zZWNvbmQsIEMpOwoJfQoJcmV0dXJuIEM7Cn0KCmJvb2wgSXNQYWlyKERhdGEmIEEsIERhdGEmIEIpIHsKCXJldHVybiAoc3RkOjpnZXQ8MD4oQSkgPT0gc3RkOjpnZXQ8MD4oQikpIHx8IChzdGQ6OmdldDwxPihBKSA9PSBzdGQ6OmdldDwxPihCKSk7Cn0KCmJvb2wgQ2FsY19yZWMyKERUeXBlIEEsUFR5cGUgUCwgUFR5cGUmIFIpIHsKCWZvciAoc3RkOjpzaXplX3QgaSA9IDA7IGkgPCBBLnNpemUoKTsgaSsrKSB7CgkJZm9yIChzdGQ6OnNpemVfdCBqID0gaSArIDE7IGogPCBBLnNpemUoKTsgaisrKSB7CgkJCWlmIChpID09IGopY29udGludWU7CgkJCWlmIChJc1BhaXIoQVtpXSwgQVtqXSkpIHsKCQkJCVAucHVzaF9iYWNrKHsgQVtpXSxBW2pdIH0pOwoJCQkJQS5lcmFzZShBLmJlZ2luKCkgKyBqKTsKCQkJCUEuZXJhc2UoQS5iZWdpbigpICsgaSk7CgkJCQlDYWxjX3JlYzIoQSwgUCwgUik7CgkJCQlBLnB1c2hfYmFjayhzdGQ6OmdldDwwPihQLmJhY2soKSkpOwoJCQkJQS5wdXNoX2JhY2soc3RkOjpnZXQ8MT4oUC5iYWNrKCkpKTsJCgkJCQlzdGQ6OnNvcnQoQS5iZWdpbigpLCBBLmVuZCgpKTsKCQkJCVAucG9wX2JhY2soKTsKCQkJfQoJCX0KCX0KCWlmIChQLnNpemUoKSA+IFIuc2l6ZSgpKSBSID0gUDsKCXJldHVybiB0cnVlOwp9ClBUeXBlIENhbGMyKERUeXBlJiBEKSB7CglQVHlwZSBSOwoJc3RkOjpzb3J0KEQuYmVnaW4oKSwgRC5lbmQoKSk7CglDYWxjX3JlYzIoRCwgUFR5cGUoKSwgUik7CglyZXR1cm4gUjsKfQoKUkRhdGEgQ2FsYyhEVHlwZSYgRCkgewoJUkRhdGEgUnsgMCwwIH07CgoJc3RkOjpzb3J0KEQuYmVnaW4oKSwgRC5lbmQoKSk7CgoJc3RkOjpzaXplX3QgQSA9IENvdW50PDA+KEQpOwoJc3RkOjpzaXplX3QgQiA9IENvdW50PDE+KEQpOwoJc3RkOjpzaXplX3QgQyA9IHN0ZDo6bWF4KEEsIEIpOwoKCWZvciAoc3RkOjpzaXplX3QgaSA9IDI7IGk8QysxOyBpKyspIHsKCQlDYWxjX3JlYyhEVHlwZSgpLCBELCBSLCBpKTsKCX0KCQoJcmV0dXJuIFI7Cgp9Cgpib29sIFNob3coc3RkOjpzdHJpbmcmIFMsIFJEYXRhJiBSKSB7CglzdGQ6OmNvdXQgPDwgUyA8PCAnOicgPDwgc3RkOjpnZXQ8MD4oUikgPDwgJywnIDw8IHN0ZDo6Z2V0PDE+KFIpIDw8IHN0ZDo6ZW5kbDsKCXJldHVybiB0cnVlOwp9CmJvb2wgU2hvdzIoc3RkOjpzdHJpbmcmIFMsIFBUeXBlJiBSKSB7CglzdGQ6OmNvdXQgPDwgUyA8PCAnOic8PFIuc2l6ZSgpPDwnQCc7CgoJZm9yIChhdXRvJiBvIDogUikgewoJCXN0ZDo6Y291dCA8PCAnWycgPDwgc3RkOjpnZXQ8MD4oc3RkOjpnZXQ8MD4obykpIDw8IHN0ZDo6Z2V0PDE+KHN0ZDo6Z2V0PDA+KG8pKSA8PCAnLCcgPDwgc3RkOjpnZXQ8MD4oc3RkOjpnZXQ8MT4obykpIDw8IHN0ZDo6Z2V0PDE+KHN0ZDo6Z2V0PDE+KG8pKSA8PCAnXSc7Cgl9CglzdGQ6OmNvdXQgPDwgc3RkOjplbmRsOwoKCXJldHVybiB0cnVlOwp9CmludCBtYWluKCkgewoJCgl7CgkJc3RkOjpzdHJpbmcgUyA9ICJEQUQySEFIMyI7CgkJc3RkOjpzdHJpbmdzdHJlYW0gc3MoUyk7CgkJRFR5cGUgRCA9IEdldElucHV0KHNzKTsKCQlQVHlwZSBSID0gQ2FsYzIoRCk7CgkJU2hvdzIoUywgUik7Cgl9CgkKCXsKCQlzdGQ6OnN0cmluZyBTID0gIkRBRDNEOEQ5REpINUg4SEtTQVNLQ0FDNUM4Q0siOwoJCXN0ZDo6c3RyaW5nc3RyZWFtIHNzKFMpOwoJCURUeXBlIEQgPSBHZXRJbnB1dChzcyk7CgkJUFR5cGUgUiA9IENhbGMyKEQpOwoJCVNob3cyKFMsIFIpOwkKCX0KCQoJewoJCXN0ZDo6c3RyaW5nIFMgPSAiU0FTMlMzUzRTNVM2UzdTOFM5QzJDM0M0QzVDNkM3QzhDOUNUIjsKCQlzdGQ6OnN0cmluZ3N0cmVhbSBzcyhTKTsKCQlEVHlwZSBEID0gR2V0SW5wdXQoc3MpOwoJCVBUeXBlIFIgPSBDYWxjMihEKTsKCQlTaG93MihTLCBSKTsKCX0KCS8qKiAvLyoqLwoJcmV0dXJuIDA7Cn0KLyoqIC8KaW50IG1haW4oKSB7CgkKCXsKCQlzdGQ6OnN0cmluZyBTID0gIkRBRDJIQUgzIjsKCQlzdGQ6OnN0cmluZ3N0cmVhbSBzcyhTKTsKCQlEVHlwZSBEID0gR2V0SW5wdXQoc3MpOwoJCVJEYXRhIFIgPSBDYWxjKEQpOwoJCVNob3coUywgUik7Cgl9CgkKCXsKCQlzdGQ6OnN0cmluZyBTID0gIkRBRDNEOEQ5REpINUg4SEtTQVNLQ0FDNUM4Q0siOwoJCXN0ZDo6c3RyaW5nc3RyZWFtIHNzKFMpOwoJCURUeXBlIEQgPSBHZXRJbnB1dChzcyk7CgkJUkRhdGEgUiA9IENhbGMoRCk7CgkJU2hvdyhTLCBSKTsKCX0KCQoJewoJCXN0ZDo6c3RyaW5nIFMgPSAiU0FTMlMzUzRTNVM2UzdTOFM5QzJDM0M0QzVDNkM3QzhDOUNUIjsKCQlzdGQ6OnN0cmluZ3N0cmVhbSBzcyhTKTsKCQlEVHlwZSBEID0gR2V0SW5wdXQoc3MpOwoJCVJEYXRhIFIgPSBDYWxjKEQpOwoJCVNob3coUywgUik7Cgl9CgoJcmV0dXJuIDA7Cn0KLyoqLw==