/* package whatever; // don't place package name! */
import java.util.*;
import java.lang.*;
import java.io.*;
import java.security.MessageDigest;
import java.nio.charset.StandardCharsets;
/* Name of the class has to be "Main" only if the class is public. */
class Ideone
{
public static class Ring {
public static class OrderedMemberRing {
public static OrderedMemberRing ofOnlineMembers
(HashSet
<String
> onlineMembers,
String ownName,
String hashModification
) { HashMap
<Integer, String
> hashToMember
= new HashMap
<>(); for(String member
: onlineMembers
) { int hash = hashOf(member, hashModification);
if(hashToMember.containsKey(hash)) {
// Hash collision, can't determine next
return null;
}
hashToMember.put(hash, member);
}
if(ownName != null) {
int ownHash = hashOf(ownName, hashModification);
if(!hashToMember.containsKey(ownHash))
hashToMember.put(ownHash, ownName);
}
ArrayList<Integer> orderedHashes = new ArrayList<>(hashToMember.keySet());
ArrayList<String> orderedMembers = new ArrayList<>();
for(int hash : orderedHashes)
orderedMembers.add(hashToMember.get(hash));
return new OrderedMemberRing
(orderedMembers.
toArray(new String[0]), hashModification
); }
private final String usedHashModification
;
public OrderedMemberRing
(String[] ring,
String usedHashModification
) { this.ring = ring;
this.usedHashModification = usedHashModification;
}
return ring;
}
public String getUsedHashModification
() { return usedHashModification;
}
/**
* @return -1 if not found. Else index of member in orderedMemberRing
*/
public int indexOf
(String member
) { int memberIndex = -1;
for(int i = 0; i < ring.length; i++) {
if(ring[i].equalsIgnoreCase(member)) {
memberIndex = i;
break;
}
}
return memberIndex;
}
public boolean contains
(String member
) { return indexOf(member) != -1;
}
int memberIndex = indexOf(member);
if(memberIndex == -1) return null; // Not found!
return ring
[Math.
floorMod(memberIndex
+ 1, ring.
length)]; }
int memberIndex = indexOf(member);
if(memberIndex == -1) return null; // Not found!
return ring
[Math.
floorMod(memberIndex
- 1, ring.
length)]; }
}
public static int hashOf
(String userName,
String hashModification
) { userName = userName.toLowerCase();
String hashStr
= userName
+ (hashModification
!= null ? ":" + hashModification
: ""); // Create MD5 Hash
try {
byte[] hash = digest.digest(hashStr.getBytes(StandardCharsets.UTF_8));
int h = (hash[0] << 3*8) | (hash[1] << 2*8) | (hash[2] << 8) | (hash[3]);
System.
out.
println(userName
+ " : " + h
+ " : " + hash
[3]); return h;
throw new RuntimeException("WTF, this should never happen! You don't have MD5!"); }
}
public static boolean contains
(HashSet
<String
> members,
String member
) { for(String maybeMember
: members
) if(maybeMember.equalsIgnoreCase(member)) return true;
return false;
}
}
{
HashSet<String> members = new HashSet<>();
members.add("EnderKill98");
members.add("ItzN00bPvP");
members.add("GoobBot1");
members.add("Honbra");
var r = Ring.OrderedMemberRing.ofOnlineMembers(members, "EnderKill98", "rwgOSa");
for(String member
: r.
getRing()) { System.
out.
println(" - " + member
); }
}
}
LyogcGFja2FnZSB3aGF0ZXZlcjsgLy8gZG9uJ3QgcGxhY2UgcGFja2FnZSBuYW1lISAqLwoKaW1wb3J0IGphdmEudXRpbC4qOwppbXBvcnQgamF2YS5sYW5nLio7CmltcG9ydCBqYXZhLmlvLio7CmltcG9ydCBqYXZhLnNlY3VyaXR5Lk1lc3NhZ2VEaWdlc3Q7CmltcG9ydCBqYXZhLm5pby5jaGFyc2V0LlN0YW5kYXJkQ2hhcnNldHM7CgoKLyogTmFtZSBvZiB0aGUgY2xhc3MgaGFzIHRvIGJlICJNYWluIiBvbmx5IGlmIHRoZSBjbGFzcyBpcyBwdWJsaWMuICovCmNsYXNzIElkZW9uZQp7CgpwdWJsaWMgc3RhdGljIGNsYXNzIFJpbmcgewoKICAgIHB1YmxpYyBzdGF0aWMgY2xhc3MgT3JkZXJlZE1lbWJlclJpbmcgewoKICAgICAgICBwdWJsaWMgc3RhdGljIE9yZGVyZWRNZW1iZXJSaW5nIG9mT25saW5lTWVtYmVycyhIYXNoU2V0PFN0cmluZz4gb25saW5lTWVtYmVycywgU3RyaW5nIG93bk5hbWUsIFN0cmluZyBoYXNoTW9kaWZpY2F0aW9uKSB7CiAgICAgICAgICAgIEhhc2hNYXA8SW50ZWdlciwgU3RyaW5nPiBoYXNoVG9NZW1iZXIgPSBuZXcgSGFzaE1hcDw+KCk7CiAgICAgICAgICAgIGZvcihTdHJpbmcgbWVtYmVyIDogb25saW5lTWVtYmVycykgewogICAgICAgICAgICAgICAgaW50IGhhc2ggPSBoYXNoT2YobWVtYmVyLCBoYXNoTW9kaWZpY2F0aW9uKTsKICAgICAgICAgICAgICAgIGlmKGhhc2hUb01lbWJlci5jb250YWluc0tleShoYXNoKSkgewogICAgICAgICAgICAgICAgICAgIC8vIEhhc2ggY29sbGlzaW9uLCBjYW4ndCBkZXRlcm1pbmUgbmV4dAogICAgICAgICAgICAgICAgICAgIHJldHVybiBudWxsOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgaGFzaFRvTWVtYmVyLnB1dChoYXNoLCBtZW1iZXIpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmKG93bk5hbWUgIT0gbnVsbCkgewogICAgICAgICAgICAgICAgaW50IG93bkhhc2ggPSBoYXNoT2Yob3duTmFtZSwgaGFzaE1vZGlmaWNhdGlvbik7CiAgICAgICAgICAgICAgICBpZighaGFzaFRvTWVtYmVyLmNvbnRhaW5zS2V5KG93bkhhc2gpKQogICAgICAgICAgICAgICAgICAgIGhhc2hUb01lbWJlci5wdXQob3duSGFzaCwgb3duTmFtZSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgQXJyYXlMaXN0PEludGVnZXI+IG9yZGVyZWRIYXNoZXMgPSBuZXcgQXJyYXlMaXN0PD4oaGFzaFRvTWVtYmVyLmtleVNldCgpKTsKICAgICAgICAgICAgQ29sbGVjdGlvbnMuc29ydChvcmRlcmVkSGFzaGVzKTsKCiAgICAgICAgICAgIEFycmF5TGlzdDxTdHJpbmc+IG9yZGVyZWRNZW1iZXJzID0gbmV3IEFycmF5TGlzdDw+KCk7CiAgICAgICAgICAgIGZvcihpbnQgaGFzaCA6IG9yZGVyZWRIYXNoZXMpCiAgICAgICAgICAgICAgICBvcmRlcmVkTWVtYmVycy5hZGQoaGFzaFRvTWVtYmVyLmdldChoYXNoKSk7CiAgICAgICAgICAgIHJldHVybiBuZXcgT3JkZXJlZE1lbWJlclJpbmcob3JkZXJlZE1lbWJlcnMudG9BcnJheShuZXcgU3RyaW5nWzBdKSwgaGFzaE1vZGlmaWNhdGlvbik7CiAgICAgICAgfQoKICAgICAgICBwcml2YXRlIGZpbmFsIFN0cmluZ1tdIHJpbmc7CiAgICAgICAgcHJpdmF0ZSBmaW5hbCBTdHJpbmcgdXNlZEhhc2hNb2RpZmljYXRpb247CgogICAgICAgIHB1YmxpYyBPcmRlcmVkTWVtYmVyUmluZyhTdHJpbmdbXSByaW5nLCBTdHJpbmcgdXNlZEhhc2hNb2RpZmljYXRpb24pIHsKICAgICAgICAgICAgdGhpcy5yaW5nID0gcmluZzsKICAgICAgICAgICAgdGhpcy51c2VkSGFzaE1vZGlmaWNhdGlvbiA9IHVzZWRIYXNoTW9kaWZpY2F0aW9uOwogICAgICAgIH0KCiAgICAgICAgcHVibGljIFN0cmluZ1tdIGdldFJpbmcoKSB7CiAgICAgICAgICAgIHJldHVybiByaW5nOwogICAgICAgIH0KCiAgICAgICAgcHVibGljIFN0cmluZyBnZXRVc2VkSGFzaE1vZGlmaWNhdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuIHVzZWRIYXNoTW9kaWZpY2F0aW9uOwogICAgICAgIH0KCiAgICAgICAgLyoqCiAgICAgICAgICogQHJldHVybiAtMSBpZiBub3QgZm91bmQuIEVsc2UgaW5kZXggb2YgbWVtYmVyIGluIG9yZGVyZWRNZW1iZXJSaW5nCiAgICAgICAgICovCiAgICAgICAgcHVibGljIGludCBpbmRleE9mKFN0cmluZyBtZW1iZXIpIHsKICAgICAgICAgICAgaW50IG1lbWJlckluZGV4ID0gLTE7CiAgICAgICAgICAgIGZvcihpbnQgaSA9IDA7IGkgPCByaW5nLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgICAgICAgICBpZihyaW5nW2ldLmVxdWFsc0lnbm9yZUNhc2UobWVtYmVyKSkgewogICAgICAgICAgICAgICAgICAgIG1lbWJlckluZGV4ID0gaTsKICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgICByZXR1cm4gbWVtYmVySW5kZXg7CiAgICAgICAgfQoKICAgICAgICBwdWJsaWMgYm9vbGVhbiBjb250YWlucyhTdHJpbmcgbWVtYmVyKSB7CiAgICAgICAgICAgIHJldHVybiBpbmRleE9mKG1lbWJlcikgIT0gLTE7CiAgICAgICAgfQoKICAgICAgICBwdWJsaWMgU3RyaW5nIGFmdGVyKFN0cmluZyBtZW1iZXIpIHsKICAgICAgICAgICAgaW50IG1lbWJlckluZGV4ID0gaW5kZXhPZihtZW1iZXIpOwogICAgICAgICAgICBpZihtZW1iZXJJbmRleCA9PSAtMSkgcmV0dXJuIG51bGw7IC8vIE5vdCBmb3VuZCEKICAgICAgICAgICAgcmV0dXJuIHJpbmdbTWF0aC5mbG9vck1vZChtZW1iZXJJbmRleCArIDEsIHJpbmcubGVuZ3RoKV07CiAgICAgICAgfQoKICAgICAgICBwdWJsaWMgU3RyaW5nIGJlZm9yZShTdHJpbmcgbWVtYmVyKSB7CiAgICAgICAgICAgIGludCBtZW1iZXJJbmRleCA9IGluZGV4T2YobWVtYmVyKTsKICAgICAgICAgICAgaWYobWVtYmVySW5kZXggPT0gLTEpIHJldHVybiBudWxsOyAvLyBOb3QgZm91bmQhCiAgICAgICAgICAgIHJldHVybiByaW5nW01hdGguZmxvb3JNb2QobWVtYmVySW5kZXggLSAxLCByaW5nLmxlbmd0aCldOwogICAgICAgIH0KICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGludCBoYXNoT2YoU3RyaW5nIHVzZXJOYW1lLCBTdHJpbmcgaGFzaE1vZGlmaWNhdGlvbikgewogICAgICAgIHVzZXJOYW1lID0gdXNlck5hbWUudG9Mb3dlckNhc2UoKTsKICAgICAgICBTdHJpbmcgaGFzaFN0ciA9IHVzZXJOYW1lICsgKGhhc2hNb2RpZmljYXRpb24gIT0gbnVsbCA/ICI6IiArIGhhc2hNb2RpZmljYXRpb24gOiAiIik7CiAgICAgICAgLy8gQ3JlYXRlIE1ENSBIYXNoCiAgICAgICAgdHJ5IHsKICAgICAgICAgICAgTWVzc2FnZURpZ2VzdCBkaWdlc3QgPSBqYXZhLnNlY3VyaXR5Lk1lc3NhZ2VEaWdlc3QuZ2V0SW5zdGFuY2UoIk1ENSIpOwogICAgICAgICAgICBieXRlW10gaGFzaCA9IGRpZ2VzdC5kaWdlc3QoaGFzaFN0ci5nZXRCeXRlcyhTdGFuZGFyZENoYXJzZXRzLlVURl84KSk7CiAgICAgICAgICAgIGludCBoID0gKGhhc2hbMF0gPDwgMyo4KSB8IChoYXNoWzFdIDw8IDIqOCkgfCAoaGFzaFsyXSA8PCA4KSB8IChoYXNoWzNdKTsKICAgICAgICAgICAgU3lzdGVtLm91dC5wcmludGxuKHVzZXJOYW1lICsgIiA6ICIgKyBoICsgIiA6ICIgKyBoYXNoWzNdKTsKICAgICAgICAgICAgcmV0dXJuIGg7CiAgICAgICAgfWNhdGNoIChFeGNlcHRpb24gZXgpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IFJ1bnRpbWVFeGNlcHRpb24oIldURiwgdGhpcyBzaG91bGQgbmV2ZXIgaGFwcGVuISBZb3UgZG9uJ3QgaGF2ZSBNRDUhIik7CiAgICAgICAgfQogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgYm9vbGVhbiBjb250YWlucyhIYXNoU2V0PFN0cmluZz4gbWVtYmVycywgU3RyaW5nIG1lbWJlcikgewogICAgICAgIGZvcihTdHJpbmcgbWF5YmVNZW1iZXIgOiBtZW1iZXJzKQogICAgICAgICAgICBpZihtYXliZU1lbWJlci5lcXVhbHNJZ25vcmVDYXNlKG1lbWJlcikpIHJldHVybiB0cnVlOwogICAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KCn0KCQoJCglwdWJsaWMgc3RhdGljIHZvaWQgbWFpbiAoU3RyaW5nW10gYXJncykgdGhyb3dzIGphdmEubGFuZy5FeGNlcHRpb24KCXsKCQlIYXNoU2V0PFN0cmluZz4gbWVtYmVycyA9IG5ldyBIYXNoU2V0PD4oKTsKCQltZW1iZXJzLmFkZCgiRW5kZXJLaWxsOTgiKTsKCQltZW1iZXJzLmFkZCgiSXR6TjAwYlB2UCIpOwoJCW1lbWJlcnMuYWRkKCJHb29iQm90MSIpOwoJCW1lbWJlcnMuYWRkKCJIb25icmEiKTsKCQl2YXIgciA9IFJpbmcuT3JkZXJlZE1lbWJlclJpbmcub2ZPbmxpbmVNZW1iZXJzKG1lbWJlcnMsICJFbmRlcktpbGw5OCIsICJyd2dPU2EiKTsKCQlmb3IoU3RyaW5nIG1lbWJlciA6IHIuZ2V0UmluZygpKSB7CgkJCVN5c3RlbS5vdXQucHJpbnRsbigiIC0gIiAgKyBtZW1iZXIpOwoJCX0KCX0KfQo=