import java.util.*;
public class Main {
enum Type {
Normal(10), Rare(2), Yoba(1);
int coefficient;
Type(int coefficient) { this.coefficient = coefficient; }
}
static class Item {
int weight;
Type type;
double expectedProbability;
public Item
(String name,
int weight, Type type,
double expectedProbability
) { this.name = name;
this.weight = weight;
this.type = type;
this.expectedProbability = expectedProbability;
}
@Override
public String toString
() { return name
; } }
static class WeightedItemSelector {
private final NavigableMap
<Integer, Item
> map
= new TreeMap
<>(); private final int maxRange;
public WeightedItemSelector(Item... items) {
int currentWeight = 0;
for (Item item : items) {
currentWeight += item.weight * item.type.coefficient;
map.put(currentWeight, item);
}
maxRange = currentWeight;
}
public Item getNext() {
return map.higherEntry(random.nextInt(maxRange)).getValue();
}
}
private static int iterCount = 1000000;
public static void main
(String[] args
) { WeightedItemSelector selector = new WeightedItemSelector(
new Item("Шапка пиздоглазия", 5, Type.Normal, 50 / 207d),
new Item("Зелье упоротости", 7, Type.Normal, 70 / 207d),
new Item("Картонный щит", 6, Type.Normal, 60 / 207d),
new Item("Меч-опиздюливатель", 5, Type.Rare, 10 / 207d),
new Item("Шлем из мамкиной кастрюли", 8, Type.Rare, 16 / 207d),
new Item("Хуй дракона", 1, Type.Yoba, 1 / 207d)
);
Map<Item, Integer> counters = new HashMap<>();
for (int i = 0; i < iterCount; i++) {
counters.compute(selector.getNext(), (k, v) -> v == null ? 1 : v + 1);
}
counters.
entrySet().
forEach(e
-> System.
out.
println(String.
format("%s: expected %f, actual %f", e.
getKey().
name, e.
getKey().
expectedProbability, e.
getValue().
doubleValue() / iterCount
)));
}
}
aW1wb3J0IGphdmEudXRpbC4qOwoKcHVibGljIGNsYXNzIE1haW4gewoKICAgIGVudW0gVHlwZSB7CiAgICAgICAgTm9ybWFsKDEwKSwgUmFyZSgyKSwgWW9iYSgxKTsKCiAgICAgICAgaW50IGNvZWZmaWNpZW50OwogICAgICAgIFR5cGUoaW50IGNvZWZmaWNpZW50KSB7IHRoaXMuY29lZmZpY2llbnQgPSBjb2VmZmljaWVudDsgfQogICAgfQoKICAgIHN0YXRpYyBjbGFzcyBJdGVtIHsKICAgICAgICBTdHJpbmcgbmFtZTsKICAgICAgICBpbnQgd2VpZ2h0OwogICAgICAgIFR5cGUgdHlwZTsKICAgICAgICBkb3VibGUgZXhwZWN0ZWRQcm9iYWJpbGl0eTsKCiAgICAgICAgcHVibGljIEl0ZW0oU3RyaW5nIG5hbWUsIGludCB3ZWlnaHQsIFR5cGUgdHlwZSwgZG91YmxlIGV4cGVjdGVkUHJvYmFiaWxpdHkpIHsKICAgICAgICAgICAgdGhpcy5uYW1lID0gbmFtZTsKICAgICAgICAgICAgdGhpcy53ZWlnaHQgPSB3ZWlnaHQ7CiAgICAgICAgICAgIHRoaXMudHlwZSA9IHR5cGU7CiAgICAgICAgICAgIHRoaXMuZXhwZWN0ZWRQcm9iYWJpbGl0eSA9IGV4cGVjdGVkUHJvYmFiaWxpdHk7CiAgICAgICAgfQoKICAgICAgICBAT3ZlcnJpZGUKICAgICAgICBwdWJsaWMgU3RyaW5nIHRvU3RyaW5nKCkgeyByZXR1cm4gbmFtZTsgfQogICAgfQoKICAgIHN0YXRpYyBjbGFzcyBXZWlnaHRlZEl0ZW1TZWxlY3RvciB7CiAgICAgICAgcHJpdmF0ZSBmaW5hbCBOYXZpZ2FibGVNYXA8SW50ZWdlciwgSXRlbT4gbWFwID0gbmV3IFRyZWVNYXA8PigpOwogICAgICAgIHByaXZhdGUgZmluYWwgUmFuZG9tIHJhbmRvbSA9IG5ldyBSYW5kb20oKTsKICAgICAgICBwcml2YXRlIGZpbmFsIGludCBtYXhSYW5nZTsKCiAgICAgICAgcHVibGljIFdlaWdodGVkSXRlbVNlbGVjdG9yKEl0ZW0uLi4gaXRlbXMpIHsKICAgICAgICAgICAgaW50IGN1cnJlbnRXZWlnaHQgPSAwOwogICAgICAgICAgICBmb3IgKEl0ZW0gaXRlbSA6IGl0ZW1zKSB7CiAgICAgICAgICAgICAgICBjdXJyZW50V2VpZ2h0ICs9IGl0ZW0ud2VpZ2h0ICogaXRlbS50eXBlLmNvZWZmaWNpZW50OwogICAgICAgICAgICAgICAgbWFwLnB1dChjdXJyZW50V2VpZ2h0LCBpdGVtKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBtYXhSYW5nZSA9IGN1cnJlbnRXZWlnaHQ7CiAgICAgICAgfQoKICAgICAgICBwdWJsaWMgSXRlbSBnZXROZXh0KCkgewogICAgICAgICAgICByZXR1cm4gbWFwLmhpZ2hlckVudHJ5KHJhbmRvbS5uZXh0SW50KG1heFJhbmdlKSkuZ2V0VmFsdWUoKTsKICAgICAgICB9CiAgICB9CgoKCiAgICBwcml2YXRlIHN0YXRpYyBpbnQgaXRlckNvdW50ID0gMTAwMDAwMDsKCiAgICBwdWJsaWMgc3RhdGljIHZvaWQgbWFpbihTdHJpbmdbXSBhcmdzKSB7CiAgICAgICAgV2VpZ2h0ZWRJdGVtU2VsZWN0b3Igc2VsZWN0b3IgPSBuZXcgV2VpZ2h0ZWRJdGVtU2VsZWN0b3IoCiAgICAgICAgICAgICAgICBuZXcgSXRlbSgi0KjQsNC/0LrQsCDQv9C40LfQtNC+0LPQu9Cw0LfQuNGPIiwgNSwgVHlwZS5Ob3JtYWwsIDUwIC8gMjA3ZCksCiAgICAgICAgICAgICAgICBuZXcgSXRlbSgi0JfQtdC70YzQtSDRg9C/0L7RgNC+0YLQvtGB0YLQuCIsIDcsIFR5cGUuTm9ybWFsLCA3MCAvIDIwN2QpLAogICAgICAgICAgICAgICAgbmV3IEl0ZW0oItCa0LDRgNGC0L7QvdC90YvQuSDRidC40YIiLCA2LCBUeXBlLk5vcm1hbCwgNjAgLyAyMDdkKSwKICAgICAgICAgICAgICAgIG5ldyBJdGVtKCLQnNC10Yct0L7Qv9C40LfQtNGO0LvQuNCy0LDRgtC10LvRjCIsIDUsIFR5cGUuUmFyZSwgMTAgLyAyMDdkKSwKICAgICAgICAgICAgICAgIG5ldyBJdGVtKCLQqNC70LXQvCDQuNC3INC80LDQvNC60LjQvdC+0Lkg0LrQsNGB0YLRgNGO0LvQuCIsIDgsIFR5cGUuUmFyZSwgMTYgLyAyMDdkKSwKICAgICAgICAgICAgICAgIG5ldyBJdGVtKCLQpdGD0Lkg0LTRgNCw0LrQvtC90LAiLCAxLCBUeXBlLllvYmEsIDEgLyAyMDdkKQogICAgICAgICk7CgogICAgICAgIE1hcDxJdGVtLCBJbnRlZ2VyPiBjb3VudGVycyA9IG5ldyBIYXNoTWFwPD4oKTsKICAgICAgICBmb3IgKGludCBpID0gMDsgaSA8IGl0ZXJDb3VudDsgaSsrKSB7CiAgICAgICAgICAgIGNvdW50ZXJzLmNvbXB1dGUoc2VsZWN0b3IuZ2V0TmV4dCgpLCAoaywgdikgLT4gdiA9PSBudWxsID8gMSA6IHYgKyAxKTsKICAgICAgICB9CgogICAgICAgIGNvdW50ZXJzLmVudHJ5U2V0KCkuZm9yRWFjaChlIC0+IFN5c3RlbS5vdXQucHJpbnRsbihTdHJpbmcuZm9ybWF0KCIlczogZXhwZWN0ZWQgJWYsIGFjdHVhbCAlZiIsIGUuZ2V0S2V5KCkubmFtZSwgZS5nZXRLZXkoKS5leHBlY3RlZFByb2JhYmlsaXR5LCBlLmdldFZhbHVlKCkuZG91YmxlVmFsdWUoKSAvIGl0ZXJDb3VudCkpKTsKCiAgICB9Cgp9Cg==