import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
class Test
{
private static Map
<String, Integer
> tagToIgnores
= new HashMap
<>(); private static Map
<String, Integer
> tagToUsage
= new HashMap
<>();
static
{
tagToIgnores.put("c#", 23790);
tagToIgnores.put("php", 23721);
tagToIgnores.put("java", 22250);
tagToIgnores.put("android", 22201);
tagToIgnores.put("asp.net", 17320);
tagToIgnores.put("c++", 15191);
tagToIgnores.put("python", 14869);
tagToIgnores.put(".net", 13293);
tagToIgnores.put("ruby", 12691);
tagToIgnores.put("ios", 11896);
tagToIgnores.put("ruby-on-rails", 11819);
tagToIgnores.put("iphone", 10955);
tagToIgnores.put("javascript", 10078);
tagToIgnores.put("objective-c", 8587);
tagToIgnores.put("vb.net", 7892);
tagToIgnores.put("c", 7767);
tagToIgnores.put("jquery", 6939);
tagToIgnores.put("delphi", 6563);
tagToIgnores.put("django", 6423);
tagToIgnores.put("perl", 5925);
tagToIgnores.put("asp.net-mvc", 5887);
tagToIgnores.put("flash", 5569);
tagToIgnores.put("mysql", 5142);
tagToIgnores.put("windows", 5131);
tagToIgnores.put("facebook", 4851);
tagToIgnores.put("r", 4629);
tagToIgnores.put("wpf", 4484);
tagToIgnores.put("visual-studio", 4392);
tagToIgnores.put("angularjs", 4298);
tagToIgnores.put("flex", 4186);
tagToIgnores.put("sql-server", 4108);
tagToIgnores.put("wordpress", 4076);
tagToIgnores.put("silverlight", 4016);
tagToIgnores.put("oracle", 4005);
tagToIgnores.put("css", 3972);
tagToIgnores.put("haskell", 3752);
tagToIgnores.put("scala", 3737);
tagToIgnores.put("html", 3663);
tagToIgnores.put("vba", 3624);
tagToIgnores.put("sql", 3359);
tagToIgnores.put("node.js", 3232);
tagToIgnores.put("matlab", 3220);
tagToIgnores.put("sharepoint", 3108);
tagToIgnores.put("eclipse", 3073);
tagToIgnores.put("xcode", 3068);
tagToIgnores.put("swift", 3065);
tagToIgnores.put("angular", 2956);
tagToIgnores.put("spring", 2890);
tagToIgnores.put("linux", 2875);
tagToIgnores.put("macos", 2804);
tagToUsage.put("c#", 1286491);
tagToUsage.put("php", 1263058);
tagToUsage.put("java", 1515802);
tagToUsage.put("android", 1173706);
tagToUsage.put("asp.net", 342947);
tagToUsage.put("c++", 605528);
tagToUsage.put("python", 1114060);
tagToUsage.put(".net", 279901);
tagToUsage.put("ruby", 202463);
tagToUsage.put("ios", 591066);
tagToUsage.put("ruby-on-rails", 303176);
tagToUsage.put("iphone", 219814);
tagToUsage.put("javascript", 1763733);
tagToUsage.put("objective-c", 286812);
tagToUsage.put("vb.net", 122490);
tagToUsage.put("c", 296656);
tagToUsage.put("jquery", 944680);
tagToUsage.put("delphi", 43337);
tagToUsage.put("django", 190837);
tagToUsage.put("perl", 61725);
tagToUsage.put("asp.net-mvc", 178208);
tagToUsage.put("flash", 35282);
tagToUsage.put("mysql", 550486);
tagToUsage.put("windows", 127560);
tagToUsage.put("facebook", 83210);
tagToUsage.put("r", 276465);
tagToUsage.put("wpf", 147423);
tagToUsage.put("visual-studio", 85729);
tagToUsage.put("angularjs", 257148);
tagToUsage.put("flex", 24297);
tagToUsage.put("sql-server", 253505);
tagToUsage.put("wordpress", 145586);
tagToUsage.put("silverlight", 27515);
tagToUsage.put("oracle", 106795);
tagToUsage.put("css", 574065);
tagToUsage.put("haskell", 39976);
tagToUsage.put("scala", 86886);
tagToUsage.put("html", 804877);
tagToUsage.put("vba", 139729);
tagToUsage.put("sql", 479302);
tagToUsage.put("node.js", 262844);
tagToUsage.put("matlab", 82398);
tagToUsage.put("sharepoint", 24236);
tagToUsage.put("eclipse", 115751);
tagToUsage.put("xcode", 130502);
tagToUsage.put("swift", 221958);
tagToUsage.put("angular", 153902);
tagToUsage.put("spring", 147214);
tagToUsage.put("linux", 173188);
tagToUsage.put("macos", 90234);
}
public static void main
(String[] args
) {
final double averageFreq = tagToIgnores.values().stream().mapToInt(x -> x).average().orElse(0);
final double averageUsage = tagToUsage.values().stream().mapToInt(x -> x).average().orElse(0);
final Map
<String, Double
> tagToNormalisedIgnores
= tagToIgnores.
entrySet() .stream()
.
collect(Collectors.
toMap(Map.Entry::getKey, v
-> v.
getValue() / averageFreq
));
final Map
<String, Double
> tagToNormalisedUsage
= tagToUsage.
entrySet() .stream()
.
collect(Collectors.
toMap(Map.Entry::getKey, v
-> v.
getValue() / averageUsage
));
final double similarity = cosineSimilarity(tagToNormalisedIgnores, tagToNormalisedUsage);
System.
out.
println(similarity
);
final Map
<String, Double
> tagToDiff
= new HashMap
<>(); for (final String tag
: tagToNormalisedIgnores.
keySet()) {
double diff = tagToNormalisedIgnores.get(tag) - tagToNormalisedUsage.get(tag);
tagToDiff.put(tag, diff);
}
tagToDiff.entrySet().stream()
.
forEach(System.
out::println
); }
private static double cosineSimilarity
(Map
<String, Double
> a, Map
<String, Double
> b
) {
final Set<String> intersection = new HashSet<>(a.keySet());
intersection.retainAll(b.keySet());
double dotProduct = 0, magnitudeA = 0, magnitudeB = 0;
for (String item
: intersection
) { dotProduct += a.get(item) * b.get(item);
}
magnitudeA
+= Math.
pow(a.
get(k
),
2); }
magnitudeB
+= Math.
pow(b.
get(k
),
2); }
return dotProduct
/ Math.
sqrt(magnitudeA
* magnitudeB
); }
}
aW1wb3J0IGphdmEudXRpbC5IYXNoTWFwOwppbXBvcnQgamF2YS51dGlsLkhhc2hTZXQ7CmltcG9ydCBqYXZhLnV0aWwuTWFwOwppbXBvcnQgamF2YS51dGlsLlNldDsKaW1wb3J0IGphdmEudXRpbC5zdHJlYW0uQ29sbGVjdG9yczsKCmNsYXNzIFRlc3QKewogICAgcHJpdmF0ZSBzdGF0aWMgTWFwPFN0cmluZywgSW50ZWdlcj4gdGFnVG9JZ25vcmVzID0gbmV3IEhhc2hNYXA8PigpOwogICAgcHJpdmF0ZSBzdGF0aWMgTWFwPFN0cmluZywgSW50ZWdlcj4gdGFnVG9Vc2FnZSA9IG5ldyBIYXNoTWFwPD4oKTsKICAgIAogICAgc3RhdGljCiAgICB7CiAgICAgICAgdGFnVG9JZ25vcmVzLnB1dCgiYyMiLCAyMzc5MCk7CiAgICAgICAgdGFnVG9JZ25vcmVzLnB1dCgicGhwIiwgMjM3MjEpOwogICAgICAgIHRhZ1RvSWdub3Jlcy5wdXQoImphdmEiLCAyMjI1MCk7CiAgICAgICAgdGFnVG9JZ25vcmVzLnB1dCgiYW5kcm9pZCIsIDIyMjAxKTsKICAgICAgICB0YWdUb0lnbm9yZXMucHV0KCJhc3AubmV0IiwgMTczMjApOwogICAgICAgIHRhZ1RvSWdub3Jlcy5wdXQoImMrKyIsIDE1MTkxKTsKICAgICAgICB0YWdUb0lnbm9yZXMucHV0KCJweXRob24iLCAxNDg2OSk7CiAgICAgICAgdGFnVG9JZ25vcmVzLnB1dCgiLm5ldCIsIDEzMjkzKTsKICAgICAgICB0YWdUb0lnbm9yZXMucHV0KCJydWJ5IiwgMTI2OTEpOwogICAgICAgIHRhZ1RvSWdub3Jlcy5wdXQoImlvcyIsIDExODk2KTsKICAgICAgICB0YWdUb0lnbm9yZXMucHV0KCJydWJ5LW9uLXJhaWxzIiwgMTE4MTkpOwogICAgICAgIHRhZ1RvSWdub3Jlcy5wdXQoImlwaG9uZSIsIDEwOTU1KTsKICAgICAgICB0YWdUb0lnbm9yZXMucHV0KCJqYXZhc2NyaXB0IiwgMTAwNzgpOwogICAgICAgIHRhZ1RvSWdub3Jlcy5wdXQoIm9iamVjdGl2ZS1jIiwgODU4Nyk7CiAgICAgICAgdGFnVG9JZ25vcmVzLnB1dCgidmIubmV0IiwgNzg5Mik7CiAgICAgICAgdGFnVG9JZ25vcmVzLnB1dCgiYyIsIDc3NjcpOwogICAgICAgIHRhZ1RvSWdub3Jlcy5wdXQoImpxdWVyeSIsIDY5MzkpOwogICAgICAgIHRhZ1RvSWdub3Jlcy5wdXQoImRlbHBoaSIsIDY1NjMpOwogICAgICAgIHRhZ1RvSWdub3Jlcy5wdXQoImRqYW5nbyIsIDY0MjMpOwogICAgICAgIHRhZ1RvSWdub3Jlcy5wdXQoInBlcmwiLCA1OTI1KTsKICAgICAgICB0YWdUb0lnbm9yZXMucHV0KCJhc3AubmV0LW12YyIsIDU4ODcpOwogICAgICAgIHRhZ1RvSWdub3Jlcy5wdXQoImZsYXNoIiwgNTU2OSk7CiAgICAgICAgdGFnVG9JZ25vcmVzLnB1dCgibXlzcWwiLCA1MTQyKTsKICAgICAgICB0YWdUb0lnbm9yZXMucHV0KCJ3aW5kb3dzIiwgNTEzMSk7CiAgICAgICAgdGFnVG9JZ25vcmVzLnB1dCgiZmFjZWJvb2siLCA0ODUxKTsKICAgICAgICB0YWdUb0lnbm9yZXMucHV0KCJyIiwgNDYyOSk7CiAgICAgICAgdGFnVG9JZ25vcmVzLnB1dCgid3BmIiwgNDQ4NCk7CiAgICAgICAgdGFnVG9JZ25vcmVzLnB1dCgidmlzdWFsLXN0dWRpbyIsIDQzOTIpOwogICAgICAgIHRhZ1RvSWdub3Jlcy5wdXQoImFuZ3VsYXJqcyIsIDQyOTgpOwogICAgICAgIHRhZ1RvSWdub3Jlcy5wdXQoImZsZXgiLCA0MTg2KTsKICAgICAgICB0YWdUb0lnbm9yZXMucHV0KCJzcWwtc2VydmVyIiwgNDEwOCk7CiAgICAgICAgdGFnVG9JZ25vcmVzLnB1dCgid29yZHByZXNzIiwgNDA3Nik7CiAgICAgICAgdGFnVG9JZ25vcmVzLnB1dCgic2lsdmVybGlnaHQiLCA0MDE2KTsKICAgICAgICB0YWdUb0lnbm9yZXMucHV0KCJvcmFjbGUiLCA0MDA1KTsKICAgICAgICB0YWdUb0lnbm9yZXMucHV0KCJjc3MiLCAzOTcyKTsKICAgICAgICB0YWdUb0lnbm9yZXMucHV0KCJoYXNrZWxsIiwgMzc1Mik7CiAgICAgICAgdGFnVG9JZ25vcmVzLnB1dCgic2NhbGEiLCAzNzM3KTsKICAgICAgICB0YWdUb0lnbm9yZXMucHV0KCJodG1sIiwgMzY2Myk7CiAgICAgICAgdGFnVG9JZ25vcmVzLnB1dCgidmJhIiwgMzYyNCk7CiAgICAgICAgdGFnVG9JZ25vcmVzLnB1dCgic3FsIiwgMzM1OSk7CiAgICAgICAgdGFnVG9JZ25vcmVzLnB1dCgibm9kZS5qcyIsIDMyMzIpOwogICAgICAgIHRhZ1RvSWdub3Jlcy5wdXQoIm1hdGxhYiIsIDMyMjApOwogICAgICAgIHRhZ1RvSWdub3Jlcy5wdXQoInNoYXJlcG9pbnQiLCAzMTA4KTsKICAgICAgICB0YWdUb0lnbm9yZXMucHV0KCJlY2xpcHNlIiwgMzA3Myk7CiAgICAgICAgdGFnVG9JZ25vcmVzLnB1dCgieGNvZGUiLCAzMDY4KTsKICAgICAgICB0YWdUb0lnbm9yZXMucHV0KCJzd2lmdCIsIDMwNjUpOwogICAgICAgIHRhZ1RvSWdub3Jlcy5wdXQoImFuZ3VsYXIiLCAyOTU2KTsKICAgICAgICB0YWdUb0lnbm9yZXMucHV0KCJzcHJpbmciLCAyODkwKTsKICAgICAgICB0YWdUb0lnbm9yZXMucHV0KCJsaW51eCIsIDI4NzUpOwogICAgICAgIHRhZ1RvSWdub3Jlcy5wdXQoIm1hY29zIiwgMjgwNCk7CgogICAgICAgIHRhZ1RvVXNhZ2UucHV0KCJjIyIsIDEyODY0OTEpOwogICAgICAgIHRhZ1RvVXNhZ2UucHV0KCJwaHAiLCAxMjYzMDU4KTsKICAgICAgICB0YWdUb1VzYWdlLnB1dCgiamF2YSIsIDE1MTU4MDIpOwogICAgICAgIHRhZ1RvVXNhZ2UucHV0KCJhbmRyb2lkIiwgMTE3MzcwNik7CiAgICAgICAgdGFnVG9Vc2FnZS5wdXQoImFzcC5uZXQiLCAzNDI5NDcpOwogICAgICAgIHRhZ1RvVXNhZ2UucHV0KCJjKysiLCA2MDU1MjgpOwogICAgICAgIHRhZ1RvVXNhZ2UucHV0KCJweXRob24iLCAxMTE0MDYwKTsKICAgICAgICB0YWdUb1VzYWdlLnB1dCgiLm5ldCIsIDI3OTkwMSk7CiAgICAgICAgdGFnVG9Vc2FnZS5wdXQoInJ1YnkiLCAyMDI0NjMpOwogICAgICAgIHRhZ1RvVXNhZ2UucHV0KCJpb3MiLCA1OTEwNjYpOwogICAgICAgIHRhZ1RvVXNhZ2UucHV0KCJydWJ5LW9uLXJhaWxzIiwgMzAzMTc2KTsKICAgICAgICB0YWdUb1VzYWdlLnB1dCgiaXBob25lIiwgMjE5ODE0KTsKICAgICAgICB0YWdUb1VzYWdlLnB1dCgiamF2YXNjcmlwdCIsIDE3NjM3MzMpOwogICAgICAgIHRhZ1RvVXNhZ2UucHV0KCJvYmplY3RpdmUtYyIsIDI4NjgxMik7CiAgICAgICAgdGFnVG9Vc2FnZS5wdXQoInZiLm5ldCIsIDEyMjQ5MCk7CiAgICAgICAgdGFnVG9Vc2FnZS5wdXQoImMiLCAyOTY2NTYpOwogICAgICAgIHRhZ1RvVXNhZ2UucHV0KCJqcXVlcnkiLCA5NDQ2ODApOwogICAgICAgIHRhZ1RvVXNhZ2UucHV0KCJkZWxwaGkiLCA0MzMzNyk7CiAgICAgICAgdGFnVG9Vc2FnZS5wdXQoImRqYW5nbyIsIDE5MDgzNyk7CiAgICAgICAgdGFnVG9Vc2FnZS5wdXQoInBlcmwiLCA2MTcyNSk7CiAgICAgICAgdGFnVG9Vc2FnZS5wdXQoImFzcC5uZXQtbXZjIiwgMTc4MjA4KTsKICAgICAgICB0YWdUb1VzYWdlLnB1dCgiZmxhc2giLCAzNTI4Mik7CiAgICAgICAgdGFnVG9Vc2FnZS5wdXQoIm15c3FsIiwgNTUwNDg2KTsKICAgICAgICB0YWdUb1VzYWdlLnB1dCgid2luZG93cyIsIDEyNzU2MCk7CiAgICAgICAgdGFnVG9Vc2FnZS5wdXQoImZhY2Vib29rIiwgODMyMTApOwogICAgICAgIHRhZ1RvVXNhZ2UucHV0KCJyIiwgMjc2NDY1KTsKICAgICAgICB0YWdUb1VzYWdlLnB1dCgid3BmIiwgMTQ3NDIzKTsKICAgICAgICB0YWdUb1VzYWdlLnB1dCgidmlzdWFsLXN0dWRpbyIsIDg1NzI5KTsKICAgICAgICB0YWdUb1VzYWdlLnB1dCgiYW5ndWxhcmpzIiwgMjU3MTQ4KTsKICAgICAgICB0YWdUb1VzYWdlLnB1dCgiZmxleCIsIDI0Mjk3KTsKICAgICAgICB0YWdUb1VzYWdlLnB1dCgic3FsLXNlcnZlciIsIDI1MzUwNSk7CiAgICAgICAgdGFnVG9Vc2FnZS5wdXQoIndvcmRwcmVzcyIsIDE0NTU4Nik7CiAgICAgICAgdGFnVG9Vc2FnZS5wdXQoInNpbHZlcmxpZ2h0IiwgMjc1MTUpOwogICAgICAgIHRhZ1RvVXNhZ2UucHV0KCJvcmFjbGUiLCAxMDY3OTUpOwogICAgICAgIHRhZ1RvVXNhZ2UucHV0KCJjc3MiLCA1NzQwNjUpOwogICAgICAgIHRhZ1RvVXNhZ2UucHV0KCJoYXNrZWxsIiwgMzk5NzYpOwogICAgICAgIHRhZ1RvVXNhZ2UucHV0KCJzY2FsYSIsIDg2ODg2KTsKICAgICAgICB0YWdUb1VzYWdlLnB1dCgiaHRtbCIsIDgwNDg3Nyk7CiAgICAgICAgdGFnVG9Vc2FnZS5wdXQoInZiYSIsIDEzOTcyOSk7CiAgICAgICAgdGFnVG9Vc2FnZS5wdXQoInNxbCIsIDQ3OTMwMik7CiAgICAgICAgdGFnVG9Vc2FnZS5wdXQoIm5vZGUuanMiLCAyNjI4NDQpOwogICAgICAgIHRhZ1RvVXNhZ2UucHV0KCJtYXRsYWIiLCA4MjM5OCk7CiAgICAgICAgdGFnVG9Vc2FnZS5wdXQoInNoYXJlcG9pbnQiLCAyNDIzNik7CiAgICAgICAgdGFnVG9Vc2FnZS5wdXQoImVjbGlwc2UiLCAxMTU3NTEpOwogICAgICAgIHRhZ1RvVXNhZ2UucHV0KCJ4Y29kZSIsIDEzMDUwMik7CiAgICAgICAgdGFnVG9Vc2FnZS5wdXQoInN3aWZ0IiwgMjIxOTU4KTsKICAgICAgICB0YWdUb1VzYWdlLnB1dCgiYW5ndWxhciIsIDE1MzkwMik7CiAgICAgICAgdGFnVG9Vc2FnZS5wdXQoInNwcmluZyIsIDE0NzIxNCk7CiAgICAgICAgdGFnVG9Vc2FnZS5wdXQoImxpbnV4IiwgMTczMTg4KTsKICAgICAgICB0YWdUb1VzYWdlLnB1dCgibWFjb3MiLCA5MDIzNCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyB2b2lkIG1haW4oU3RyaW5nW10gYXJncykKICAgIHsKICAgICAgICBmaW5hbCBkb3VibGUgYXZlcmFnZUZyZXEgPSB0YWdUb0lnbm9yZXMudmFsdWVzKCkuc3RyZWFtKCkubWFwVG9JbnQoeCAtPiB4KS5hdmVyYWdlKCkub3JFbHNlKDApOwogICAgICAgIGZpbmFsIGRvdWJsZSBhdmVyYWdlVXNhZ2UgPSB0YWdUb1VzYWdlLnZhbHVlcygpLnN0cmVhbSgpLm1hcFRvSW50KHggLT4geCkuYXZlcmFnZSgpLm9yRWxzZSgwKTsKCiAgICAgICAgZmluYWwgTWFwPFN0cmluZywgRG91YmxlPiB0YWdUb05vcm1hbGlzZWRJZ25vcmVzID0gdGFnVG9JZ25vcmVzLmVudHJ5U2V0KCkKICAgICAgICAgICAgLnN0cmVhbSgpCiAgICAgICAgICAgIC5jb2xsZWN0KENvbGxlY3RvcnMudG9NYXAoTWFwLkVudHJ5OjpnZXRLZXksIHYgLT4gdi5nZXRWYWx1ZSgpIC8gYXZlcmFnZUZyZXEpKTsKCiAgICAgICAgZmluYWwgTWFwPFN0cmluZywgRG91YmxlPiB0YWdUb05vcm1hbGlzZWRVc2FnZSA9IHRhZ1RvVXNhZ2UuZW50cnlTZXQoKQogICAgICAgICAgICAuc3RyZWFtKCkKICAgICAgICAgICAgLmNvbGxlY3QoQ29sbGVjdG9ycy50b01hcChNYXAuRW50cnk6OmdldEtleSwgdiAtPiB2LmdldFZhbHVlKCkgLyBhdmVyYWdlVXNhZ2UpKTsKCiAgICAgICAgZmluYWwgZG91YmxlIHNpbWlsYXJpdHkgPSBjb3NpbmVTaW1pbGFyaXR5KHRhZ1RvTm9ybWFsaXNlZElnbm9yZXMsIHRhZ1RvTm9ybWFsaXNlZFVzYWdlKTsKICAgICAgICBTeXN0ZW0ub3V0LnByaW50bG4oc2ltaWxhcml0eSk7CiAgICAgICAgU3lzdGVtLm91dC5wcmludGxuKCk7CiAgICAgICAgCiAgICAgICAgCiAgICAgICAgZmluYWwgTWFwPFN0cmluZywgRG91YmxlPiB0YWdUb0RpZmYgPSBuZXcgSGFzaE1hcDw+KCk7CiAgICAgICAgZm9yIChmaW5hbCBTdHJpbmcgdGFnIDogdGFnVG9Ob3JtYWxpc2VkSWdub3Jlcy5rZXlTZXQoKSkKICAgICAgICB7CiAgICAgICAgICAgIGRvdWJsZSBkaWZmID0gdGFnVG9Ob3JtYWxpc2VkSWdub3Jlcy5nZXQodGFnKSAtIHRhZ1RvTm9ybWFsaXNlZFVzYWdlLmdldCh0YWcpOwogICAgICAgICAgICB0YWdUb0RpZmYucHV0KHRhZywgZGlmZik7CiAgICAgICAgfQogICAgICAgIHRhZ1RvRGlmZi5lbnRyeVNldCgpLnN0cmVhbSgpCiAgICAgICAgICAgIC5zb3J0ZWQoTWFwLkVudHJ5LmNvbXBhcmluZ0J5VmFsdWUoKSkKICAgICAgICAgICAgLmZvckVhY2goU3lzdGVtLm91dDo6cHJpbnRsbik7CiAgICB9CgogICAgcHJpdmF0ZSBzdGF0aWMgZG91YmxlIGNvc2luZVNpbWlsYXJpdHkoTWFwPFN0cmluZywgRG91YmxlPiBhLCBNYXA8U3RyaW5nLCBEb3VibGU+IGIpCiAgICB7CiAgICAgICAgZmluYWwgU2V0PFN0cmluZz4gaW50ZXJzZWN0aW9uID0gbmV3IEhhc2hTZXQ8PihhLmtleVNldCgpKTsKICAgICAgICBpbnRlcnNlY3Rpb24ucmV0YWluQWxsKGIua2V5U2V0KCkpOwoKICAgICAgICBkb3VibGUgZG90UHJvZHVjdCA9IDAsIG1hZ25pdHVkZUEgPSAwLCBtYWduaXR1ZGVCID0gMDsKCiAgICAgICAgZm9yIChTdHJpbmcgaXRlbSA6IGludGVyc2VjdGlvbikgewogICAgICAgICAgICBkb3RQcm9kdWN0ICs9IGEuZ2V0KGl0ZW0pICogYi5nZXQoaXRlbSk7CiAgICAgICAgfQogICAgICAgIGZvciAoU3RyaW5nIGsgOiBhLmtleVNldCgpKSB7CiAgICAgICAgICAgIG1hZ25pdHVkZUEgKz0gTWF0aC5wb3coYS5nZXQoayksIDIpOwogICAgICAgIH0KICAgICAgICBmb3IgKFN0cmluZyBrIDogYi5rZXlTZXQoKSkgewogICAgICAgICAgICBtYWduaXR1ZGVCICs9IE1hdGgucG93KGIuZ2V0KGspLCAyKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIGRvdFByb2R1Y3QgLyBNYXRoLnNxcnQobWFnbml0dWRlQSAqIG1hZ25pdHVkZUIpOwogICAgfQp9