/* package whatever; // don't place package name! */
import java.util.* ;
import java.lang.* ;
import java.io.* ;
/* Name of the class has to be "Main" only if the class is public. */
class Ideone
{
{
System .
out .
println ( BaseConverter.
changeBase ( "" + 0x7FFF_FFFF_FFFF_FFFFL,
10 ,
16 ,
true ) ) ; try {
System .
out .
println ( BaseConverter.
changeBase ( "" + 100000 ,
10 ,
70000 ,
true ) ) ; System .
out .
println ( "Infinite loop handled via " + e.
getClass ( ) .
getName ( ) + ": " + e.
getMessage ( ) ) ; }
System .
out .
println ( BaseConverter.
changeBase ( "0" ,
10 ,
16 ,
true ) ) ; System .
out .
println ( BaseConverter.
changeBase ( "-0" ,
10 ,
16 ,
true ) ) ; try {
System .
out .
println ( BaseConverter.
changeBase ( "--1" ,
10 ,
16 ,
true ) ) ; System .
out .
println ( "--1 handled via " + e.
getClass ( ) .
getName ( ) + ": " + e.
getMessage ( ) ) ; }
try {
System .
out .
println ( BaseConverter.
changeBase ( "1-1" ,
10 ,
16 ,
true ) ) ; System .
out .
println ( "1-1 handled via " + e.
getClass ( ) .
getName ( ) + ": " + e.
getMessage ( ) ) ; }
}
}
class BaseConverter {
protected static final String negativeBaseErrorMessage
= "Negative or zero base values are illegal - supplied bases were %d & %d." ,
invalidInputNumberErrorMessage = "The supplied number (%s) for base conversion is invalid." ,
tooLargeBaseForLookupErrorMessage = "Not enough available characters for substitution. Number of available characters is %d , minimum required number is %d" ;
private static String lookup
= "0123456789ABCDEFGHIJKLMNOPQRSTWXYZabcdefghijklmnopqrstwxyz+/=,?!;:\" '^`~|\\ @#$%&*_<>(){}" ; private static StringBuilder builder = new StringBuilder( lookup) ;
private static void updateLookup( int base) {
int charsToAdd = base - lookup.length ( ) ;
if ( charsToAdd > 0 ) {
for ( int i
= 0 ; i
< Character .
MAX_VALUE && charsToAdd
> 0 ; ++ i
) { if ( ( ! oldLookup.contains ( "" + ( char ) i) ) &&
( ( char ) i != '.' ) && ( char ) i != '-' ) {
builder.append ( ( char ) i) ;
-- charsToAdd;
}
}
}
lookup = builder.toString ( ) ;
if ( charsToAdd > 0 ) {
}
}
public static long convertToNumber
( String inputNumber,
int from_base
) { if ( from_base >= lookup.length ( ) ) {
updateLookup( from_base) ;
}
long number = 0 ;
int length = inputNumber.length ( ) ;
for ( int i = 0 ; i < length; ++ i) {
long digitValue = lookup.indexOf ( inputNumber.charAt ( i) ) ;
if ( digitValue < 0 ) { //this digit does not exist in the lookup, so the input is incorrect
}
number
+= digitValue
* Math .
round ( Math .
pow ( from_base, length
- 1 - i
) ) ; }
return number;
}
private static int countDigits( long number, int to_base) {
int num_digits = 0 ;
while ( number > 0 ) {
number /= to_base;
++ num_digits;
}
return num_digits;
}
private static int [ ] createDigits( long number, int to_base) {
int [ ] digits = new int [ countDigits( number, to_base) ] ;
int num_digits = 0 ;
while ( number > 0 ) {
digits[ num_digits++ ] = ( int ) ( number % to_base) ;
number /= to_base;
}
return digits;
}
public static String changeBase
( String inputNumber,
int from_base,
int to_base
) { return changeBase( inputNumber, from_base, to_base, true ) ;
}
private static boolean isInvalidInputNumber
( String inputNumber,
int from_base
) { //there should be no more than 1 - sign, which should have been removed already if it exists
return inputNumber.contains ( "-" ) ||
//there should be no more than 1 fixed point, which should have been removed already if it exists
inputNumber.contains ( "." ) ||
//there should be no characters in the string which indicate values for a digit greater than the current base
( ! inputNumber.
matches ( String .
format ( "^[%s]*$" , lookup.
substring ( 0 , from_base
) ) ) ) ; }
public static String changeBase
( String inputNumber,
int from_base,
int to_base,
boolean substituteNumerics
) { boolean isNegative = false ;
if ( inputNumber.startsWith ( "-" ) ) {
//the provided number is (supposedly) negative
inputNumber = inputNumber.substring ( 1 , inputNumber.length ( ) ) ;
isNegative = true ;
}
if ( from_base <= 0 || to_base <= 0 ) {
//negative or zero bases can't be handled using simple integer arithmetic
}
updateLookup
( Math .
max ( from_base, to_base
) ) ; if ( inputNumber.contains ( "." ) ) {
return changeBase( inputNumber.substring ( 0 , inputNumber.indexOf ( "." ) ) , from_base, to_base, substituteNumerics) /*Integer part*/ + "." +
changeBase( inputNumber.substring ( inputNumber.indexOf ( "." ) + 1 , inputNumber.length ( ) ) , from_base, to_base, substituteNumerics) /*Fractional part*/ ;
}
//checking for invalid numbers is easier now when negatives and fixed points should have been taken care of
if ( isInvalidInputNumber( inputNumber, from_base) ) {
}
//special handling for 0 to avoid undefined behaviour and other bugs
if ( inputNumber.matches ( "^[0]+$" ) ) { //check for any number of only 0s in the input
return ( isNegative) ? "-" + lookup.charAt ( 0 ) : lookup.charAt ( 0 ) + "" ; //I could simply return "0", but this looks less hardcoded
}
int [ ] digits = createDigits( convertToNumber( inputNumber, from_base) , to_base) ;
if ( substituteNumerics) {
//use character representation for digits
for ( int i = digits.length - 1 ; i >= 0 ; -- i) {
new_number += lookup.charAt ( digits[ i] ) ;
}
} else {
//use numeric representations for digits, separate using space
for ( int i = digits.length - 1 ; i >= 0 ; -- i) {
new_number += digits[ i] + " " ;
}
}
return ( isNegative) ? "-" + new_number.trim ( ) : new_number.trim ( ) ;
}
}
LyogcGFja2FnZSB3aGF0ZXZlcjsgLy8gZG9uJ3QgcGxhY2UgcGFja2FnZSBuYW1lISAqLwoKaW1wb3J0IGphdmEudXRpbC4qOwppbXBvcnQgamF2YS5sYW5nLio7CmltcG9ydCBqYXZhLmlvLio7CgovKiBOYW1lIG9mIHRoZSBjbGFzcyBoYXMgdG8gYmUgIk1haW4iIG9ubHkgaWYgdGhlIGNsYXNzIGlzIHB1YmxpYy4gKi8KY2xhc3MgSWRlb25lCnsKCXB1YmxpYyBzdGF0aWMgdm9pZCBtYWluIChTdHJpbmdbXSBhcmdzKSB0aHJvd3MgamF2YS5sYW5nLkV4Y2VwdGlvbgoJewoJCVN5c3RlbS5vdXQucHJpbnRsbihCYXNlQ29udmVydGVyLmNoYW5nZUJhc2UoIiIrMHg3RkZGX0ZGRkZfRkZGRl9GRkZGTCwgMTAsIDE2LCB0cnVlKSk7CgkJdHJ5ewoJCSAgIFN5c3RlbS5vdXQucHJpbnRsbihCYXNlQ29udmVydGVyLmNoYW5nZUJhc2UoIiIrMTAwMDAwLCAxMCwgNzAwMDAsIHRydWUpKTsKCQl9IGNhdGNoIChFeGNlcHRpb24gZSl7CgkJCVN5c3RlbS5vdXQucHJpbnRsbigiSW5maW5pdGUgbG9vcCBoYW5kbGVkIHZpYSAiK2UuZ2V0Q2xhc3MoKS5nZXROYW1lKCkrIjogIitlLmdldE1lc3NhZ2UoKSk7CgkJfQoJCVN5c3RlbS5vdXQucHJpbnRsbihCYXNlQ29udmVydGVyLmNoYW5nZUJhc2UoIjAiLCAxMCwgMTYsIHRydWUpKTsKCQlTeXN0ZW0ub3V0LnByaW50bG4oQmFzZUNvbnZlcnRlci5jaGFuZ2VCYXNlKCItMCIsIDEwLCAxNiwgdHJ1ZSkpOwoJCXRyeXsKCQlTeXN0ZW0ub3V0LnByaW50bG4oQmFzZUNvbnZlcnRlci5jaGFuZ2VCYXNlKCItLTEiLCAxMCwgMTYsIHRydWUpKTsKCQl9IGNhdGNoKEV4Y2VwdGlvbiBlKXsKCQkJU3lzdGVtLm91dC5wcmludGxuKCItLTEgaGFuZGxlZCB2aWEgIitlLmdldENsYXNzKCkuZ2V0TmFtZSgpKyI6ICIrZS5nZXRNZXNzYWdlKCkpOwoJCX0KCQl0cnl7CgkJU3lzdGVtLm91dC5wcmludGxuKEJhc2VDb252ZXJ0ZXIuY2hhbmdlQmFzZSgiMS0xIiwgMTAsIDE2LCB0cnVlKSk7CgkJfSBjYXRjaChFeGNlcHRpb24gZSl7CgkJCVN5c3RlbS5vdXQucHJpbnRsbigiMS0xIGhhbmRsZWQgdmlhICIrZS5nZXRDbGFzcygpLmdldE5hbWUoKSsiOiAiK2UuZ2V0TWVzc2FnZSgpKTsKCQl9CiAgICB9Cn0KCmNsYXNzIEJhc2VDb252ZXJ0ZXIgewogICAgcHJvdGVjdGVkIHN0YXRpYyBmaW5hbCBTdHJpbmcgbmVnYXRpdmVCYXNlRXJyb3JNZXNzYWdlID0gIk5lZ2F0aXZlIG9yIHplcm8gYmFzZSB2YWx1ZXMgYXJlIGlsbGVnYWwgLSBzdXBwbGllZCBiYXNlcyB3ZXJlICVkICYgJWQuIiwgCiAgICBpbnZhbGlkSW5wdXROdW1iZXJFcnJvck1lc3NhZ2UgPSAiVGhlIHN1cHBsaWVkIG51bWJlciAoJXMpIGZvciBiYXNlIGNvbnZlcnNpb24gaXMgaW52YWxpZC4iLCAKICAgIHRvb0xhcmdlQmFzZUZvckxvb2t1cEVycm9yTWVzc2FnZSA9ICJOb3QgZW5vdWdoIGF2YWlsYWJsZSBjaGFyYWN0ZXJzIGZvciBzdWJzdGl0dXRpb24uIE51bWJlciBvZiBhdmFpbGFibGUgY2hhcmFjdGVycyBpcyAlZCAsIG1pbmltdW0gcmVxdWlyZWQgbnVtYmVyIGlzICVkIjsKCiAgICAKICAgIHByaXZhdGUgc3RhdGljIFN0cmluZyBsb29rdXAgPSAiMDEyMzQ1Njc4OUFCQ0RFRkdISUpLTE1OT1BRUlNUV1hZWmFiY2RlZmdoaWprbG1ub3BxcnN0d3h5eisvPSw/ITs6XCInXmB+fFxcQCMkJSYqXzw+KCl7fSI7CiAgICBwcml2YXRlIHN0YXRpYyBTdHJpbmdCdWlsZGVyIGJ1aWxkZXIgPSBuZXcgU3RyaW5nQnVpbGRlcihsb29rdXApOwoKICAgIHByaXZhdGUgc3RhdGljIHZvaWQgdXBkYXRlTG9va3VwKGludCBiYXNlKSB7CiAgICAgICAgaW50IGNoYXJzVG9BZGQgPSBiYXNlIC0gbG9va3VwLmxlbmd0aCgpOwogICAgICAgIFN0cmluZyBvbGRMb29rdXAgPSBsb29rdXA7CiAgICAgICAgaWYgKGNoYXJzVG9BZGQgPiAwKSB7CiAgICAgICAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgQ2hhcmFjdGVyLk1BWF9WQUxVRSAmJiBjaGFyc1RvQWRkID4gMDsgKytpKSB7CiAgICAgICAgICAgIAlpZiAoKCFvbGRMb29rdXAuY29udGFpbnMoIiIgKyAoY2hhcikgaSkpICYmCiAgICAgICAgICAgICAgICAgICAgICAgICghQ2hhcmFjdGVyLmlzSVNPQ29udHJvbCgoY2hhcikgaSkpICYmCiAgICAgICAgICAgICAgICAgICAgICAgICghQ2hhcmFjdGVyLmlzV2hpdGVzcGFjZSgoY2hhcikgaSkpICYmCiAgICAgICAgICAgICAgICAgICAgICAgICgoY2hhcikgaSAhPSAnLicpICYmIChjaGFyKSBpICE9ICctJykgewogICAgICAgICAgICAgICAgICAgIGJ1aWxkZXIuYXBwZW5kKChjaGFyKSBpKTsKICAgICAgICAgICAgICAgICAgICAtLWNoYXJzVG9BZGQ7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgbG9va3VwID0gYnVpbGRlci50b1N0cmluZygpOwogICAgICAgIGlmIChjaGFyc1RvQWRkID4gMCkgewogICAgICAgICAgICB0aHJvdyBuZXcgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKFN0cmluZy5mb3JtYXQodG9vTGFyZ2VCYXNlRm9yTG9va3VwRXJyb3JNZXNzYWdlLCBsb29rdXAubGVuZ3RoKCksIGJhc2UpKTsKICAgICAgICB9CiAgICB9CiAgICBwdWJsaWMgc3RhdGljIGxvbmcgY29udmVydFRvTnVtYmVyKFN0cmluZyBpbnB1dE51bWJlciwgaW50IGZyb21fYmFzZSkgewogICAgICAgIGlmIChmcm9tX2Jhc2UgPj0gbG9va3VwLmxlbmd0aCgpKSB7CiAgICAgICAgICAgIHVwZGF0ZUxvb2t1cChmcm9tX2Jhc2UpOwogICAgICAgIH0KICAgICAgICBsb25nIG51bWJlciA9IDA7CiAgICAgICAgaW50IGxlbmd0aCA9IGlucHV0TnVtYmVyLmxlbmd0aCgpOwogICAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgbGVuZ3RoOyArK2kpIHsKICAgICAgICAgICAgbG9uZyBkaWdpdFZhbHVlID0gbG9va3VwLmluZGV4T2YoaW5wdXROdW1iZXIuY2hhckF0KGkpKTsKICAgICAgICAgICAgaWYgKGRpZ2l0VmFsdWUgPCAwKSB7Ly90aGlzIGRpZ2l0IGRvZXMgbm90IGV4aXN0IGluIHRoZSBsb29rdXAsIHNvIHRoZSBpbnB1dCBpcyBpbmNvcnJlY3QKICAgICAgICAgICAgICAgIHRocm93IG5ldyBJbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oU3RyaW5nLmZvcm1hdChpbnZhbGlkSW5wdXROdW1iZXJFcnJvck1lc3NhZ2UsIGlucHV0TnVtYmVyKSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgbnVtYmVyICs9IGRpZ2l0VmFsdWUgKiBNYXRoLnJvdW5kKE1hdGgucG93KGZyb21fYmFzZSwgbGVuZ3RoIC0gMSAtIGkpKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIG51bWJlcjsKICAgIH0KICAgIHByaXZhdGUgc3RhdGljIGludCBjb3VudERpZ2l0cyhsb25nIG51bWJlciwgaW50IHRvX2Jhc2UpIHsKICAgICAgICBpbnQgbnVtX2RpZ2l0cyA9IDA7CiAgICAgICAgd2hpbGUgKG51bWJlciA+IDApIHsKICAgICAgICAgICAgbnVtYmVyIC89IHRvX2Jhc2U7CiAgICAgICAgICAgICsrbnVtX2RpZ2l0czsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIG51bV9kaWdpdHM7CiAgICB9CiAgICBwcml2YXRlIHN0YXRpYyBpbnRbXSBjcmVhdGVEaWdpdHMobG9uZyBudW1iZXIsIGludCB0b19iYXNlKSB7CiAgICAgICAgaW50W10gZGlnaXRzID0gbmV3IGludFtjb3VudERpZ2l0cyhudW1iZXIsIHRvX2Jhc2UpXTsKICAgICAgICBpbnQgbnVtX2RpZ2l0cyA9IDA7CiAgICAgICAgd2hpbGUgKG51bWJlciA+IDApIHsKICAgICAgICAgICAgZGlnaXRzW251bV9kaWdpdHMrK10gPSAoaW50KSAobnVtYmVyICUgdG9fYmFzZSk7CiAgICAgICAgICAgIG51bWJlciAvPSB0b19iYXNlOwogICAgICAgIH0KICAgICAgICByZXR1cm4gZGlnaXRzOwogICAgfQogICAgcHVibGljIHN0YXRpYyBTdHJpbmcgY2hhbmdlQmFzZShTdHJpbmcgaW5wdXROdW1iZXIsIGludCBmcm9tX2Jhc2UsIGludCB0b19iYXNlKSB7CiAgICAgICAgcmV0dXJuIGNoYW5nZUJhc2UoaW5wdXROdW1iZXIsIGZyb21fYmFzZSwgdG9fYmFzZSwgdHJ1ZSk7CiAgICB9CiAgICBwcml2YXRlIHN0YXRpYyBib29sZWFuIGlzSW52YWxpZElucHV0TnVtYmVyKFN0cmluZyBpbnB1dE51bWJlciwgaW50IGZyb21fYmFzZSkgewogICAgICAgIC8vdGhlcmUgc2hvdWxkIGJlIG5vIG1vcmUgdGhhbiAxIC0gc2lnbiwgd2hpY2ggc2hvdWxkIGhhdmUgYmVlbiByZW1vdmVkIGFscmVhZHkgaWYgaXQgZXhpc3RzCiAgICAgICAgcmV0dXJuIGlucHV0TnVtYmVyLmNvbnRhaW5zKCItIikgfHwKICAgICAgICAgICAgICAgIC8vdGhlcmUgc2hvdWxkIGJlIG5vIG1vcmUgdGhhbiAxIGZpeGVkIHBvaW50LCB3aGljaCBzaG91bGQgaGF2ZSBiZWVuIHJlbW92ZWQgYWxyZWFkeSBpZiBpdCBleGlzdHMKICAgICAgICAgICAgICAgIGlucHV0TnVtYmVyLmNvbnRhaW5zKCIuIikgfHwKICAgICAgICAgICAgICAgIC8vdGhlcmUgc2hvdWxkIGJlIG5vIGNoYXJhY3RlcnMgaW4gdGhlIHN0cmluZyB3aGljaCBpbmRpY2F0ZSB2YWx1ZXMgZm9yIGEgZGlnaXQgZ3JlYXRlciB0aGFuIHRoZSBjdXJyZW50IGJhc2UKICAgICAgICAgICAgICAgICghaW5wdXROdW1iZXIubWF0Y2hlcyhTdHJpbmcuZm9ybWF0KCJeWyVzXSokIiwgbG9va3VwLnN1YnN0cmluZygwLCBmcm9tX2Jhc2UpKSkpOwogICAgfQogICAgcHVibGljIHN0YXRpYyBTdHJpbmcgY2hhbmdlQmFzZShTdHJpbmcgaW5wdXROdW1iZXIsIGludCBmcm9tX2Jhc2UsIGludCB0b19iYXNlLCBib29sZWFuIHN1YnN0aXR1dGVOdW1lcmljcykgewogICAgICAgIGJvb2xlYW4gaXNOZWdhdGl2ZSA9IGZhbHNlOwogICAgICAgIGlmIChpbnB1dE51bWJlci5zdGFydHNXaXRoKCItIikpIHsKICAgICAgICAgICAgLy90aGUgcHJvdmlkZWQgbnVtYmVyIGlzIChzdXBwb3NlZGx5KSBuZWdhdGl2ZQogICAgICAgICAgICBpbnB1dE51bWJlciA9IGlucHV0TnVtYmVyLnN1YnN0cmluZygxLCBpbnB1dE51bWJlci5sZW5ndGgoKSk7CiAgICAgICAgICAgIGlzTmVnYXRpdmUgPSB0cnVlOwogICAgICAgIH0KICAgICAgICBpZiAoZnJvbV9iYXNlIDw9IDAgfHwgdG9fYmFzZSA8PSAwKSB7CiAgICAgICAgICAgIC8vbmVnYXRpdmUgb3IgemVybyBiYXNlcyBjYW4ndCBiZSBoYW5kbGVkIHVzaW5nIHNpbXBsZSBpbnRlZ2VyIGFyaXRobWV0aWMKICAgICAgICAgICAgdGhyb3cgbmV3IElsbGVnYWxBcmd1bWVudEV4Y2VwdGlvbihTdHJpbmcuZm9ybWF0KG5lZ2F0aXZlQmFzZUVycm9yTWVzc2FnZSwgZnJvbV9iYXNlLCB0b19iYXNlKSk7CiAgICAgICAgfQogICAgICAgIHVwZGF0ZUxvb2t1cChNYXRoLm1heChmcm9tX2Jhc2UsIHRvX2Jhc2UpKTsKICAgICAgICBpZiAoaW5wdXROdW1iZXIuY29udGFpbnMoIi4iKSkgewogICAgICAgICAgICByZXR1cm4gY2hhbmdlQmFzZShpbnB1dE51bWJlci5zdWJzdHJpbmcoMCwgaW5wdXROdW1iZXIuaW5kZXhPZigiLiIpKSwgZnJvbV9iYXNlLCB0b19iYXNlLCBzdWJzdGl0dXRlTnVtZXJpY3MpLypJbnRlZ2VyIHBhcnQqLyArICIuIiArCiAgICAgICAgICAgICAgICAgICAgY2hhbmdlQmFzZShpbnB1dE51bWJlci5zdWJzdHJpbmcoaW5wdXROdW1iZXIuaW5kZXhPZigiLiIpICsgMSwgaW5wdXROdW1iZXIubGVuZ3RoKCkpLCBmcm9tX2Jhc2UsIHRvX2Jhc2UsIHN1YnN0aXR1dGVOdW1lcmljcykvKkZyYWN0aW9uYWwgcGFydCovOwogICAgICAgIH0KICAgICAgICAvL2NoZWNraW5nIGZvciBpbnZhbGlkIG51bWJlcnMgaXMgZWFzaWVyIG5vdyB3aGVuIG5lZ2F0aXZlcyBhbmQgZml4ZWQgcG9pbnRzIHNob3VsZCBoYXZlIGJlZW4gdGFrZW4gY2FyZSBvZgogICAgICAgIGlmIChpc0ludmFsaWRJbnB1dE51bWJlcihpbnB1dE51bWJlciwgZnJvbV9iYXNlKSkgewogICAgICAgICAgICB0aHJvdyBuZXcgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKFN0cmluZy5mb3JtYXQoaW52YWxpZElucHV0TnVtYmVyRXJyb3JNZXNzYWdlLCBpbnB1dE51bWJlcikpOwogICAgICAgIH0KICAgICAgICAvL3NwZWNpYWwgaGFuZGxpbmcgZm9yIDAgdG8gYXZvaWQgdW5kZWZpbmVkIGJlaGF2aW91ciBhbmQgb3RoZXIgYnVncwogICAgICAgIGlmIChpbnB1dE51bWJlci5tYXRjaGVzKCJeWzBdKyQiKSkgey8vY2hlY2sgZm9yIGFueSBudW1iZXIgb2Ygb25seSAwcyBpbiB0aGUgaW5wdXQKICAgICAgICAgICAgcmV0dXJuIChpc05lZ2F0aXZlKSA/ICItIiArIGxvb2t1cC5jaGFyQXQoMCkgOiBsb29rdXAuY2hhckF0KDApICsgIiI7Ly9JIGNvdWxkIHNpbXBseSByZXR1cm4gIjAiLCBidXQgdGhpcyBsb29rcyBsZXNzIGhhcmRjb2RlZAogICAgICAgIH0KICAgICAgICBTdHJpbmcgbmV3X251bWJlciA9ICIiOwogICAgICAgIGludFtdIGRpZ2l0cyA9IGNyZWF0ZURpZ2l0cyhjb252ZXJ0VG9OdW1iZXIoaW5wdXROdW1iZXIsIGZyb21fYmFzZSksIHRvX2Jhc2UpOwogICAgICAgIGlmIChzdWJzdGl0dXRlTnVtZXJpY3MpIHsKICAgICAgICAgICAgLy91c2UgY2hhcmFjdGVyIHJlcHJlc2VudGF0aW9uIGZvciBkaWdpdHMKICAgICAgICAgICAgZm9yIChpbnQgaSA9IGRpZ2l0cy5sZW5ndGggLSAxOyBpID49IDA7IC0taSkgewogICAgICAgICAgICAgICAgbmV3X251bWJlciArPSBsb29rdXAuY2hhckF0KGRpZ2l0c1tpXSk7CiAgICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAvL3VzZSBudW1lcmljIHJlcHJlc2VudGF0aW9ucyBmb3IgZGlnaXRzLCBzZXBhcmF0ZSB1c2luZyBzcGFjZQogICAgICAgICAgICBmb3IgKGludCBpID0gZGlnaXRzLmxlbmd0aCAtIDE7IGkgPj0gMDsgLS1pKSB7CiAgICAgICAgICAgICAgICBuZXdfbnVtYmVyICs9IGRpZ2l0c1tpXSArICIgIjsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICByZXR1cm4gKGlzTmVnYXRpdmUpID8gIi0iICsgbmV3X251bWJlci50cmltKCkgOiBuZXdfbnVtYmVyLnRyaW0oKTsKICAgIH0KfSAgIA==