/* package whatever; // don't place package name! */
import java.util.*;
import java.util.stream.*;
import java.util.concurrent.ThreadLocalRandom;
class Ideone {
public static void main
(String[] args
) {
Ranges r = new Ranges()
.add(3, 5)
.add(13, 16);
Map
<Long, Long
> map
= Stream.
generate(() -> r.
random()) .limit(1000000)
.collect(Collectors.groupingBy(i -> i, Collectors.counting()));
map.
forEach((k, v
) -> System.
out.
println(k
+ ": " + v
+ "x"));
}
}
class Ranges {
private long offset;
private List<Long> offsets = new ArrayList<>();
private List<Range> ranges = new ArrayList<>();
Ranges add(long min, long max) {
this.ranges.add(new Range(min, max));
this.offsets.add(offset);
this.offset += (max - min);
return this;
}
long random() {
long index = ThreadLocalRandom.current().nextLong(this.offset);
int offsetIndex
= Collections.
binarySearch(this.
offsets, index
); if (offsetIndex < 0) {
offsetIndex
= Math.
abs(offsetIndex
) - 2; }
Range r = this.ranges.get(offsetIndex);
return r.lower + index - this.offsets.get(offsetIndex);
}
}
class Range {
long lower;
long upper;
Range(long lower, long upper) {
this.lower = lower;
this.upper = upper;
}
}
LyogcGFja2FnZSB3aGF0ZXZlcjsgLy8gZG9uJ3QgcGxhY2UgcGFja2FnZSBuYW1lISAqLwoKaW1wb3J0IGphdmEudXRpbC4qOwppbXBvcnQgamF2YS51dGlsLnN0cmVhbS4qOwppbXBvcnQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkTG9jYWxSYW5kb207CgpjbGFzcyBJZGVvbmUgewoJcHVibGljIHN0YXRpYyB2b2lkIG1haW4oU3RyaW5nW10gYXJncykgewoKICAgICAgICBSYW5nZXMgciA9IG5ldyBSYW5nZXMoKQogICAgICAgICAgICAuYWRkKDMsIDUpCiAgICAgICAgICAgIC5hZGQoMTMsIDE2KTsKCiAgICAgICAgTWFwPExvbmcsIExvbmc+IG1hcCA9IFN0cmVhbS5nZW5lcmF0ZSgoKSAtPiByLnJhbmRvbSgpKQogICAgICAgICAgICAubGltaXQoMTAwMDAwMCkKICAgICAgICAgICAgLmNvbGxlY3QoQ29sbGVjdG9ycy5ncm91cGluZ0J5KGkgLT4gaSwgQ29sbGVjdG9ycy5jb3VudGluZygpKSk7CgogICAgICAgIG1hcC5mb3JFYWNoKChrLCB2KSAtPiBTeXN0ZW0ub3V0LnByaW50bG4oayArICI6ICIgKyB2ICsgIngiKSk7CgoJfQp9CgpjbGFzcyBSYW5nZXMgewoKICAgIHByaXZhdGUgbG9uZyBvZmZzZXQ7CiAgICBwcml2YXRlIExpc3Q8TG9uZz4gb2Zmc2V0cyA9IG5ldyBBcnJheUxpc3Q8PigpOwogICAgcHJpdmF0ZSBMaXN0PFJhbmdlPiByYW5nZXMgPSBuZXcgQXJyYXlMaXN0PD4oKTsKCiAgICBSYW5nZXMgYWRkKGxvbmcgbWluLCBsb25nIG1heCkgewogICAgICAgIHRoaXMucmFuZ2VzLmFkZChuZXcgUmFuZ2UobWluLCBtYXgpKTsKICAgICAgICB0aGlzLm9mZnNldHMuYWRkKG9mZnNldCk7CiAgICAgICAgdGhpcy5vZmZzZXQgKz0gKG1heCAtIG1pbik7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICB9CgogICAgbG9uZyByYW5kb20oKSB7CiAgICAgICAgbG9uZyBpbmRleCA9IFRocmVhZExvY2FsUmFuZG9tLmN1cnJlbnQoKS5uZXh0TG9uZyh0aGlzLm9mZnNldCk7CiAgICAgICAgaW50IG9mZnNldEluZGV4ID0gQ29sbGVjdGlvbnMuYmluYXJ5U2VhcmNoKHRoaXMub2Zmc2V0cywgaW5kZXgpOwogICAgICAgIGlmIChvZmZzZXRJbmRleCA8IDApIHsKICAgICAgICAgICAgb2Zmc2V0SW5kZXggPSBNYXRoLmFicyhvZmZzZXRJbmRleCkgLSAyOwogICAgICAgIH0KICAgICAgICBSYW5nZSByID0gdGhpcy5yYW5nZXMuZ2V0KG9mZnNldEluZGV4KTsKICAgICAgICByZXR1cm4gci5sb3dlciArIGluZGV4IC0gdGhpcy5vZmZzZXRzLmdldChvZmZzZXRJbmRleCk7CiAgICB9Cn0KCmNsYXNzIFJhbmdlIHsKCiAgICBsb25nIGxvd2VyOwogICAgbG9uZyB1cHBlcjsKCiAgICBSYW5nZShsb25nIGxvd2VyLCBsb25nIHVwcGVyKSB7CiAgICAgICAgdGhpcy5sb3dlciA9IGxvd2VyOwogICAgICAgIHRoaXMudXBwZXIgPSB1cHBlcjsKICAgIH0KfQ==