#include <iostream>
#include <vector>
#include <cstdint>
#include <algorithm>
#include <random>
#include <iterator>
typedef std::vector<std::uint32_t> DType;
typedef std::vector<DType> Grid;
typedef std::vector<Grid> RType;
typedef std::vector < std::vector<DType>> Cube;
#ifdef _WIN32
#include <Windows.h>//ms windows os only.
void gotoxy(int X, int Y) {//カーソルを移動させる関数です。環境によってはエスケープシーケンスが使えるのでそれに置き換えることもできます。
return;
COORD Pos = { static_cast<SHORT>(X),static_cast<SHORT>(Y) };//WINDOWS定義の構造体です。
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), Pos);//windows定義の関数です。カーソルを移動します。
return;
}
#else
void gotoxy(int X, int Y) {
return;
}
#endif
Grid MakeProblem() {
Grid R{
{ 1,5,0,0,8,6,0,7,0, },
{ 7,0,8,9,0,0,0,0,0, },
{ 0,9,0,5,0,0,0,8,1, },
{ 9,0,0,0,0,8,1,0,6, },
{ 0,0,1,0,2,0,0,9,0, },
{ 0,7,5,6,0,0,2,0,0, },
{ 5,0,6,0,4,0,0,2,0, },
{ 3,0,0,1,0,2,5,0,0, },
{ 0,4,0,8,0,0,0,0,9, },
};
Grid R2{
{ 0,0,5,3,0,0,0,0,0, },
{ 8,0,0,0,0,0,0,2,0, },
{ 0,7,0,0,1,0,5,0,0, },
{ 4,0,0,0,0,5,3,0,0, },
{ 0,1,0,0,7,0,0,0,6, },
{ 0,0,3,2,0,0,0,8,0, },
{ 0,6,0,5,0,0,0,0,9, },
{ 0,0,4,0,0,0,0,3,0, },
{ 0,0,0,0,0,9,7,0,0, },
};
return R2;
}
Grid MakeProblem2() {
const std::uint64_t N = 30;
Grid G(9);
for (auto& o : G) {
o.resize(9);
}
std::random_device rd;
std::mt19937 mt(rd());
std::uniform_int_distribution<std::int64_t> ui(0, 8);
auto Check = [](Grid& g,std::uint64_t X, std::uint64_t Y,std::uint64_t V)->bool {
for (std::size_t i = 0; i < 9; i++) {
if (g[i][X] == V) return false;
}
for (std::size_t i = 0; i < 9; i++) {
if (g[Y][i] == V) return false;
}
return true;
};
auto Check2 = [](Grid& g,std::uint64_t X, std::uint64_t Y,std::uint64_t V)->bool {
std::uint64_t BX = X / 3;
std::uint64_t BY = Y / 3;
for (std::size_t i = 0; i < 3; i++) {
for (std::size_t j = 0; j < 3; j++) {
if (g[i + (BY * 3)][j + (BX * 3)] == V) return false;
}
}
return true;
};
std::uint64_t C = 0;
std::uint64_t X = 0;
std::uint64_t Y = 0;
for (std::int64_t i = 0; i < N; i++) {
X = ui(mt);
Y = ui(mt);
if ((Check(G, X, Y, C + 1) && Check2(G, X, Y, C + 1)&& G[Y][X] == 0) == true) {
G[Y][X] = C + 1;
}
else {
i--;
}
C++;
C %= 9;
}
return G;
}
Grid EraseNumber(Grid& G, std::uint64_t N) {
if (N > 80) return Grid();
std::random_device rd;
std::mt19937 mt(rd());
std::uniform_int_distribution<std::int64_t> ui(0, 8);
std::uint64_t X = 0;
std::uint64_t Y = 0;
for (std::int64_t i = 0; i < N; i++) {
X = ui(mt);
Y = ui(mt);
if (G[Y][X] != 0) {
G[Y][X] = 0;
}
else {
i--;
}
}
return G;
}
Grid MakeGrid() {
Grid G(9);
for (auto& o : G) {
o.assign(9, 0);
}
return G;
}
Cube MakeCube() {
DType D{ 1,2,3,4,5,6,7,8,9 };
Cube C(9);
for (auto& oo : C) {
oo.resize(9);
for (auto& o : oo) {
o = D;
}
}
return C;
}
Cube ReduceCube(const Cube& Cu, const Grid& P) {
Cube C = Cu;
for (std::size_t i = 0; i < P.size(); i++) {
for (std::size_t j = 0; j < P[i].size(); j++) {
if (P[i][j] != 0) {
C[i][j].clear();
C[i][j].push_back(P[i][j]);
}
}
}
for (std::size_t i = 0; i < C.size(); i++) {
for (std::size_t j = 0; j < C[i].size(); j++) {
if (C[i][j].size() != 1)continue;
for (std::size_t k = 0; k < P.size(); k++) {
if (C[i][k].size() == 1) continue;
auto it = std::find(C[i][k].begin(), C[i][k].end(), C[i][j][0]);
if (it != C[i][k].end()) {
C[i][k].erase(it);
}
}
for (std::size_t k = 0; k < P.size(); k++) {
if (C[k][j].size() == 1) continue;
auto it = std::find(C[k][j].begin(), C[k][j].end(), C[i][j][0]);
if (it != C[k][j].end()) {
C[k][j].erase(it);
}
}
}
}
std::size_t X = 0;
std::size_t Y = 0;
for (std::size_t Y = 0; Y < 3; Y++) {
for (std::size_t X = 0; X < 3; X++) {
for (std::size_t i = 0; i < 3; i++) {
for (std::size_t j = 0; j < 3; j++) {
if (C[Y * 3 + i][X * 3 + j].size() != 1)continue;
for (std::size_t k = 0; k < 3; k++) {
for (std::size_t l = 0; l < 3; l++) {
if (C[Y * 3 + k][X * 3 + l].size() == 1)continue;
auto it = std::find(C[Y * 3 + k][X * 3 + l].begin(), C[Y * 3 + k][X * 3 + l].end(), C[Y * 3 + i][X * 3 + j][0]);
if (it != C[Y * 3 + k][X * 3 + l].end()) {
C[Y * 3 + k][X * 3 + l].erase(it);
}
}
}
}
}
}
}
return C;
}
bool IsAnswer(Grid P) {
DType D;
for (std::size_t Y = 0; Y < 3; Y++) {
for (std::size_t X = 0; X < 3; X++) {
for (std::size_t i = 0; i < 3; i++) {
for (std::size_t j = 0; j < 3; j++) {
D.push_back(P[Y * 3 + i][X * 3 + j]);
}
}
std::sort(D.begin(), D.end());
D.erase(std::unique(D.begin(), D.end()), D.end());
if (D.size() != 9)return false;
}
}
for (std::size_t i = 0; i < P.size(); i++) {
D.clear();
for (std::size_t j = 0; j < P[i].size(); j++) {
D.push_back(P[i][j]);
}
std::sort(D.begin(), D.end());
D.erase(std::unique(D.begin(), D.end()), D.end());
if (D.size() != 9)return false;
}
for (std::size_t i = 0; i < P.size(); i++) {
D.clear();
for (std::size_t j = 0; j < P[i].size(); j++) {
D.push_back(P[j][i]);
}
std::sort(D.begin(), D.end());
D.erase(std::unique(D.begin(), D.end()), D.end());
if (D.size() != 9)return false;
}
return true;
}
Grid CubeToGrid(const Cube& C, const Grid G) {
Grid R = MakeGrid();
for (std::size_t i = 0; i < G.size(); i++) {
for (std::size_t j = 0; j < G[i].size(); j++) {
R[i][j] = C[i][j][G[i][j]];
}
}
return R;
}
Grid CubeToProblem(const Cube& C) {
Grid G = MakeGrid();
for (std::size_t i = 0; i < G.size(); i++) {
for (std::size_t j = 0; j < G[i].size(); j++) {
if (C[i][j].size() == 1) {
G[i][j] = C[i][j][0];
}
else {
G[i][j] = 0;
}
}
}
return G;
}
bool ShowList(Cube& C) {
std::size_t i = 1;
double D = 0;
for (auto& ooo : C) {
for (auto& oo : ooo) {
std::cout << '[' << i << ':';
i++;
D += oo.size();
for (auto& o : oo) {
std::cout << o << ',';
}
std::cout << ']';
}
std::cout << std::endl;
}
std::cout << D / 81.0 << std::endl;
return true;
}
bool Show(const Grid& G) {
for (auto& oo : G) {
for (auto& o : oo) {
std::cout << o;
}
std::cout << std::endl;
}
std::cout << std::endl;
std::cout << std::endl;
return true;
}
DType GetAntiIntersection(DType A ,const DType& B){//積集合を取り除く??
for (auto& o : B) {
auto it = std::find(A.begin(), A.end(), o);
if(it != A.end())A.erase(it);
}
return A;
}
bool IsHorizonValid(const Grid& G,std::size_t V) {//横方向検査
DType D;
for (std::size_t i = 0; i < G[V].size(); i++) {
if(G[V][i]!=0)D.push_back(G[V][i]);
}
std::sort(D.begin(), D.end());
D.erase(std::unique(D.begin(), D.end()), D.end());
return D.size() == 9 ? true : false;
}
DType GetHorizonUsing(const Grid& G,std::size_t V) {//横方向検査
DType D;
for (std::size_t i = 0; i < G[V].size(); i++) {
if(G[V][i]!=0) D.push_back(G[V][i]);
}
return D;
}
bool HaveHorizonZero(const Grid& G,std::size_t V) {//横方向検査
DType D;
for (std::size_t i = 0; i < G[V].size(); i++) {
if (G[V][i] == 0)return true;
}
return false;
}
bool IsVerticalValid(const Grid& G,std::size_t H) {//縦方向検査
DType D;
for (std::size_t i = 0; i < G.size(); i++) {
if(G[i][H]!= 0)D.push_back(G[i][H]);
}
std::sort(D.begin(), D.end());
D.erase(std::unique(D.begin(), D.end()), D.end());
return D.size() == 9 ? true : false;
}DType GetVerticalUsing(const Grid& G,std::size_t H) {//横方向検査
DType D;
DType T{ 0,1,2,3,4,5,6,7,8 };
for (std::size_t i = 0; i < G.size(); i++) {
if(G[i][H]!= 0)D.push_back(G[i][H]);
}
return D;
}
bool HaveVerticalZero(const Grid& G,std::size_t H) {//縦方向検査
DType D;
for (std::size_t i = 0; i < G.size(); i++) {
if (G[i][H] == 0)return true;
}
return false;
}
bool IsBlockValid(const Grid& G, std::size_t X, std::size_t Y) {//3x3検査
DType D;
for (std::size_t i = 0; i < 3; i++) {
for (std::size_t j = 0; j < 3; j++) {
if(G[Y*3+i][X*3+j] !=0)D.push_back(G[Y*3+i][X*3+j]);
}
}
std::sort(D.begin(), D.end());
D.erase(std::unique(D.begin(), D.end()), D.end());
return D.size() == 9 ? true : false;
}
DType GetBlockUsing(const Grid& G,std::size_t X,std::size_t Y) {//横方向検査
DType D;
for (std::size_t i = 0; i < 3; i++) {
for (std::size_t j = 0; j < 3; j++) {
if(G[Y*3+i][X*3+j] !=0) D.push_back(G[Y*3+i][X*3+j]);
}
}
return D;
}
bool HaveBlockNumber(const Grid& G, std::size_t X, std::size_t Y, std::size_t N) {//横方向検査
DType D;
for (std::size_t i = 0; i < 3; i++) {
for (std::size_t j = 0; j < 3; j++) {
if (G[Y * 3 + i][X * 3 + j] == N)return true;
}
}
return false;
}
bool HaveBlockZero(const Grid& G, std::size_t X, std::size_t Y) {//3x3検査
DType D;
for (std::size_t i = 0; i < 3; i++) {
for (std::size_t j = 0; j < 3; j++) {
if (G[Y * 3 + i][X * 3 + j] == 0)return true;
}
}
return false;
}
bool Search_r(Grid& G, int Deep, RType& R, std::size_t& C) {
C++;
gotoxy(11, 0);
// std::cout << C << std::endl;
if (Deep >= 81) {
gotoxy(0, 0);
//Show(G);
if (IsAnswer(G)) {
R.push_back(G);
std::cout << "find!!" << std::endl;
return true;
}
return false;
}
static const DType T{ 1,2,3,4,5,6,7,8,9 };
std::size_t MX = (Deep % 9) % 3;
std::size_t MY = (Deep % 9) / 3;
std::size_t BX = (Deep / 9) % 3;
std::size_t BY = (Deep / 9) / 3;
auto BU = GetBlockUsing(G, BX, BY);
auto HU = GetHorizonUsing(G, BY*3+MY);
auto VU = GetVerticalUsing(G, BX*3 + MX);
DType AI;
if (G[BY*3 + MY][BX*3 + MX] != 0) {
return Search_r(G, Deep + 1, R,C);
}
std::copy(BU.begin(), BU.end(), std::back_inserter(AI));
std::copy(HU.begin(), HU.end(), std::back_inserter(AI));
std::copy(VU.begin(), VU.end(), std::back_inserter(AI));
std::sort(AI.begin(), AI.end());
AI.erase(std::unique(AI.begin(), AI.end()), AI.end());
DType D = GetAntiIntersection(T, AI);
auto WG = G;
if (D.size() == 0) return false;
for (std::size_t i = 0; i < D.size(); i++) {
WG[BY*3 + MY][BX*3 + MX] = D[i];
gotoxy(0, 0);
// Show(WG);
Search_r(WG, Deep + 1, R,C);
}
return false;
}
bool Search(Grid& G, RType& R) {
int Deep = 0;
std::size_t C=0;
return Search_r(G, Deep, R, C);
}
RType MakeHoge(Grid G) {
Cube Cu = MakeCube();
Cube C = ReduceCube(Cu, G);
Grid V = MakeGrid();
RType R;
Grid B = G;
Grid D;
std::uint64_t Co = 0;
std::uint64_t Find = 1;
do {
D = B;
B = CubeToProblem(C);
C = ReduceCube(C, B);
} while (D != B);
gotoxy(0, 11);
// Show(B);
// ShowList(C);
auto A = CubeToProblem(C);
gotoxy(0, 11);
// Show(A);
Search(A, R);
std::sort(R.begin(), R.end());
R.erase(std::unique(R.begin(), R.end()), R.end());
gotoxy(0, 11);
return R;
}
int main() {
std::cout << "Generateing!" << std::endl;
F:
Grid G = MakeProblem2();
RType R;
R = MakeHoge(G);
if (R.size() == 0) goto F;
std::cout << "Show Problem Seed." << std::endl;
Show(G);
/*
for (auto& o : R) {
// gotoxy(0, 0);
Show(o);
}
*/
G = R[0];
std::cout << "Show Problem Seed2." << std::endl;
Show(G);
Grid A = EraseNumber(G, 45);
std::cout << "Number Erased!" << std::endl;
Show(A);
R=MakeHoge(A);
std::cout << "Show Answer!" << std::endl;
for (auto& o : R) {
// gotoxy(0, 0);
Show(o);
}
return 0;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8dmVjdG9yPgojaW5jbHVkZSA8Y3N0ZGludD4KI2luY2x1ZGUgPGFsZ29yaXRobT4KI2luY2x1ZGUgPHJhbmRvbT4KI2luY2x1ZGUgPGl0ZXJhdG9yPgoKdHlwZWRlZiBzdGQ6OnZlY3RvcjxzdGQ6OnVpbnQzMl90PiBEVHlwZTsKdHlwZWRlZiBzdGQ6OnZlY3RvcjxEVHlwZT4gR3JpZDsKdHlwZWRlZiBzdGQ6OnZlY3RvcjxHcmlkPiBSVHlwZTsKdHlwZWRlZiBzdGQ6OnZlY3RvciA8IHN0ZDo6dmVjdG9yPERUeXBlPj4gQ3ViZTsKI2lmZGVmIF9XSU4zMgojaW5jbHVkZSA8V2luZG93cy5oPi8vbXMgd2luZG93cyBvcyBvbmx5Lgp2b2lkIGdvdG94eShpbnQgWCwgaW50IFkpIHsvL+OCq+ODvOOCveODq+OCkuenu+WLleOBleOBm+OCi+mWouaVsOOBp+OBmeOAgueSsOWig+OBq+OCiOOBo+OBpuOBr+OCqOOCueOCseODvOODl+OCt+ODvOOCseODs+OCueOBjOS9v+OBiOOCi+OBruOBp+OBneOCjOOBq+e9ruOBjeaPm+OBiOOCi+OBk+OBqOOCguOBp+OBjeOBvuOBmeOAggoJcmV0dXJuOwoJQ09PUkQgUG9zID0geyBzdGF0aWNfY2FzdDxTSE9SVD4oWCksc3RhdGljX2Nhc3Q8U0hPUlQ+KFkpIH07Ly9XSU5ET1dT5a6a576p44Gu5qeL6YCg5L2T44Gn44GZ44CCCglTZXRDb25zb2xlQ3Vyc29yUG9zaXRpb24oR2V0U3RkSGFuZGxlKFNURF9PVVRQVVRfSEFORExFKSwgUG9zKTsvL3dpbmRvd3Plrprnvqnjga7plqLmlbDjgafjgZnjgILjgqvjg7zjgr3jg6vjgpLnp7vli5XjgZfjgb7jgZnjgIIKCXJldHVybjsKfQojZWxzZQp2b2lkIGdvdG94eShpbnQgWCwgaW50IFkpIHsKCXJldHVybjsKfQojZW5kaWYKCgpHcmlkIE1ha2VQcm9ibGVtKCkgewoJR3JpZCBSewoJCXsgMSw1LDAsMCw4LDYsMCw3LDAsIH0sCgkJeyA3LDAsOCw5LDAsMCwwLDAsMCwgfSwKCQl7IDAsOSwwLDUsMCwwLDAsOCwxLCB9LAoJCXsgOSwwLDAsMCwwLDgsMSwwLDYsIH0sCgkJeyAwLDAsMSwwLDIsMCwwLDksMCwgfSwKCQl7IDAsNyw1LDYsMCwwLDIsMCwwLCB9LAoJCXsgNSwwLDYsMCw0LDAsMCwyLDAsIH0sCgkJeyAzLDAsMCwxLDAsMiw1LDAsMCwgfSwKCQl7IDAsNCwwLDgsMCwwLDAsMCw5LCB9LAoJfTsKCQoJR3JpZCBSMnsKCQl7IDAsMCw1LDMsMCwwLDAsMCwwLCB9LAoJCXsgOCwwLDAsMCwwLDAsMCwyLDAsIH0sCgkJeyAwLDcsMCwwLDEsMCw1LDAsMCwgfSwKCQl7IDQsMCwwLDAsMCw1LDMsMCwwLCB9LAoJCXsgMCwxLDAsMCw3LDAsMCwwLDYsIH0sCgkJeyAwLDAsMywyLDAsMCwwLDgsMCwgfSwKCQl7IDAsNiwwLDUsMCwwLDAsMCw5LCB9LAoJCXsgMCwwLDQsMCwwLDAsMCwzLDAsIH0sCgkJeyAwLDAsMCwwLDAsOSw3LDAsMCwgfSwKfTsKCXJldHVybiBSMjsKCn0KCkdyaWQgTWFrZVByb2JsZW0yKCkgewoJY29uc3Qgc3RkOjp1aW50NjRfdCBOID0gMzA7CglHcmlkIEcoOSk7Cglmb3IgKGF1dG8mIG8gOiBHKSB7CgkJby5yZXNpemUoOSk7Cgl9CgoJc3RkOjpyYW5kb21fZGV2aWNlIHJkOwoJc3RkOjptdDE5OTM3IG10KHJkKCkpOwoJc3RkOjp1bmlmb3JtX2ludF9kaXN0cmlidXRpb248c3RkOjppbnQ2NF90PiB1aSgwLCA4KTsKCglhdXRvIENoZWNrID0gW10oR3JpZCYgZyxzdGQ6OnVpbnQ2NF90IFgsIHN0ZDo6dWludDY0X3QgWSxzdGQ6OnVpbnQ2NF90IFYpLT5ib29sIHsKCQlmb3IgKHN0ZDo6c2l6ZV90IGkgPSAwOyBpIDwgOTsgaSsrKSB7CgkJCWlmIChnW2ldW1hdID09IFYpIHJldHVybiBmYWxzZTsKCQl9CgkJZm9yIChzdGQ6OnNpemVfdCBpID0gMDsgaSA8IDk7IGkrKykgewoJCQlpZiAoZ1tZXVtpXSA9PSBWKSByZXR1cm4gZmFsc2U7CgkJfQoJCXJldHVybiB0cnVlOwoJfTsKCWF1dG8gQ2hlY2syID0gW10oR3JpZCYgZyxzdGQ6OnVpbnQ2NF90IFgsIHN0ZDo6dWludDY0X3QgWSxzdGQ6OnVpbnQ2NF90IFYpLT5ib29sIHsKCQlzdGQ6OnVpbnQ2NF90IEJYID0gWCAvIDM7CgkJc3RkOjp1aW50NjRfdCBCWSA9IFkgLyAzOwoJCQoJCWZvciAoc3RkOjpzaXplX3QgaSA9IDA7IGkgPCAzOyBpKyspIHsKCQkJZm9yIChzdGQ6OnNpemVfdCBqID0gMDsgaiA8IDM7IGorKykgewoJCQkJaWYgKGdbaSArIChCWSAqIDMpXVtqICsgKEJYICogMyldID09IFYpIHJldHVybiBmYWxzZTsKCQkJfQoJCX0KCgoJCXJldHVybiB0cnVlOwoJfTsKCXN0ZDo6dWludDY0X3QgQyA9IDA7CglzdGQ6OnVpbnQ2NF90IFggPSAwOwoJc3RkOjp1aW50NjRfdCBZID0gMDsKCWZvciAoc3RkOjppbnQ2NF90IGkgPSAwOyBpIDwgTjsgaSsrKSB7CgkJWCA9IHVpKG10KTsKCQlZID0gdWkobXQpOwoJCQoJCWlmICgoQ2hlY2soRywgWCwgWSwgQyArIDEpICYmIENoZWNrMihHLCBYLCBZLCBDICsgMSkmJiBHW1ldW1hdID09IDApID09IHRydWUpIHsKCQkJR1tZXVtYXSA9IEMgKyAxOwoKCQl9CgkJZWxzZSB7CgkJCWktLTsKCQl9CgkJCUMrKzsKCQkJQyAlPSA5OwoJfQoKCglyZXR1cm4gRzsKCgoKfQoKR3JpZCBFcmFzZU51bWJlcihHcmlkJiBHLCBzdGQ6OnVpbnQ2NF90IE4pIHsKCWlmIChOID4gODApIHJldHVybiBHcmlkKCk7CgoJc3RkOjpyYW5kb21fZGV2aWNlIHJkOwoJc3RkOjptdDE5OTM3IG10KHJkKCkpOwoJc3RkOjp1bmlmb3JtX2ludF9kaXN0cmlidXRpb248c3RkOjppbnQ2NF90PiB1aSgwLCA4KTsKCXN0ZDo6dWludDY0X3QgWCA9IDA7CglzdGQ6OnVpbnQ2NF90IFkgPSAwOwoJZm9yIChzdGQ6OmludDY0X3QgaSA9IDA7IGkgPCBOOyBpKyspIHsKCQlYID0gdWkobXQpOwoJCVkgPSB1aShtdCk7CgoJCWlmIChHW1ldW1hdICE9IDApIHsKCQkJR1tZXVtYXSA9IDA7CgkJfQoJCWVsc2UgewoJCQlpLS07CgkJfQoJfQoJcmV0dXJuIEc7Cn0KCgpHcmlkIE1ha2VHcmlkKCkgewoJR3JpZCBHKDkpOwoJZm9yIChhdXRvJiBvIDogRykgewoJCW8uYXNzaWduKDksIDApOwoJfQoJcmV0dXJuIEc7Cn0KQ3ViZSBNYWtlQ3ViZSgpIHsKCURUeXBlIER7IDEsMiwzLDQsNSw2LDcsOCw5IH07CglDdWJlIEMoOSk7Cglmb3IgKGF1dG8mIG9vIDogQykgewoJCW9vLnJlc2l6ZSg5KTsKCQlmb3IgKGF1dG8mIG8gOiBvbykgewoJCQlvID0gRDsKCQl9Cgl9CgoJcmV0dXJuIEM7Cn0KCkN1YmUgUmVkdWNlQ3ViZShjb25zdCBDdWJlJiBDdSwgY29uc3QgR3JpZCYgUCkgewoJQ3ViZSBDID0gQ3U7Cglmb3IgKHN0ZDo6c2l6ZV90IGkgPSAwOyBpIDwgUC5zaXplKCk7IGkrKykgewoJCWZvciAoc3RkOjpzaXplX3QgaiA9IDA7IGogPCBQW2ldLnNpemUoKTsgaisrKSB7CgkJCWlmIChQW2ldW2pdICE9IDApIHsKCQkJCUNbaV1bal0uY2xlYXIoKTsKCQkJCUNbaV1bal0ucHVzaF9iYWNrKFBbaV1bal0pOwoJCQl9CgoJCX0KCX0KCWZvciAoc3RkOjpzaXplX3QgaSA9IDA7IGkgPCBDLnNpemUoKTsgaSsrKSB7CgkJZm9yIChzdGQ6OnNpemVfdCBqID0gMDsgaiA8IENbaV0uc2l6ZSgpOyBqKyspIHsKCQkJaWYgKENbaV1bal0uc2l6ZSgpICE9IDEpY29udGludWU7CgoKCQkJZm9yIChzdGQ6OnNpemVfdCBrID0gMDsgayA8IFAuc2l6ZSgpOyBrKyspIHsKCQkJCWlmIChDW2ldW2tdLnNpemUoKSA9PSAxKSBjb250aW51ZTsKCQkJCWF1dG8gaXQgPSBzdGQ6OmZpbmQoQ1tpXVtrXS5iZWdpbigpLCBDW2ldW2tdLmVuZCgpLCBDW2ldW2pdWzBdKTsKCQkJCWlmIChpdCAhPSBDW2ldW2tdLmVuZCgpKSB7CgkJCQkJQ1tpXVtrXS5lcmFzZShpdCk7CgkJCQl9CgkJCX0KCQkJZm9yIChzdGQ6OnNpemVfdCBrID0gMDsgayA8IFAuc2l6ZSgpOyBrKyspIHsKCQkJCWlmIChDW2tdW2pdLnNpemUoKSA9PSAxKSBjb250aW51ZTsKCQkJCWF1dG8gaXQgPSBzdGQ6OmZpbmQoQ1trXVtqXS5iZWdpbigpLCBDW2tdW2pdLmVuZCgpLCBDW2ldW2pdWzBdKTsKCQkJCWlmIChpdCAhPSBDW2tdW2pdLmVuZCgpKSB7CgkJCQkJQ1trXVtqXS5lcmFzZShpdCk7CgkJCQl9CgkJCX0KCQl9Cgl9CglzdGQ6OnNpemVfdCBYID0gMDsKCXN0ZDo6c2l6ZV90IFkgPSAwOwoJZm9yIChzdGQ6OnNpemVfdCBZID0gMDsgWSA8IDM7IFkrKykgewoJCWZvciAoc3RkOjpzaXplX3QgWCA9IDA7IFggPCAzOyBYKyspIHsKCgkJCWZvciAoc3RkOjpzaXplX3QgaSA9IDA7IGkgPCAzOyBpKyspIHsKCQkJCWZvciAoc3RkOjpzaXplX3QgaiA9IDA7IGogPCAzOyBqKyspIHsKCgkJCQkJaWYgKENbWSAqIDMgKyBpXVtYICogMyArIGpdLnNpemUoKSAhPSAxKWNvbnRpbnVlOwoKCQkJCQlmb3IgKHN0ZDo6c2l6ZV90IGsgPSAwOyBrIDwgMzsgaysrKSB7CgkJCQkJCWZvciAoc3RkOjpzaXplX3QgbCA9IDA7IGwgPCAzOyBsKyspIHsKCQkJCQkJCWlmIChDW1kgKiAzICsga11bWCAqIDMgKyBsXS5zaXplKCkgPT0gMSljb250aW51ZTsKCQkJCQkJCWF1dG8gaXQgPSBzdGQ6OmZpbmQoQ1tZICogMyArIGtdW1ggKiAzICsgbF0uYmVnaW4oKSwgQ1tZICogMyArIGtdW1ggKiAzICsgbF0uZW5kKCksIENbWSAqIDMgKyBpXVtYICogMyArIGpdWzBdKTsKCQkJCQkJCWlmIChpdCAhPSBDW1kgKiAzICsga11bWCAqIDMgKyBsXS5lbmQoKSkgewoJCQkJCQkJCUNbWSAqIDMgKyBrXVtYICogMyArIGxdLmVyYXNlKGl0KTsKCgkJCQkJCQl9CgkJCQkJCX0KCQkJCQl9CgkJCQl9CgkJCX0KCQl9Cgl9CglyZXR1cm4gQzsKfQoKCmJvb2wgSXNBbnN3ZXIoR3JpZCBQKSB7CglEVHlwZSBEOwoJZm9yIChzdGQ6OnNpemVfdCBZID0gMDsgWSA8IDM7IFkrKykgewoJCWZvciAoc3RkOjpzaXplX3QgWCA9IDA7IFggPCAzOyBYKyspIHsKCQkJZm9yIChzdGQ6OnNpemVfdCBpID0gMDsgaSA8IDM7IGkrKykgewoJCQkJZm9yIChzdGQ6OnNpemVfdCBqID0gMDsgaiA8IDM7IGorKykgewoJCQkJCUQucHVzaF9iYWNrKFBbWSAqIDMgKyBpXVtYICogMyArIGpdKTsKCQkJCX0KCQkJfQoJCQlzdGQ6OnNvcnQoRC5iZWdpbigpLCBELmVuZCgpKTsKCQkJRC5lcmFzZShzdGQ6OnVuaXF1ZShELmJlZ2luKCksIEQuZW5kKCkpLCBELmVuZCgpKTsKCQkJaWYgKEQuc2l6ZSgpICE9IDkpcmV0dXJuIGZhbHNlOwoJCX0KCX0KCglmb3IgKHN0ZDo6c2l6ZV90IGkgPSAwOyBpIDwgUC5zaXplKCk7IGkrKykgewoJCUQuY2xlYXIoKTsKCQlmb3IgKHN0ZDo6c2l6ZV90IGogPSAwOyBqIDwgUFtpXS5zaXplKCk7IGorKykgewoJCQlELnB1c2hfYmFjayhQW2ldW2pdKTsKCQl9CgkJc3RkOjpzb3J0KEQuYmVnaW4oKSwgRC5lbmQoKSk7CgkJRC5lcmFzZShzdGQ6OnVuaXF1ZShELmJlZ2luKCksIEQuZW5kKCkpLCBELmVuZCgpKTsKCQlpZiAoRC5zaXplKCkgIT0gOSlyZXR1cm4gZmFsc2U7Cgl9Cglmb3IgKHN0ZDo6c2l6ZV90IGkgPSAwOyBpIDwgUC5zaXplKCk7IGkrKykgewoJCUQuY2xlYXIoKTsKCQlmb3IgKHN0ZDo6c2l6ZV90IGogPSAwOyBqIDwgUFtpXS5zaXplKCk7IGorKykgewoJCQlELnB1c2hfYmFjayhQW2pdW2ldKTsKCQl9CgkJc3RkOjpzb3J0KEQuYmVnaW4oKSwgRC5lbmQoKSk7CgkJRC5lcmFzZShzdGQ6OnVuaXF1ZShELmJlZ2luKCksIEQuZW5kKCkpLCBELmVuZCgpKTsKCQlpZiAoRC5zaXplKCkgIT0gOSlyZXR1cm4gZmFsc2U7Cgl9CgoJcmV0dXJuIHRydWU7Cn0KR3JpZCBDdWJlVG9HcmlkKGNvbnN0IEN1YmUmIEMsIGNvbnN0IEdyaWQgRykgewoJR3JpZCBSID0gTWFrZUdyaWQoKTsKCWZvciAoc3RkOjpzaXplX3QgaSA9IDA7IGkgPCBHLnNpemUoKTsgaSsrKSB7CgkJZm9yIChzdGQ6OnNpemVfdCBqID0gMDsgaiA8IEdbaV0uc2l6ZSgpOyBqKyspIHsKCQkJUltpXVtqXSA9IENbaV1bal1bR1tpXVtqXV07CgkJfQoJfQoJcmV0dXJuIFI7Cn0KR3JpZCBDdWJlVG9Qcm9ibGVtKGNvbnN0IEN1YmUmIEMpIHsKCUdyaWQgRyA9IE1ha2VHcmlkKCk7Cglmb3IgKHN0ZDo6c2l6ZV90IGkgPSAwOyBpIDwgRy5zaXplKCk7IGkrKykgewoJCWZvciAoc3RkOjpzaXplX3QgaiA9IDA7IGogPCBHW2ldLnNpemUoKTsgaisrKSB7CgkJCWlmIChDW2ldW2pdLnNpemUoKSA9PSAxKSB7CgkJCQlHW2ldW2pdID0gQ1tpXVtqXVswXTsKCQkJfQoJCQllbHNlIHsKCQkJCUdbaV1bal0gPSAwOwoJCQl9CgkJfQoJfQoJcmV0dXJuIEc7Cn0KCmJvb2wgU2hvd0xpc3QoQ3ViZSYgQykgewoJc3RkOjpzaXplX3QgaSA9IDE7Cglkb3VibGUgRCA9IDA7Cglmb3IgKGF1dG8mIG9vbyA6IEMpIHsKCQlmb3IgKGF1dG8mIG9vIDogb29vKSB7CgkJCXN0ZDo6Y291dCA8PCAnWycgPDwgaSA8PCAnOic7CgkJCWkrKzsKCQkJRCArPSBvby5zaXplKCk7CgkJCWZvciAoYXV0byYgbyA6IG9vKSB7CgkJCQlzdGQ6OmNvdXQgPDwgbyA8PCAnLCc7CgkJCX0KCQkJc3RkOjpjb3V0IDw8ICddJzsKCQl9CgkJc3RkOjpjb3V0IDw8IHN0ZDo6ZW5kbDsKCX0KCXN0ZDo6Y291dCA8PCBEIC8gODEuMCA8PCBzdGQ6OmVuZGw7CglyZXR1cm4gdHJ1ZTsKfQoKYm9vbCBTaG93KGNvbnN0IEdyaWQmIEcpIHsKCWZvciAoYXV0byYgb28gOiBHKSB7CgkJZm9yIChhdXRvJiBvIDogb28pIHsKCQkJc3RkOjpjb3V0IDw8IG87CgkJfQoJCXN0ZDo6Y291dCA8PCBzdGQ6OmVuZGw7Cgl9CglzdGQ6OmNvdXQgPDwgc3RkOjplbmRsOwoJc3RkOjpjb3V0IDw8IHN0ZDo6ZW5kbDsKCXJldHVybiB0cnVlOwp9CkRUeXBlIEdldEFudGlJbnRlcnNlY3Rpb24oRFR5cGUgQSAsY29uc3QgRFR5cGUmIEIpey8v56mN6ZuG5ZCI44KS5Y+W44KK6Zmk44GP77yf77yfCglmb3IgKGF1dG8mIG8gOiBCKSB7CgkJYXV0byBpdCA9IHN0ZDo6ZmluZChBLmJlZ2luKCksIEEuZW5kKCksIG8pOwoJCWlmKGl0ICE9IEEuZW5kKCkpQS5lcmFzZShpdCk7Cgl9CglyZXR1cm4gQTsKfQpib29sIElzSG9yaXpvblZhbGlkKGNvbnN0IEdyaWQmIEcsc3RkOjpzaXplX3QgVikgey8v5qiq5pa55ZCR5qSc5p+7CglEVHlwZSBEOwoJZm9yIChzdGQ6OnNpemVfdCBpID0gMDsgaSA8IEdbVl0uc2l6ZSgpOyBpKyspIHsKCQlpZihHW1ZdW2ldIT0wKUQucHVzaF9iYWNrKEdbVl1baV0pOwoJfQoJc3RkOjpzb3J0KEQuYmVnaW4oKSwgRC5lbmQoKSk7CglELmVyYXNlKHN0ZDo6dW5pcXVlKEQuYmVnaW4oKSwgRC5lbmQoKSksIEQuZW5kKCkpOwoJcmV0dXJuIEQuc2l6ZSgpID09IDkgPyB0cnVlIDogZmFsc2U7Cn0KRFR5cGUgR2V0SG9yaXpvblVzaW5nKGNvbnN0IEdyaWQmIEcsc3RkOjpzaXplX3QgVikgey8v5qiq5pa55ZCR5qSc5p+7CglEVHlwZSBEOwoJZm9yIChzdGQ6OnNpemVfdCBpID0gMDsgaSA8IEdbVl0uc2l6ZSgpOyBpKyspIHsKCQlpZihHW1ZdW2ldIT0wKSBELnB1c2hfYmFjayhHW1ZdW2ldKTsKCX0KCXJldHVybiAgRDsKfQpib29sIEhhdmVIb3Jpem9uWmVybyhjb25zdCBHcmlkJiBHLHN0ZDo6c2l6ZV90IFYpIHsvL+aoquaWueWQkeaknOafuwoJRFR5cGUgRDsKCWZvciAoc3RkOjpzaXplX3QgaSA9IDA7IGkgPCBHW1ZdLnNpemUoKTsgaSsrKSB7CgkJaWYgKEdbVl1baV0gPT0gMClyZXR1cm4gdHJ1ZTsKCX0KCXJldHVybiBmYWxzZTsKfQpib29sIElzVmVydGljYWxWYWxpZChjb25zdCBHcmlkJiBHLHN0ZDo6c2l6ZV90IEgpIHsvL+e4puaWueWQkeaknOafuwoJRFR5cGUgRDsKCWZvciAoc3RkOjpzaXplX3QgaSA9IDA7IGkgPCBHLnNpemUoKTsgaSsrKSB7CgkJaWYoR1tpXVtIXSE9IDApRC5wdXNoX2JhY2soR1tpXVtIXSk7Cgl9CglzdGQ6OnNvcnQoRC5iZWdpbigpLCBELmVuZCgpKTsKCUQuZXJhc2Uoc3RkOjp1bmlxdWUoRC5iZWdpbigpLCBELmVuZCgpKSwgRC5lbmQoKSk7CglyZXR1cm4gRC5zaXplKCkgPT0gOSA/IHRydWUgOiBmYWxzZTsKfURUeXBlIEdldFZlcnRpY2FsVXNpbmcoY29uc3QgR3JpZCYgRyxzdGQ6OnNpemVfdCBIKSB7Ly/mqKrmlrnlkJHmpJzmn7sKCURUeXBlIEQ7CglEVHlwZSBUeyAwLDEsMiwzLDQsNSw2LDcsOCB9OwoJZm9yIChzdGQ6OnNpemVfdCBpID0gMDsgaSA8IEcuc2l6ZSgpOyBpKyspIHsKCQlpZihHW2ldW0hdIT0gMClELnB1c2hfYmFjayhHW2ldW0hdKTsKCX0KCglyZXR1cm4gIEQ7Cn0KYm9vbCBIYXZlVmVydGljYWxaZXJvKGNvbnN0IEdyaWQmIEcsc3RkOjpzaXplX3QgSCkgey8v57im5pa55ZCR5qSc5p+7CglEVHlwZSBEOwoJZm9yIChzdGQ6OnNpemVfdCBpID0gMDsgaSA8IEcuc2l6ZSgpOyBpKyspIHsKCQlpZiAoR1tpXVtIXSA9PSAwKXJldHVybiB0cnVlOwoJfQoJcmV0dXJuIGZhbHNlOwp9CmJvb2wgSXNCbG9ja1ZhbGlkKGNvbnN0IEdyaWQmIEcsIHN0ZDo6c2l6ZV90IFgsIHN0ZDo6c2l6ZV90IFkpIHsvLzN4M+aknOafuwoJRFR5cGUgRDsKCWZvciAoc3RkOjpzaXplX3QgaSA9IDA7IGkgPCAzOyBpKyspIHsKCQlmb3IgKHN0ZDo6c2l6ZV90IGogPSAwOyBqIDwgMzsgaisrKSB7CgkJCWlmKEdbWSozK2ldW1gqMytqXSAhPTApRC5wdXNoX2JhY2soR1tZKjMraV1bWCozK2pdKTsKCQl9Cgl9CglzdGQ6OnNvcnQoRC5iZWdpbigpLCBELmVuZCgpKTsKCUQuZXJhc2Uoc3RkOjp1bmlxdWUoRC5iZWdpbigpLCBELmVuZCgpKSwgRC5lbmQoKSk7CglyZXR1cm4gRC5zaXplKCkgPT0gOSA/IHRydWUgOiBmYWxzZTsKfQpEVHlwZSBHZXRCbG9ja1VzaW5nKGNvbnN0IEdyaWQmIEcsc3RkOjpzaXplX3QgWCxzdGQ6OnNpemVfdCBZKSB7Ly/mqKrmlrnlkJHmpJzmn7sKCURUeXBlIEQ7Cglmb3IgKHN0ZDo6c2l6ZV90IGkgPSAwOyBpIDwgMzsgaSsrKSB7CgkJZm9yIChzdGQ6OnNpemVfdCBqID0gMDsgaiA8IDM7IGorKykgewoJCQlpZihHW1kqMytpXVtYKjMral0gIT0wKSBELnB1c2hfYmFjayhHW1kqMytpXVtYKjMral0pOwoJCX0KCX0KCglyZXR1cm4gRDsKfQpib29sIEhhdmVCbG9ja051bWJlcihjb25zdCBHcmlkJiBHLCBzdGQ6OnNpemVfdCBYLCBzdGQ6OnNpemVfdCBZLCBzdGQ6OnNpemVfdCBOKSB7Ly/mqKrmlrnlkJHmpJzmn7sKCURUeXBlIEQ7Cglmb3IgKHN0ZDo6c2l6ZV90IGkgPSAwOyBpIDwgMzsgaSsrKSB7CgkJZm9yIChzdGQ6OnNpemVfdCBqID0gMDsgaiA8IDM7IGorKykgewoJCQlpZiAoR1tZICogMyArIGldW1ggKiAzICsgal0gPT0gTilyZXR1cm4gdHJ1ZTsKCQl9Cgl9CgoJcmV0dXJuIGZhbHNlOwp9CmJvb2wgSGF2ZUJsb2NrWmVybyhjb25zdCBHcmlkJiBHLCBzdGQ6OnNpemVfdCBYLCBzdGQ6OnNpemVfdCBZKSB7Ly8zeDPmpJzmn7sKCURUeXBlIEQ7Cglmb3IgKHN0ZDo6c2l6ZV90IGkgPSAwOyBpIDwgMzsgaSsrKSB7CgkJZm9yIChzdGQ6OnNpemVfdCBqID0gMDsgaiA8IDM7IGorKykgewoJCQlpZiAoR1tZICogMyArIGldW1ggKiAzICsgal0gPT0gMClyZXR1cm4gdHJ1ZTsKCQl9Cgl9CgoJcmV0dXJuIGZhbHNlOwp9CgoKYm9vbCBTZWFyY2hfcihHcmlkJiBHLCBpbnQgRGVlcCwgUlR5cGUmIFIsIHN0ZDo6c2l6ZV90JiBDKSB7CglDKys7Cglnb3RveHkoMTEsIDApOwovLwlzdGQ6OmNvdXQgPDwgQyA8PCBzdGQ6OmVuZGw7CglpZiAoRGVlcCA+PSA4MSkgewoJCWdvdG94eSgwLCAwKTsKCQkvL1Nob3coRyk7CgkJaWYgKElzQW5zd2VyKEcpKSB7CgkJCVIucHVzaF9iYWNrKEcpOwoJCQlzdGQ6OmNvdXQgPDwgImZpbmQhISIgPDwgc3RkOjplbmRsOwoJCQlyZXR1cm4gdHJ1ZTsKCQl9CgoJCXJldHVybiBmYWxzZTsKCX0JCgkKCXN0YXRpYyBjb25zdCBEVHlwZSBUeyAxLDIsMyw0LDUsNiw3LDgsOSB9OwoJc3RkOjpzaXplX3QgTVggPSAoRGVlcCAlIDkpICUgMzsKCXN0ZDo6c2l6ZV90IE1ZID0gKERlZXAgJSA5KSAvIDM7CglzdGQ6OnNpemVfdCBCWCA9IChEZWVwIC8gOSkgJSAzOwoJc3RkOjpzaXplX3QgQlkgPSAoRGVlcCAvIDkpIC8gMzsKCWF1dG8gQlUgPSBHZXRCbG9ja1VzaW5nKEcsIEJYLCBCWSk7CglhdXRvIEhVID0gR2V0SG9yaXpvblVzaW5nKEcsIEJZKjMrTVkpOwoJYXV0byBWVSA9IEdldFZlcnRpY2FsVXNpbmcoRywgQlgqMyArIE1YKTsKCURUeXBlIEFJOwoJCglpZiAoR1tCWSozICsgTVldW0JYKjMgKyBNWF0gIT0gMCkgewoJCXJldHVybiBTZWFyY2hfcihHLCBEZWVwICsgMSwgUixDKTsKCX0KCQoJc3RkOjpjb3B5KEJVLmJlZ2luKCksIEJVLmVuZCgpLCBzdGQ6OmJhY2tfaW5zZXJ0ZXIoQUkpKTsKCXN0ZDo6Y29weShIVS5iZWdpbigpLCBIVS5lbmQoKSwgc3RkOjpiYWNrX2luc2VydGVyKEFJKSk7CglzdGQ6OmNvcHkoVlUuYmVnaW4oKSwgVlUuZW5kKCksIHN0ZDo6YmFja19pbnNlcnRlcihBSSkpOwoJc3RkOjpzb3J0KEFJLmJlZ2luKCksIEFJLmVuZCgpKTsKCUFJLmVyYXNlKHN0ZDo6dW5pcXVlKEFJLmJlZ2luKCksIEFJLmVuZCgpKSwgQUkuZW5kKCkpOwoJRFR5cGUgRCA9IEdldEFudGlJbnRlcnNlY3Rpb24oVCwgQUkpOwoKCWF1dG8gV0cgPSBHOwoJaWYgKEQuc2l6ZSgpID09IDApIHJldHVybiBmYWxzZTsKCWZvciAoc3RkOjpzaXplX3QgaSA9IDA7IGkgPCBELnNpemUoKTsgaSsrKSB7CgkJV0dbQlkqMyArIE1ZXVtCWCozICsgTVhdID0gRFtpXTsKCQlnb3RveHkoMCwgMCk7Ci8vCQlTaG93KFdHKTsKCQlTZWFyY2hfcihXRywgRGVlcCArIDEsIFIsQyk7Cgl9CgoJcmV0dXJuIGZhbHNlOwoKfQpib29sIFNlYXJjaChHcmlkJiBHLCBSVHlwZSYgUikgewoJaW50IERlZXAgPSAwOwoJc3RkOjpzaXplX3QgQz0wOwoJcmV0dXJuIFNlYXJjaF9yKEcsIERlZXAsIFIsIEMpOwp9CgoKUlR5cGUgTWFrZUhvZ2UoR3JpZCBHKSB7CglDdWJlIEN1ID0gTWFrZUN1YmUoKTsKCUN1YmUgQyA9IFJlZHVjZUN1YmUoQ3UsIEcpOwoJR3JpZCBWID0gTWFrZUdyaWQoKTsKCVJUeXBlIFI7CglHcmlkIEIgPSBHOwoJR3JpZCBEOwoJc3RkOjp1aW50NjRfdCBDbyA9IDA7CglzdGQ6OnVpbnQ2NF90IEZpbmQgPSAxOwoJZG8gewoJCUQgPSBCOwoJCUIgPSBDdWJlVG9Qcm9ibGVtKEMpOwoJCUMgPSBSZWR1Y2VDdWJlKEMsIEIpOwoJfSB3aGlsZSAoRCAhPSBCKTsKCWdvdG94eSgwLCAxMSk7Ci8vCVNob3coQik7Ci8vCVNob3dMaXN0KEMpOwoJYXV0byBBID0gQ3ViZVRvUHJvYmxlbShDKTsKCWdvdG94eSgwLCAxMSk7Ci8vCVNob3coQSk7CglTZWFyY2goQSwgUik7CglzdGQ6OnNvcnQoUi5iZWdpbigpLCBSLmVuZCgpKTsKCVIuZXJhc2Uoc3RkOjp1bmlxdWUoUi5iZWdpbigpLCBSLmVuZCgpKSwgUi5lbmQoKSk7Cglnb3RveHkoMCwgMTEpOwoJcmV0dXJuIFI7Cn0KCgoKaW50IG1haW4oKSB7CglzdGQ6OmNvdXQgPDwgIkdlbmVyYXRlaW5nISIgPDwgc3RkOjplbmRsOwoJRjoKCUdyaWQgRyA9IE1ha2VQcm9ibGVtMigpOwoJUlR5cGUgUjsKCVIgPSBNYWtlSG9nZShHKTsKCWlmIChSLnNpemUoKSA9PSAwKSBnb3RvIEY7CglzdGQ6OmNvdXQgPDwgIlNob3cgUHJvYmxlbSBTZWVkLiIgPDwgc3RkOjplbmRsOwoJU2hvdyhHKTsKLyoKCWZvciAoYXV0byYgbyA6IFIpIHsKLy8JCWdvdG94eSgwLCAwKTsKCQlTaG93KG8pOwoJfQoJKi8KCUcgPSBSWzBdOwoKCXN0ZDo6Y291dCA8PCAiU2hvdyBQcm9ibGVtIFNlZWQyLiIgPDwgc3RkOjplbmRsOwoJU2hvdyhHKTsKCUdyaWQgQSA9IEVyYXNlTnVtYmVyKEcsIDQ1KTsKCXN0ZDo6Y291dCA8PCAiTnVtYmVyIEVyYXNlZCEiIDw8IHN0ZDo6ZW5kbDsKCVNob3coQSk7CgkKCVI9TWFrZUhvZ2UoQSk7CglzdGQ6OmNvdXQgPDwgIlNob3cgQW5zd2VyISIgPDwgc3RkOjplbmRsOwoJZm9yIChhdXRvJiBvIDogUikgewovLwkJZ290b3h5KDAsIDApOwoJCVNob3cobyk7Cgl9CglyZXR1cm4gMDsKfQ==