#include <iostream>
#include <vector>
#include <string>
#include <tuple>
#include <algorithm>
//小文字大文字は判別する。
//処理速度度返し!!Orz
typedef std:: vector < std:: tuple < int , int , std:: string >> RType;
RType FindRight( const std:: vector < std:: string > & Vec, const std:: string & Word, bool IsRev = false ) {
std:: size_t Cur = 0 ;
std:: size_t x = 0 , y = 0 ;
RType Ret;
for ( std:: size_t i = 0 ; i < Vec.size ( ) ; i++ ) {
for ( std:: size_t j = 0 ; j < Vec[ i] .size ( ) ; j++ ) {
if ( Vec[ i] [ j] == Word[ Cur] ) {
if ( Cur == 0 ) {
x = j;
y = i;
}
Cur++ ;
}
else {
if ( Cur ! = 0 ) j-- ;
Cur = 0 ;
}
if ( Cur == Word.size ( ) ) {
if ( IsRev == false ) {
Ret.push_back ( std:: make_tuple ( y, x, "R" ) ) ;
}
else {
Ret.push_back ( std:: make_tuple ( i, j, "L" ) ) ;
}
//return Ret;//一個見つけたらやめる
}
}
Cur = 0 ;
}
return Ret;
}
RType FindBottom( const std:: vector < std:: string > & Vec,const std:: string & Word,bool IsRev = false ) {
std:: size_t Cur = 0 ;
std:: size_t x = 0 , y = 0 ;
std:: size_t j = 0 ;
RType Ret;
std:: size_t M = 0 ;
while ( true ) {
for ( std:: size_t i = 0 ; i < Vec.size ( ) ; i++ ) {
if ( Vec[ i] .size ( ) < j) continue ;
M = std:: max ( M, Vec[ i] .size ( ) ) ;
if ( Vec[ i] [ j] == Word[ Cur] ) {
if ( Cur == 0 ) {
x = j;
y = i;
}
Cur++ ;
}
else {
if ( Cur ! = 0 ) i-- ;
Cur = 0 ;
}
if ( Cur == Word.size ( ) ) {
if ( IsRev == false ) {
Ret.push_back ( std:: make_tuple ( y, x, "D" ) ) ;
}
else {
Ret.push_back ( std:: make_tuple ( i, j, "U" ) ) ;
}
//return Ret;//一個見つけたらやめる
}
}
Cur = 0 ;
j++ ;
if ( j >= M) break ;
}
return Ret;
}
RType FindNanameMae( std:: vector < std:: string > & Vec, std:: string Word,bool IsRev = false ) {
std:: size_t vs = Vec.size ( ) ;
std:: size_t ss = Word.size ( ) ;
std:: size_t Cur = 0 ;
std:: size_t x = 0 , y = 0 ;
bool F = false ;
RType Ret;
std:: vector < std:: pair < int , int >> T;
int A = 0 , B = 0 ;
for ( std:: size_t i = 0 ; i < Vec.size ( ) ; i++ ) {
for ( std:: size_t j = 0 ; j < Vec[ i] .size ( ) ; j++ ) {
for ( std:: size_t k = 0 ; k + i < Vec.size ( ) && k + j < Vec[ i + k] .size ( ) ; k++ ) {
if ( Vec[ i + k] [ j + k] == Word[ Cur] ) {
if ( Cur == 0 ) {
x = j+ k;
y = i+ k;
}
Cur++ ;
}
else {
Cur = 0 ;
}
if ( Cur == Word.size ( ) ) {
if ( IsRev == false ) {
A = y;
B = x;
}
else {
A = i+ k;
B = j+ k;
}
auto P = std:: make_pair ( A, B) ;
for ( auto & o : T) {
F = o == P;
if ( F == true ) break ;
}
if ( F == true ) continue ;
if ( IsRev == false ) {
T.push_back ( std:: make_pair ( y, x) ) ;
Ret.push_back ( std:: make_tuple ( y, x, "NM" ) ) ;
}
else {
T.push_back ( std:: make_pair ( i+ k, j+ k) ) ;
Ret.push_back ( std:: make_tuple ( i+ k, j+ k, "NMR" ) ) ;
}
//return Ret;//一個見つけたらやめる
}
}
Cur = 0 ;
}
}
return Ret;
}
RType FindNanameUsiro( std:: vector < std:: string > & Vec, std:: string Word,bool IsRev = false ) {
std:: size_t vs = Vec.size ( ) ;
std:: size_t ss = Word.size ( ) ;
std:: size_t Cur = 0 ;
std:: size_t x = 0 , y = 0 ;
bool F = false ;
RType Ret;
std:: vector < std:: pair < int , int >> T;
int A = 0 , B = 0 ;
for ( std:: size_t i = 0 ; i < Vec.size ( ) ; i++ ) {
for ( int j = 0 ; j < Vec[ i] .size ( ) ; j++ ) {
for ( int k = 0 ; k + i < Vec.size ( ) && j- k >= 0 ; k++ ) {
if ( Vec[ i + k] [ j - k] == Word[ Cur] ) {
if ( Cur == 0 ) {
x = j+ k;
y = i+ k;
}
Cur++ ;
}
else {
Cur = 0 ;
}
if ( Cur == Word.size ( ) ) {
if ( IsRev == false ) {
A = y;
B = x;
}
else {
A = i+ k;
B = j- k;
}
auto P = std:: make_pair ( A, B) ;
for ( auto & o : T) {
F = o == P;
if ( F == true ) break ;
}
if ( F == true ) continue ;
if ( IsRev == false ) {
T.push_back ( std:: make_pair ( y, x) ) ;
Ret.push_back ( std:: make_tuple ( y, x, "NU" ) ) ;
}
else {
T.push_back ( std:: make_pair ( i+ k, j- k) ) ;
Ret.push_back ( std:: make_tuple ( i+ k, j- k, "NUR" ) ) ;
}
//return Ret;//一個見つけたらやめる
}
}
Cur = 0 ;
}
}
return Ret;
}
RType FindWord( std:: vector < std:: string > & Vec,const std:: string & Word) {
RType Ret;
auto bs = std:: back_inserter ( Ret) ;
/* */
auto FR = FindRight( Vec, Word) ;
for ( auto & o : FR) bs = o;
/* */
auto FB = FindBottom( Vec, Word) ;
for ( auto & o : FB) bs = o;
/* */
auto FNM = FindNanameMae( Vec, Word) ;
for ( auto & o : FNM) bs = o;
/* */
auto FNU = FindNanameUsiro( Vec, Word) ;
for ( auto & o : FNU) bs = o;
/* */
std:: string T( Word.rbegin ( ) ,Word.rend ( ) ) ;
/* */
auto FRR = FindRight( Vec, T, true ) ;
for ( auto & o : FRR) bs = o;
/* */
auto FBR = FindBottom( Vec, T,true ) ;
for ( auto & o : FBR) bs = o;
/* */
auto FNMR = FindNanameMae( Vec, T,true ) ;
for ( auto & o : FNMR) bs = o;
/* */
auto FNUR = FindNanameUsiro( Vec, T,true ) ;
for ( auto & o : FNUR) bs = o;
/* */
return Ret;
}
int main( ) {
std:: vector < std:: string > vec = {
"WVERTICALL" ,
"ROOAFFLSAB" ,
"ACRILIATOA" ,
"NDODKONWDC" ,
"DRKESOODDK" ,
"OEEPZEGLIW" ,
"MSIIHOAERA" ,
"ALRKRRIRER" ,
"KODIDEDRCD" ,
"HELWSLEUTH" ,
} ;
std:: vector < std:: string > Words = {
"WEEK" ,
"FIND" ,
"RANDOM" ,
"SLEUTH" ,
"BACKWARD" ,
"VERTICAL" ,
"DIAGONAL" ,
"WIKIPEDIA" ,
"HORIZONTAL" ,
"WORDSEARCH" ,
} ;
std:: vector < std:: string > vec2 = {
"MAMEMAM" ,
"AAoMoAA" ,
"MoMAMoM" ,
"EMAEAME" ,
"MoMAMoM" ,
"AAoMoAA" ,
"MAMEMAM" ,
} ;
std:: string MAME = "MAME" ;
for ( std:: size_t i = 0 ; i < Words.size ( ) ; i++ ) {
auto R = FindWord( vec, Words[ i] ) ;
if ( R.size ( ) == 0 ) {
std:: cout << Words[ i] << " is NotFound!" << std:: endl ;
continue ;
}
std:: cout << Words[ i] << " is " ;
for ( auto & o : R) std:: cout << std:: get < 0 > ( o) + 1 << ',' << std:: get < 1 > ( o) + 1 << "@" << std:: get < 2 > ( o) << ' ' ;
std:: cout << std:: endl ;
}
auto R = FindWord( vec2, MAME) ;
if ( R.size ( ) == 0 ) {
std:: cout << MAME << " is NotFound!" << std:: endl ;
}
std:: cout << MAME << " is " ;
for ( auto & o : R) std:: cout << std:: get < 0 > ( o) + 1 << ',' << std:: get < 1 > ( o) + 1 << "@" << std:: get < 2 > ( o) << ' ' ;
std:: cout << std:: endl ;
return 0 ;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8dmVjdG9yPgojaW5jbHVkZSA8c3RyaW5nPgojaW5jbHVkZSA8dHVwbGU+CiNpbmNsdWRlIDxhbGdvcml0aG0+CgovL+Wwj+aWh+Wtl+Wkp+aWh+Wtl+OBr+WIpOWIpeOBmeOCi+OAggovL+WHpueQhumAn+W6puW6pui/lOOBl++8ge+8gU9yegoKdHlwZWRlZiBzdGQ6OnZlY3RvcjxzdGQ6OnR1cGxlPGludCwgaW50LCBzdGQ6OnN0cmluZz4+IFJUeXBlOwoKClJUeXBlIEZpbmRSaWdodChjb25zdCBzdGQ6OnZlY3RvcjxzdGQ6OnN0cmluZz4mIFZlYywgY29uc3Qgc3RkOjpzdHJpbmcmIFdvcmQsIGJvb2wgSXNSZXYgPSBmYWxzZSl7CglzdGQ6OnNpemVfdCBDdXIgPSAwOwoJc3RkOjpzaXplX3QgeCA9IDAsIHkgPSAwOwoJUlR5cGUgUmV0OwoKCWZvciAoc3RkOjpzaXplX3QgaSA9IDA7IGkgPCBWZWMuc2l6ZSgpOyBpKyspewoJCWZvciAoc3RkOjpzaXplX3QgaiA9IDA7IGogPCBWZWNbaV0uc2l6ZSgpOyBqKyspewoJCQlpZiAoVmVjW2ldW2pdID09IFdvcmRbQ3VyXSl7CgkJCQlpZiAoQ3VyID09IDApewoJCQkJCXggPSBqOwoJCQkJCXkgPSBpOwoJCQkJfQoJCQkJQ3VyKys7CgkJCX0KCQkJZWxzZXsKCQkJCWlmIChDdXIgIT0gMCkgai0tOwoJCQkJQ3VyID0gMDsKCQkJfQoJCQlpZiAoQ3VyID09IFdvcmQuc2l6ZSgpKXsKCQkJCWlmIChJc1JldiA9PSBmYWxzZSl7CgkJCQkJUmV0LnB1c2hfYmFjayhzdGQ6Om1ha2VfdHVwbGUoeSwgeCwgIlIiKSk7CgkJCQl9CgkJCQllbHNlewoJCQkJCVJldC5wdXNoX2JhY2soc3RkOjptYWtlX3R1cGxlKGksIGosICJMIikpOwoJCQkJfQoJCQkJLy9yZXR1cm4gUmV0Oy8v5LiA5YCL6KaL44Gk44GR44Gf44KJ44KE44KB44KLCgkJCX0KCQl9CgkJQ3VyID0gMDsKCX0KCQoJcmV0dXJuIFJldDsKfQpSVHlwZSBGaW5kQm90dG9tKGNvbnN0IHN0ZDo6dmVjdG9yPHN0ZDo6c3RyaW5nPiYgVmVjLGNvbnN0IHN0ZDo6c3RyaW5nJiBXb3JkLGJvb2wgSXNSZXYgPWZhbHNlKXsKCXN0ZDo6c2l6ZV90IEN1ciA9IDA7CglzdGQ6OnNpemVfdCB4ID0gMCwgeSA9IDA7CglzdGQ6OnNpemVfdCBqID0gMDsKCVJUeXBlIFJldDsKCXN0ZDo6c2l6ZV90IE0gPSAwOwoJd2hpbGUgKHRydWUpewoJCWZvciAoc3RkOjpzaXplX3QgaSA9IDA7IGkgPCBWZWMuc2l6ZSgpOyBpKyspewoJCQlpZiAoVmVjW2ldLnNpemUoKSA8IGopIGNvbnRpbnVlOwoJCQlNID0gc3RkOjptYXgoTSwgVmVjW2ldLnNpemUoKSk7CgkJCWlmIChWZWNbaV1bal0gPT0gV29yZFtDdXJdKXsKCQkJCWlmIChDdXIgPT0gMCl7CgkJCQkJeCA9IGo7CgkJCQkJeSA9IGk7CgkJCQl9CgkJCQlDdXIrKzsKCQkJfQoJCQllbHNlewoJCQkJaWYgKEN1ciAhPSAwKSBpLS07CgkJCQlDdXIgPSAwOwoJCQl9CgkJCWlmIChDdXIgPT0gV29yZC5zaXplKCkpewoJCQkJaWYgKElzUmV2ID09IGZhbHNlKXsKCQkJCQlSZXQucHVzaF9iYWNrKHN0ZDo6bWFrZV90dXBsZSh5LCB4LCAiRCIpKTsKCQkJCX0KCQkJCWVsc2V7CgkJCQkJUmV0LnB1c2hfYmFjayhzdGQ6Om1ha2VfdHVwbGUoaSwgaiwgIlUiKSk7CgkJCQl9CgkJCQkvL3JldHVybiBSZXQ7Ly/kuIDlgIvopovjgaTjgZHjgZ/jgonjgoTjgoHjgosKCQkJfQoKCQl9CgkJQ3VyID0gMDsKCQlqKys7CgkJaWYgKGogPj0gTSkgYnJlYWs7Cgl9CgkKCXJldHVybiBSZXQ7Cn0KUlR5cGUgRmluZE5hbmFtZU1hZShzdGQ6OnZlY3RvcjxzdGQ6OnN0cmluZz4mIFZlYywgc3RkOjpzdHJpbmcgV29yZCxib29sIElzUmV2ID0gZmFsc2UpewoJc3RkOjpzaXplX3QgdnMgPSBWZWMuc2l6ZSgpOwoJc3RkOjpzaXplX3Qgc3MgPSBXb3JkLnNpemUoKTsKCXN0ZDo6c2l6ZV90IEN1ciA9IDA7CglzdGQ6OnNpemVfdCB4ID0gMCwgeSA9IDA7Cglib29sIEYgPSBmYWxzZTsKCVJUeXBlIFJldDsKCXN0ZDo6dmVjdG9yIDwgc3RkOjpwYWlyPGludCwgaW50Pj4gVDsKCWludCBBID0gMCwgQiA9IDA7CgoJZm9yIChzdGQ6OnNpemVfdCBpID0gMDsgaSA8IFZlYy5zaXplKCk7IGkrKyl7CgkJZm9yIChzdGQ6OnNpemVfdCBqID0gMDsgaiA8IFZlY1tpXS5zaXplKCk7IGorKyl7CgkJCWZvciAoc3RkOjpzaXplX3QgayA9IDA7IGsgKyBpIDwgVmVjLnNpemUoKSAmJiBrICsgaiA8IFZlY1tpICsga10uc2l6ZSgpOyBrKyspewoJCQkJaWYgKFZlY1tpICsga11baiArIGtdID09IFdvcmRbQ3VyXSl7CgkJCQkJaWYgKEN1ciA9PSAwKXsKCQkJCQkJeCA9IGorazsKCQkJCQkJeSA9IGkrazsKCQkJCQl9CgkJCQkJQ3VyKys7CgkJCQl9CgkJCQllbHNlewoJCQkJCUN1ciA9IDA7CgkJCQl9CgkJCQlpZiAoQ3VyID09IFdvcmQuc2l6ZSgpKXsKCgkJCQkJaWYgKElzUmV2ID09IGZhbHNlKXsKCQkJCQkJQSA9IHk7CgkJCQkJCUIgPSB4OwoJCQkJCX0KCQkJCQllbHNlewoJCQkJCQlBID0gaStrOwoJCQkJCQlCID0gaitrOwoJCQkJCX0KCQkJCQlhdXRvIFAgPSBzdGQ6Om1ha2VfcGFpcihBLCBCKTsKCQkJCQlmb3IgKGF1dG8mIG8gOiBUKXsKCQkJCQkJRiA9IG8gPT0gUDsKCQkJCQkJaWYgKEYgPT0gdHJ1ZSkgYnJlYWs7CgkJCQkJfQoJCQkJCWlmIChGID09IHRydWUpY29udGludWU7CgoJCQkJCWlmIChJc1JldiA9PSBmYWxzZSl7CgkJCQkJCVQucHVzaF9iYWNrKHN0ZDo6bWFrZV9wYWlyKHksIHgpKTsKCQkJCQkJUmV0LnB1c2hfYmFjayhzdGQ6Om1ha2VfdHVwbGUoeSwgeCwgIk5NIikpOwoJCQkJCX0KCQkJCQllbHNlewoJCQkJCQlULnB1c2hfYmFjayhzdGQ6Om1ha2VfcGFpcihpK2ssIGoraykpOwoJCQkJCQlSZXQucHVzaF9iYWNrKHN0ZDo6bWFrZV90dXBsZShpK2ssIGoraywgIk5NUiIpKTsKCQkJCQl9CgkJCQkJLy9yZXR1cm4gUmV0Oy8v5LiA5YCL6KaL44Gk44GR44Gf44KJ44KE44KB44KLCgkJCQl9CgkJCX0KCQkJQ3VyID0gMDsKCQl9Cgl9CglyZXR1cm4gUmV0Owp9ClJUeXBlIEZpbmROYW5hbWVVc2lybyhzdGQ6OnZlY3RvcjxzdGQ6OnN0cmluZz4mIFZlYywgc3RkOjpzdHJpbmcgV29yZCxib29sIElzUmV2ID0gZmFsc2UpewoJc3RkOjpzaXplX3QgdnMgPSBWZWMuc2l6ZSgpOwoJc3RkOjpzaXplX3Qgc3MgPSBXb3JkLnNpemUoKTsKCXN0ZDo6c2l6ZV90IEN1ciA9IDA7CglzdGQ6OnNpemVfdCB4ID0gMCwgeSA9IDA7Cglib29sIEYgPSBmYWxzZTsKCVJUeXBlIFJldDsKCXN0ZDo6dmVjdG9yIDwgc3RkOjpwYWlyPGludCwgaW50Pj4gVDsKCWludCBBID0gMCwgQiA9IDA7CgoJZm9yIChzdGQ6OnNpemVfdCBpID0gMDsgaSA8IFZlYy5zaXplKCk7IGkrKyl7CgkJZm9yIChpbnQgaiA9IDA7IGogPCBWZWNbaV0uc2l6ZSgpOyBqKyspewoJCQlmb3IgKGludCBrID0gMDsgayArIGkgPCBWZWMuc2l6ZSgpICYmIGotayA+PSAwOyBrKyspewoJCQkJaWYgKFZlY1tpICsga11baiAtIGtdID09IFdvcmRbQ3VyXSl7CgkJCQkJaWYgKEN1ciA9PSAwKXsKCQkJCQkJeCA9IGorazsKCQkJCQkJeSA9IGkrazsKCQkJCQl9CgkJCQkJQ3VyKys7CgkJCQl9CgkJCQllbHNlewoJCQkJCUN1ciA9IDA7CgkJCQl9CgkJCQlpZiAoQ3VyID09IFdvcmQuc2l6ZSgpKXsKCgkJCQkJaWYgKElzUmV2ID09IGZhbHNlKXsKCQkJCQkJQSA9IHk7CgkJCQkJCUIgPSB4OwoJCQkJCX0KCQkJCQllbHNlewoJCQkJCQlBID0gaStrOwoJCQkJCQlCID0gai1rOwoJCQkJCX0KCQkJCQlhdXRvIFAgPSBzdGQ6Om1ha2VfcGFpcihBLCBCKTsKCQkJCQlmb3IgKGF1dG8mIG8gOiBUKXsKCQkJCQkJRiA9IG8gPT0gUDsKCQkJCQkJaWYgKEYgPT0gdHJ1ZSkgYnJlYWs7CgkJCQkJfQoJCQkJCWlmIChGID09IHRydWUpY29udGludWU7CgoJCQkJCWlmIChJc1JldiA9PSBmYWxzZSl7CgkJCQkJCVQucHVzaF9iYWNrKHN0ZDo6bWFrZV9wYWlyKHksIHgpKTsKCQkJCQkJUmV0LnB1c2hfYmFjayhzdGQ6Om1ha2VfdHVwbGUoeSwgeCwgIk5VIikpOwoJCQkJCX0KCQkJCQllbHNlewoJCQkJCQlULnB1c2hfYmFjayhzdGQ6Om1ha2VfcGFpcihpK2ssIGotaykpOwoJCQkJCQlSZXQucHVzaF9iYWNrKHN0ZDo6bWFrZV90dXBsZShpK2ssIGotaywgIk5VUiIpKTsKCQkJCQl9CgkJCQkJLy9yZXR1cm4gUmV0Oy8v5LiA5YCL6KaL44Gk44GR44Gf44KJ44KE44KB44KLCgkJCQl9CgkJCX0KCQkJQ3VyID0gMDsKCQl9Cgl9CglyZXR1cm4gUmV0Owp9CgpSVHlwZSBGaW5kV29yZChzdGQ6OnZlY3RvcjxzdGQ6OnN0cmluZz4mIFZlYyxjb25zdCBzdGQ6OnN0cmluZyYgV29yZCl7CglSVHlwZSBSZXQ7CglhdXRvIGJzID0gc3RkOjpiYWNrX2luc2VydGVyKFJldCk7CgoKCS8qICovCglhdXRvIEZSID0gRmluZFJpZ2h0KFZlYywgV29yZCk7Cglmb3IgKGF1dG8mIG8gOiBGUilicyA9IG87CgkvKiAqLwoJYXV0byBGQiA9IEZpbmRCb3R0b20oVmVjLCBXb3JkKTsKCWZvciAoYXV0byYgbyA6IEZCKWJzID0gbzsKCS8qICovCglhdXRvIEZOTSA9IEZpbmROYW5hbWVNYWUoVmVjLCBXb3JkKTsKCWZvciAoYXV0byYgbyA6IEZOTSlicyA9IG87CgkvKiAqLwoJYXV0byBGTlUgPSBGaW5kTmFuYW1lVXNpcm8oVmVjLCBXb3JkKTsKCWZvciAoYXV0byYgbyA6IEZOVSlicyA9IG87CgkvKiAqLwoJc3RkOjpzdHJpbmcgVChXb3JkLnJiZWdpbigpLFdvcmQucmVuZCgpKTsKCQoJLyogKi8KCWF1dG8gRlJSID0gRmluZFJpZ2h0KFZlYywgVCwgdHJ1ZSk7Cglmb3IgKGF1dG8mIG8gOiBGUlIpYnMgPSBvOwoJLyogKi8KCWF1dG8gRkJSID0gRmluZEJvdHRvbShWZWMsIFQsdHJ1ZSk7Cglmb3IgKGF1dG8mIG8gOiBGQlIpYnMgPSBvOwoJLyogKi8KCWF1dG8gRk5NUiA9IEZpbmROYW5hbWVNYWUoVmVjLCBULHRydWUpOwoJZm9yIChhdXRvJiBvIDogRk5NUilicyA9IG87CgkvKiAqLwoJYXV0byBGTlVSID0gRmluZE5hbmFtZVVzaXJvKFZlYywgVCx0cnVlKTsKCWZvciAoYXV0byYgbyA6IEZOVVIpYnMgPSBvOwoJLyogKi8KCXJldHVybiBSZXQ7Cgp9CgoKaW50IG1haW4oKXsKCXN0ZDo6dmVjdG9yPHN0ZDo6c3RyaW5nPiB2ZWMgPSB7CgkJIldWRVJUSUNBTEwiLAoJCSJST09BRkZMU0FCIiwKCQkiQUNSSUxJQVRPQSIsCgkJIk5ET0RLT05XREMiLAoJCSJEUktFU09PRERLIiwKCQkiT0VFUFpFR0xJVyIsCgkJIk1TSUlIT0FFUkEiLAoJCSJBTFJLUlJJUkVSIiwKCQkiS09ESURFRFJDRCIsCgkJIkhFTFdTTEVVVEgiLAoJfTsKCXN0ZDo6dmVjdG9yPHN0ZDo6c3RyaW5nPiBXb3JkcyA9IHsKCQkiV0VFSyIsCgkJIkZJTkQiLAoJCSJSQU5ET00iLAoJCSJTTEVVVEgiLAoJCSJCQUNLV0FSRCIsCgkJIlZFUlRJQ0FMIiwKCQkiRElBR09OQUwiLAoJCSJXSUtJUEVESUEiLAoJCSJIT1JJWk9OVEFMIiwKCQkiV09SRFNFQVJDSCIsCgl9OwoJc3RkOjp2ZWN0b3I8c3RkOjpzdHJpbmc+IHZlYzIgPSB7CgkJIk1BTUVNQU0iLAoJCSJBQW9Nb0FBIiwKCQkiTW9NQU1vTSIsCgkJIkVNQUVBTUUiLAoJCSJNb01BTW9NIiwKCQkiQUFvTW9BQSIsCgkJIk1BTUVNQU0iLAoJfTsKCglzdGQ6OnN0cmluZyBNQU1FID0gIk1BTUUiOwoKCWZvciAoc3RkOjpzaXplX3QgaSA9IDA7IGkgPCBXb3Jkcy5zaXplKCk7IGkrKyl7CgkJYXV0byBSID0gRmluZFdvcmQodmVjLCBXb3Jkc1tpXSk7CgoJCWlmIChSLnNpemUoKSA9PSAwKXsKCQkJc3RkOjpjb3V0IDw8IFdvcmRzW2ldIDw8ICIgaXMgTm90Rm91bmQhIiA8PCBzdGQ6OmVuZGw7CgkJCWNvbnRpbnVlOwoJCX0KCQlzdGQ6OmNvdXQgPDwgV29yZHNbaV0gPDwgIiBpcyAiOwoJCWZvciAoYXV0byYgbyA6IFIpIHN0ZDo6Y291dCA8PCBzdGQ6OmdldDwwPihvKSsxIDw8ICcsJyA8PCBzdGQ6OmdldDwxPihvKSsxIDw8ICJAIiA8PCBzdGQ6OmdldDwyPihvKSA8PCAnICc7CgkJc3RkOjpjb3V0IDw8IHN0ZDo6ZW5kbDsKCX0KCWF1dG8gUiA9IEZpbmRXb3JkKHZlYzIsIE1BTUUpOwoKCWlmIChSLnNpemUoKSA9PSAwKXsKCQlzdGQ6OmNvdXQgPDwgTUFNRSA8PCAiIGlzIE5vdEZvdW5kISIgPDwgc3RkOjplbmRsOwoJfQoJc3RkOjpjb3V0IDw8IE1BTUUgPDwgIiBpcyAiOwoJZm9yIChhdXRvJiBvIDogUikgc3RkOjpjb3V0IDw8IHN0ZDo6Z2V0PDA+KG8pKzEgPDwgJywnIDw8IHN0ZDo6Z2V0PDE+KG8pKzEgPDwgIkAiIDw8IHN0ZDo6Z2V0PDI+KG8pIDw8ICcgJzsKCXN0ZDo6Y291dCA8PCBzdGQ6OmVuZGw7CgoJcmV0dXJuIDA7Cn0=