@@ -0,0 +1,3268 @@
+/*%0A * Copyright (c) 2013 - 2017 xxyy (Philipp Nowak; xyc@l1t.li). All rights reserved.%0A *%0A * Any usage, including, but not limited to, compiling, running, redistributing, printing,%0A *  copying and reverse-engineering is strictly prohibited without explicit written permission%0A *  from the original author and may result in legal steps being taken.%0A *%0A * See the included LICENSE file (core/src/main/resources) for details.%0A */%0A%0Apackage li.l1t.common.util.math;%0A%0Aimport com.google.common.base.Preconditions;%0A%0Aimport java.util.Map;%0Aimport java.util.NavigableMap;%0Aimport java.util.Random;%0Aimport java.util.TreeMap;%0Aimport java.util.concurrent.ThreadLocalRandom;%0A%0A/**%0A * Stores a set of values with associated probabilities (relative to the other entries' probabilities) and provides a%0A * method to retrieve a random element, respecting these probabilities. Does not support storage of null values.%0A *%0A * @author %3Ca href=%22https://l1t.li/%22%3ELiterallie%3C/a%3E%0A * @since 2017-01-12%0A */%0Apublic class WeightedDistribution%3CT%3E %7B%0A    private final NavigableMap%3CDouble, T%3E probabilities = new TreeMap%3C%3E();%0A    private double cachedSum = 0D;%0A%0A    public NavigableMap%3CDouble, T%3E probabilities() %7B%0A        return probabilities;%0A    %7D%0A%0A    /**%0A     * @return the sum of all probabilities stored in this distribution%0A     */%0A    public double probabilitySum() %7B%0A        return cachedSum;%0A    %7D%0A%0A    private void recalculateSum() %7B%0A        cachedSum = probabilities.keySet().stream().mapToDouble(Number::doubleValue).sum();%0A    %7D%0A%0A    /**%0A     * Puts given item into the distribution with given probability. Note that the probability is relative to the%0A     * other items in this distribution.%0A     *%0A     * @param item        the item to put%0A     * @param probability the probability of the item being selected, relative to the other items%0A     */%0A    public void put(T item, double probability) %7B%0A        Preconditions.checkNotNull(item, %22item%22);%0A        Preconditions.checkArgument(probability %3E 0, %22probability must be positive%22);%0A        double newSum = probabilitySum() + probability;%0A        probabilities.put(newSum, item);%0A        recalculateSum();%0A    %7D%0A%0A    /**%0A     * Selects a random item using given random.%0A     *%0A     * @param random the random to get the random number from%0A     * @return the selected item, never null%0A     * @throws IllegalStateException if there are no items in this distribution%0A     */%0A    public T next(Random random) %7B%0A        Preconditions.checkNotNull(random, %22random%22);%0A        double randomValue = random.nextDouble() * cachedSum;%0A        Map.Entry%3CDouble, T%3E entry = probabilities.ceilingEntry(randomValue);%0A        if (entry == null) %7B%0A            if (probabilities.isEmpty()) %7B%0A                throw new IllegalStateException(%22no items defined%22);%0A            %7D else %7B%0A                throw new AssertionError(%22no item matched%22);%0A            %7D%0A        %7D else %7B%0A            return entry.getValue();%0A        %7D%0A    %7D%0A%0A    /**%0A     * Selects a random item using the current thread's %7B@link ThreadLocalRandom%7D.%0A     * @return the selected item, never null%0A     * @throws IllegalStateException if there are no items in this distribution%0A     * @see #next(Random)%0A     */%0A    public T next() %7B%0A        return next(ThreadLocalRandom.current());%0A    %7D%0A%7D%0A

Add WeightedDistribution