import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
class CommonCharacters {
@SuppressWarnings("boxing")
// Requirement
//
// Always return lowercase versions of common characters. e.g.:
//
// OK: (a, a) -> a
// OK: (a, A) -> a
// OK: (A, A) -> a
// No: (A, A) -> A
// No: (aA, aA) -> aA
//
// Requirement
//
// Return common characters joined in a String, preserving the order in
// which they appeared in the longest argument, or in the first argument if
// the arguments are of the same length.
//
// Requirement
//
// Handle "characters" (i.e. code points) outside the Basic Multilingual
// Plane (BMP), including characters from Supplementary Planes.
// There should be no `char' or `Character' based "false positives". i.e.:
//
// String string1 = "\uD835\uDC00", string2 = "\uD835\uDC01";
//
// string1 and string2 share no characters in the intended acceptation of
// "character".
String shortestArgument, longestArgument
; if (string1.length() < string2.length()) {
shortestArgument = string1;
longestArgument = string2;
} else {
shortestArgument = string2;
longestArgument = string1;
}
// @formatter:off
Set<Integer> codePointsSeen =
shortestArgument.codePoints()
.boxed()
.collect(Collectors.toSet());
List<Integer> codePointsInCommon = new ArrayList<>();
for (Iterator<Integer> iterator = longestArgument.codePoints()
.distinct()
.iterator();
iterator.hasNext() &&
codePointsInCommon.size() < codePointsSeen.size();) {
// @formatter:on
Integer codePoint
= iterator.
next(); int lowerCaseCodePoint
= Character.
toLowerCase(codePoint
); if (codePointsSeen.contains(lowerCaseCodePoint)) {
codePointsInCommon.add(lowerCaseCodePoint);
}
}
StringBuilder stringBuilder = new StringBuilder();
for (Integer codePoint
: codePointsInCommon
) { stringBuilder.appendCodePoint(codePoint);
}
return stringBuilder.toString();
}
@SuppressWarnings("boxing")
public static void main
(String[] args
) { // @formatter:off
String[][] testArgumentsAndExpectedValues
= { { "" , "" , "" },
{ "a" , "" , "" },
{ "" , "a" , "" },
{ "aa" , "" , "" },
{ "" , "aa" , "" },
{ "a" , "a" , "a" },
{ "aa" , "b" , "" },
{ "b" , "aa" , "" },
{ "ab" , "ba" , "ab" },
{ "aba" , "ab" , "ab" },
{ "aba" , "ba" , "ab" },
{ "aba" , "aab" , "ab" },
{ "a" , "A" , "a" },
{ "A" , "a" , "a" },
{ "A" , "A" , "a" },
{ "ab" , "AB" , "ab" },
{ "AB" , "ab" , "ab" },
{ "aB" , "Ab" , "ab" },
{ "aB" , "Ba" , "ab" },
{ "aB" , "Ba" , "ab" },
{ "a" , "\uD835\uDC1A" , "" },
{ "\uD835\uDC1A" , "\uD835\uDC1A" , "\uD835\uDC1A" },
{ "\uD835\uDC00" , "\uD835\uDC00" , "\uD835\uDC00" },
{ "\uD835\uDC1A" , "\uD835\uDC00" , "" },
{ "\uD835\uDC00" , "\uD835\uDC01" , "" },
{ "\uD801\uDC2B" , "\uD801\uDC2B" , "\uD801\uDC2B" },
{ "\uD801\uDC03" , "\uD801\uDC03" , "\uD801\uDC2B" },
{ "\uD801\uDC2B" , "\uD801\uDC03" , "\uD801\uDC2B" },
{ "\uD83D\uDE80" , "\uD83D\uDE80" , "\uD83D\uDE80" },
{ "a" , "aaaaaaaaaaaaaaaaa" , "a" },
// The last test should still work, and work fast, with a second
// argument string starting with "a" and ending _many_ characters later
// The last test values doe not test it, but illustrate the scenario
};
int maximumTestArgumentLength =
Arrays.
stream(testArgumentsAndExpectedValues
) .
flatMap(testValues
-> Arrays.
stream(testValues
) .limit(2))
.max()
.getAsInt();
// @formatter:on
int maximumQuotedTestArgumentLength = maximumTestArgumentLength + 2;
for (int i = 0; i < testArgumentsAndExpectedValues.length; i++) {
String[] currentTestValues
= testArgumentsAndExpectedValues
[i
]; String string1
= currentTestValues
[0]; String string2
= currentTestValues
[1]; String expectedResult
= currentTestValues
[2]; String actualResult
= commonCharactersOf
(string1, string2
); boolean testSuccessful = expectedResult.equals(actualResult);
if (testSuccessful) {
// continue; // TODO: uncomment to filter out successful tests
}
Function
<String, String
> quoteString
= s
-> '"' + s
+ '"'; // @formatter:off
+ "%5s: "
+ "(%-" + maximumQuotedTestArgumentLength + "s"
+ " , "
+ "%-" + maximumQuotedTestArgumentLength + "s)"
+ " -> "
+ "%s "
+ "(%s)"
+ "%n";
System.
out.
printf(outputFormat,
i,
testSuccessful ? "Success" : "Failure",
quoteString.apply(string1),
quoteString.apply(string2),
quoteString.apply(actualResult),
quoteString.apply(expectedResult));
// @formatter:on
}
}
}
ICAgIGltcG9ydCBqYXZhLnV0aWwuQXJyYXlMaXN0OwogICAgaW1wb3J0IGphdmEudXRpbC5BcnJheXM7CiAgICBpbXBvcnQgamF2YS51dGlsLkl0ZXJhdG9yOwogICAgaW1wb3J0IGphdmEudXRpbC5MaXN0OwogICAgaW1wb3J0IGphdmEudXRpbC5TZXQ7CiAgICBpbXBvcnQgamF2YS51dGlsLmZ1bmN0aW9uLkZ1bmN0aW9uOwogICAgaW1wb3J0IGphdmEudXRpbC5zdHJlYW0uQ29sbGVjdG9yczsKICAgIGNsYXNzIENvbW1vbkNoYXJhY3RlcnMgewogICAgICBAU3VwcHJlc3NXYXJuaW5ncygiYm94aW5nIikKICAgICAgcHJpdmF0ZSBzdGF0aWMgU3RyaW5nIGNvbW1vbkNoYXJhY3RlcnNPZihTdHJpbmcgc3RyaW5nMSwgU3RyaW5nIHN0cmluZzIpIHsKICAgICAgICAvLyBSZXF1aXJlbWVudAogICAgICAgIC8vCiAgICAgICAgLy8gQWx3YXlzIHJldHVybiBsb3dlcmNhc2UgdmVyc2lvbnMgb2YgY29tbW9uIGNoYXJhY3RlcnMuIGUuZy46CiAgICAgICAgLy8KICAgICAgICAvLyBPSzogKGEsIGEpIC0+IGEKICAgICAgICAvLyBPSzogKGEsIEEpIC0+IGEKICAgICAgICAvLyBPSzogKEEsIEEpIC0+IGEKICAgICAgICAvLyBObzogKEEsIEEpIC0+IEEKICAgICAgICAvLyBObzogKGFBLCBhQSkgLT4gYUEKICAgICAgICAvLwogICAgICAgIC8vIFJlcXVpcmVtZW50CiAgICAgICAgLy8KICAgICAgICAvLyBSZXR1cm4gY29tbW9uIGNoYXJhY3RlcnMgam9pbmVkIGluIGEgU3RyaW5nLCBwcmVzZXJ2aW5nIHRoZSBvcmRlciBpbgogICAgICAgIC8vIHdoaWNoIHRoZXkgYXBwZWFyZWQgaW4gdGhlIGxvbmdlc3QgYXJndW1lbnQsIG9yIGluIHRoZSBmaXJzdCBhcmd1bWVudCBpZgogICAgICAgIC8vIHRoZSBhcmd1bWVudHMgYXJlIG9mIHRoZSBzYW1lIGxlbmd0aC4KICAgICAgICAvLwogICAgICAgIC8vIFJlcXVpcmVtZW50CiAgICAgICAgLy8KICAgICAgICAvLyBIYW5kbGUgImNoYXJhY3RlcnMiIChpLmUuIGNvZGUgcG9pbnRzKSBvdXRzaWRlIHRoZSBCYXNpYyBNdWx0aWxpbmd1YWwKICAgICAgICAvLyBQbGFuZSAoQk1QKSwgaW5jbHVkaW5nIGNoYXJhY3RlcnMgZnJvbSBTdXBwbGVtZW50YXJ5IFBsYW5lcy4KICAgICAgICAvLyBUaGVyZSBzaG91bGQgYmUgbm8gYGNoYXInIG9yIGBDaGFyYWN0ZXInIGJhc2VkICJmYWxzZSBwb3NpdGl2ZXMiLiBpLmUuOgogICAgICAgIC8vCiAgICAgICAgLy8gU3RyaW5nIHN0cmluZzEgPSAiXHVEODM1XHVEQzAwIiwgc3RyaW5nMiA9ICJcdUQ4MzVcdURDMDEiOwogICAgICAgIC8vCiAgICAgICAgLy8gc3RyaW5nMSBhbmQgc3RyaW5nMiBzaGFyZSBubyBjaGFyYWN0ZXJzIGluIHRoZSBpbnRlbmRlZCBhY2NlcHRhdGlvbiBvZgogICAgICAgIC8vICJjaGFyYWN0ZXIiLgogICAgICAgIFN0cmluZyBzaG9ydGVzdEFyZ3VtZW50LCBsb25nZXN0QXJndW1lbnQ7CiAgICAgICAgaWYgKHN0cmluZzEubGVuZ3RoKCkgPCBzdHJpbmcyLmxlbmd0aCgpKSB7CiAgICAgICAgICBzaG9ydGVzdEFyZ3VtZW50ID0gc3RyaW5nMTsKICAgICAgICAgIGxvbmdlc3RBcmd1bWVudCA9IHN0cmluZzI7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHNob3J0ZXN0QXJndW1lbnQgPSBzdHJpbmcyOwogICAgICAgICAgbG9uZ2VzdEFyZ3VtZW50ID0gc3RyaW5nMTsKICAgICAgICB9CiAgICAgICAgLy8gQGZvcm1hdHRlcjpvZmYKICAgICAgICBTZXQ8SW50ZWdlcj4gY29kZVBvaW50c1NlZW4gPQogICAgICAgICAgICBzaG9ydGVzdEFyZ3VtZW50LmNvZGVQb2ludHMoKQogICAgICAgICAgICAuYm94ZWQoKQogICAgICAgICAgICAubWFwKENoYXJhY3Rlcjo6dG9Mb3dlckNhc2UpCiAgICAgICAgICAgIC5jb2xsZWN0KENvbGxlY3RvcnMudG9TZXQoKSk7CiAgICAgICAgTGlzdDxJbnRlZ2VyPiBjb2RlUG9pbnRzSW5Db21tb24gPSBuZXcgQXJyYXlMaXN0PD4oKTsKICAgICAgICBmb3IgKEl0ZXJhdG9yPEludGVnZXI+IGl0ZXJhdG9yID0gbG9uZ2VzdEFyZ3VtZW50LmNvZGVQb2ludHMoKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAuZGlzdGluY3QoKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAuaXRlcmF0b3IoKTsKICAgICAgICAgICAgIGl0ZXJhdG9yLmhhc05leHQoKSAmJgogICAgICAgICAgICAgY29kZVBvaW50c0luQ29tbW9uLnNpemUoKSA8IGNvZGVQb2ludHNTZWVuLnNpemUoKTspIHsKICAgICAgICAvLyBAZm9ybWF0dGVyOm9uCiAgICAgICAgICBJbnRlZ2VyIGNvZGVQb2ludCA9IGl0ZXJhdG9yLm5leHQoKTsKICAgICAgICAgIGludCBsb3dlckNhc2VDb2RlUG9pbnQgPSBDaGFyYWN0ZXIudG9Mb3dlckNhc2UoY29kZVBvaW50KTsKICAgICAgICAgIGlmIChjb2RlUG9pbnRzU2Vlbi5jb250YWlucyhsb3dlckNhc2VDb2RlUG9pbnQpKSB7CiAgICAgICAgICAgIGNvZGVQb2ludHNJbkNvbW1vbi5hZGQobG93ZXJDYXNlQ29kZVBvaW50KTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgU3RyaW5nQnVpbGRlciBzdHJpbmdCdWlsZGVyID0gbmV3IFN0cmluZ0J1aWxkZXIoKTsKICAgICAgICBmb3IgKEludGVnZXIgY29kZVBvaW50IDogY29kZVBvaW50c0luQ29tbW9uKSB7CiAgICAgICAgICBzdHJpbmdCdWlsZGVyLmFwcGVuZENvZGVQb2ludChjb2RlUG9pbnQpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gc3RyaW5nQnVpbGRlci50b1N0cmluZygpOwogICAgICB9CiAgICAgIEBTdXBwcmVzc1dhcm5pbmdzKCJib3hpbmciKQogICAgICBwdWJsaWMgc3RhdGljIHZvaWQgbWFpbihTdHJpbmdbXSBhcmdzKSB7CiAgICAgICAgLy8gQGZvcm1hdHRlcjpvZmYKICAgICAgICBTdHJpbmdbXVtdIHRlc3RBcmd1bWVudHNBbmRFeHBlY3RlZFZhbHVlcyA9IHsKICAgICAgICAgICAgeyAiIiAgICAgICAgICAgICAgICAgICAgICwgIiIgICAgICAgICAgICAgICAgICAsICIiICAgICAgICAgICAgIH0sCiAgICAgICAgICAgIHsgImEiICAgICAgICAgICAgICAgICAgICAsICIiICAgICAgICAgICAgICAgICAgLCAiIiAgICAgICAgICAgICB9LAogICAgICAgICAgICB7ICIiICAgICAgICAgICAgICAgICAgICAgLCAiYSIgICAgICAgICAgICAgICAgICwgIiIgICAgICAgICAgICAgfSwKICAgICAgICAgICAgeyAiYWEiICAgICAgICAgICAgICAgICAgICwgIiIgICAgICAgICAgICAgICAgICAsICIiICAgICAgICAgICAgIH0sCiAgICAgICAgICAgIHsgIiIgICAgICAgICAgICAgICAgICAgICAsICJhYSIgICAgICAgICAgICAgICAgLCAiIiAgICAgICAgICAgICB9LAogICAgICAgICAgICB7ICJhIiAgICAgICAgICAgICAgICAgICAgLCAiYSIgICAgICAgICAgICAgICAgICwgImEiICAgICAgICAgICAgfSwKICAgICAgICAgICAgeyAiYWEiICAgICAgICAgICAgICAgICAgICwgImIiICAgICAgICAgICAgICAgICAsICIiICAgICAgICAgICAgIH0sCiAgICAgICAgICAgIHsgImIiICAgICAgICAgICAgICAgICAgICAsICJhYSIgICAgICAgICAgICAgICAgLCAiIiAgICAgICAgICAgICB9LAogICAgICAgICAgICB7ICJhYiIgICAgICAgICAgICAgICAgICAgLCAiYmEiICAgICAgICAgICAgICAgICwgImFiIiAgICAgICAgICAgfSwKICAgICAgICAgICAgeyAiYWJhIiAgICAgICAgICAgICAgICAgICwgImFiIiAgICAgICAgICAgICAgICAsICJhYiIgICAgICAgICAgIH0sCiAgICAgICAgICAgIHsgImFiYSIgICAgICAgICAgICAgICAgICAsICJiYSIgICAgICAgICAgICAgICAgLCAiYWIiICAgICAgICAgICB9LAogICAgICAgICAgICB7ICJhYmEiICAgICAgICAgICAgICAgICAgLCAiYWFiIiAgICAgICAgICAgICAgICwgImFiIiAgICAgICAgICAgfSwKICAgICAgICAgICAgeyAiYSIgICAgICAgICAgICAgICAgICAgICwgIkEiICAgICAgICAgICAgICAgICAsICJhIiAgICAgICAgICAgIH0sCiAgICAgICAgICAgIHsgIkEiICAgICAgICAgICAgICAgICAgICAsICJhIiAgICAgICAgICAgICAgICAgLCAiYSIgICAgICAgICAgICB9LAogICAgICAgICAgICB7ICJBIiAgICAgICAgICAgICAgICAgICAgLCAiQSIgICAgICAgICAgICAgICAgICwgImEiICAgICAgICAgICAgfSwKICAgICAgICAgICAgeyAiYWIiICAgICAgICAgICAgICAgICAgICwgIkFCIiAgICAgICAgICAgICAgICAsICJhYiIgICAgICAgICAgIH0sCiAgICAgICAgICAgIHsgIkFCIiAgICAgICAgICAgICAgICAgICAsICJhYiIgICAgICAgICAgICAgICAgLCAiYWIiICAgICAgICAgICB9LAogICAgICAgICAgICB7ICJhQiIgICAgICAgICAgICAgICAgICAgLCAiQWIiICAgICAgICAgICAgICAgICwgImFiIiAgICAgICAgICAgfSwKICAgICAgICAgICAgeyAiYUIiICAgICAgICAgICAgICAgICAgICwgIkJhIiAgICAgICAgICAgICAgICAsICJhYiIgICAgICAgICAgIH0sCiAgICAgICAgICAgIHsgImFCIiAgICAgICAgICAgICAgICAgICAsICJCYSIgICAgICAgICAgICAgICAgLCAiYWIiICAgICAgICAgICB9LAogICAgICAgICAgICB7ICJhIiAgICAgICAgICAgICAgICAgICAgLCAiXHVEODM1XHVEQzFBIiAgICAgICwgIiIgICAgICAgICAgICAgfSwKICAgICAgICAgICAgeyAiXHVEODM1XHVEQzFBIiAgICAgICAgICwgIlx1RDgzNVx1REMxQSIgICAgICAsICJcdUQ4MzVcdURDMUEiIH0sCiAgICAgICAgICAgIHsgIlx1RDgzNVx1REMwMCIgICAgICAgICAsICJcdUQ4MzVcdURDMDAiICAgICAgLCAiXHVEODM1XHVEQzAwIiB9LAogICAgICAgICAgICB7ICJcdUQ4MzVcdURDMUEiICAgICAgICAgLCAiXHVEODM1XHVEQzAwIiAgICAgICwgIiIgICAgICAgICAgICAgfSwKICAgICAgICAgICAgeyAiXHVEODM1XHVEQzAwIiAgICAgICAgICwgIlx1RDgzNVx1REMwMSIgICAgICAsICIiICAgICAgICAgICAgIH0sCiAgICAgICAgICAgIHsgIlx1RDgwMVx1REMyQiIgICAgICAgICAsICJcdUQ4MDFcdURDMkIiICAgICAgLCAiXHVEODAxXHVEQzJCIiB9LAogICAgICAgICAgICB7ICJcdUQ4MDFcdURDMDMiICAgICAgICAgLCAiXHVEODAxXHVEQzAzIiAgICAgICwgIlx1RDgwMVx1REMyQiIgfSwKICAgICAgICAgICAgeyAiXHVEODAxXHVEQzJCIiAgICAgICAgICwgIlx1RDgwMVx1REMwMyIgICAgICAsICJcdUQ4MDFcdURDMkIiIH0sCiAgICAgICAgICAgIHsgIlx1RDgzRFx1REU4MCIgICAgICAgICAsICJcdUQ4M0RcdURFODAiICAgICAgLCAiXHVEODNEXHVERTgwIiB9LAogICAgICAgICAgICB7ICJhIiAgICAgICAgICAgICAgICAgICAgLCAiYWFhYWFhYWFhYWFhYWFhYWEiICwgImEiICAgICAgICAgICAgfSwKICAgICAgICAgICAgLy8gVGhlIGxhc3QgdGVzdCBzaG91bGQgc3RpbGwgd29yaywgYW5kIHdvcmsgZmFzdCwgd2l0aCBhIHNlY29uZAogICAgICAgICAgICAvLyBhcmd1bWVudCBzdHJpbmcgc3RhcnRpbmcgd2l0aCAiYSIgYW5kIGVuZGluZyBfbWFueV8gY2hhcmFjdGVycyBsYXRlcgogICAgICAgICAgICAvLyBUaGUgbGFzdCB0ZXN0IHZhbHVlcyBkb2Ugbm90IHRlc3QgaXQsIGJ1dCBpbGx1c3RyYXRlIHRoZSBzY2VuYXJpbwogICAgICAgIH07CiAgICAgICAgaW50IG1heGltdW1UZXN0QXJndW1lbnRMZW5ndGggPQogICAgICAgICAgICBBcnJheXMuc3RyZWFtKHRlc3RBcmd1bWVudHNBbmRFeHBlY3RlZFZhbHVlcykKICAgICAgICAgICAgICAgICAgLmZsYXRNYXAodGVzdFZhbHVlcyAtPiBBcnJheXMuc3RyZWFtKHRlc3RWYWx1ZXMpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLmxpbWl0KDIpKQogICAgICAgICAgICAgICAgICAubWFwVG9JbnQoU3RyaW5nOjpsZW5ndGgpCiAgICAgICAgICAgICAgICAgIC5tYXgoKQogICAgICAgICAgICAgICAgICAuZ2V0QXNJbnQoKTsKICAgICAgICAvLyBAZm9ybWF0dGVyOm9uCiAgICAgICAgaW50IG1heGltdW1RdW90ZWRUZXN0QXJndW1lbnRMZW5ndGggPSBtYXhpbXVtVGVzdEFyZ3VtZW50TGVuZ3RoICsgMjsKICAgICAgICBmb3IgKGludCBpID0gMDsgaSA8IHRlc3RBcmd1bWVudHNBbmRFeHBlY3RlZFZhbHVlcy5sZW5ndGg7IGkrKykgewogICAgICAgICAgU3RyaW5nW10gY3VycmVudFRlc3RWYWx1ZXMgPSB0ZXN0QXJndW1lbnRzQW5kRXhwZWN0ZWRWYWx1ZXNbaV07CiAgICAgICAgICBTdHJpbmcgc3RyaW5nMSA9IGN1cnJlbnRUZXN0VmFsdWVzWzBdOwogICAgICAgICAgU3RyaW5nIHN0cmluZzIgPSBjdXJyZW50VGVzdFZhbHVlc1sxXTsKICAgICAgICAgIFN0cmluZyBleHBlY3RlZFJlc3VsdCA9IGN1cnJlbnRUZXN0VmFsdWVzWzJdOwogICAgICAgICAgU3RyaW5nIGFjdHVhbFJlc3VsdCA9IGNvbW1vbkNoYXJhY3RlcnNPZihzdHJpbmcxLCBzdHJpbmcyKTsKICAgICAgICAgIGJvb2xlYW4gdGVzdFN1Y2Nlc3NmdWwgPSBleHBlY3RlZFJlc3VsdC5lcXVhbHMoYWN0dWFsUmVzdWx0KTsKICAgICAgICAgIGlmICh0ZXN0U3VjY2Vzc2Z1bCkgewogICAgICAgICAgICAvLyBjb250aW51ZTsgLy8gVE9ETzogdW5jb21tZW50IHRvIGZpbHRlciBvdXQgc3VjY2Vzc2Z1bCB0ZXN0cwogICAgICAgICAgfQogICAgICAgICAgRnVuY3Rpb248U3RyaW5nLCBTdHJpbmc+IHF1b3RlU3RyaW5nID0gcyAtPiAnIicgKyBzICsgJyInOwogICAgICAgICAgLy8gQGZvcm1hdHRlcjpvZmYKICAgICAgICAgIFN0cmluZyBvdXRwdXRGb3JtYXQgPSAiJTJkKSAiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICsgIiU1czogIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICArICIoJS0iICsgbWF4aW11bVF1b3RlZFRlc3RBcmd1bWVudExlbmd0aCArICJzIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICArICIgLCAiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICsgIiUtIiArIG1heGltdW1RdW90ZWRUZXN0QXJndW1lbnRMZW5ndGggKyAicykiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICsgIiAtPiAiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICsgIiVzICIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKyAiKCVzKSIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKyAiJW4iOwogICAgICAgICAgU3lzdGVtLm91dC5wcmludGYob3V0cHV0Rm9ybWF0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgaSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRlc3RTdWNjZXNzZnVsID8gIlN1Y2Nlc3MiIDogIkZhaWx1cmUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgcXVvdGVTdHJpbmcuYXBwbHkoc3RyaW5nMSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBxdW90ZVN0cmluZy5hcHBseShzdHJpbmcyKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHF1b3RlU3RyaW5nLmFwcGx5KGFjdHVhbFJlc3VsdCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBxdW90ZVN0cmluZy5hcHBseShleHBlY3RlZFJlc3VsdCkpOwogICAgICAgICAgLy8gQGZvcm1hdHRlcjpvbgogICAgICAgIH0KICAgICAgfQogICAgfQoK