Last active
June 12, 2018 14:47
-
-
Save Scarsz/9881267eac98dcb946314e54c2403363 to your computer and use it in GitHub Desktop.
Get a random object from a given map containing objects and their probabilities
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
1,000,000 iterations took 271ms to calculate | |
ten chances generated 181764 times = 18% | |
nine chances generated 163178 times = 16% | |
eight chances generated 146151 times = 14% | |
seven chances generated 127031 times = 12% | |
six chances generated 109405 times = 10% | |
five chances generated 91076 times = 9% | |
four chances generated 72484 times = 7% | |
three chances generated 54386 times = 5% | |
two chances generated 36190 times = 3% | |
one chances generated 18335 times = 1% |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.scarsz.playground; | |
import java.util.HashMap; | |
import java.util.LinkedHashMap; | |
import java.util.Map; | |
import java.util.Random; | |
import java.util.concurrent.atomic.AtomicInteger; | |
/** | |
* Made by Scarsz | |
* | |
* @in /dev/hell | |
* @on 3/5/2017 | |
* @at 11:21 AM | |
*/ | |
public class RandomObjectFromProbabilities { | |
/** | |
* {@link Random} object to generate random numbers from. | |
*/ | |
private static Random random = new Random(); | |
/** | |
* The map of all our possible random objects to be generated along with their chance of being selected.<br> | |
* Lower numbers have a lower chance of being selected & vice versa. | |
*/ | |
private static Map<Object, Integer> items = new LinkedHashMap<Object, Integer>() {{ | |
put("one chances", 1); | |
put("two chances", 2); | |
put("three chances", 3); | |
put("four chances", 4); | |
put("five chances", 5); | |
put("six chances", 6); | |
put("seven chances", 7); | |
put("eight chances", 8); | |
put("nine chances", 9); | |
put("ten chances", 10); | |
}}; | |
/** | |
* Get a random object from the given list with given probabilities of being selected | |
* @param items Items to choose from | |
* @return Randomly selected key of an entry from the given map based on the entry's probability (entry value) | |
*/ | |
private static Object getRandomObjectFromProbabilities(Map<Object, Integer> items) { | |
if (items == null) throw new NullPointerException("Null items map supplied!"); | |
if (items.size() == 0) throw new RuntimeException("Not enough items to generate from! (0)"); | |
int totalSum = items.values().stream().mapToInt(Integer::intValue).sum(); | |
int count = random.nextInt(totalSum) + 1; | |
Object currentObject = null; | |
while (count > 0) { | |
for (Map.Entry<Object, Integer> entry : items.entrySet()) { | |
currentObject = entry.getKey(); | |
count -= entry.getValue(); | |
if (count <= 0) return currentObject; | |
} | |
} | |
// it should never reach this point, but, if it does, default to the first given item | |
return currentObject != null ? currentObject : items.keySet().iterator().next(); | |
} | |
public static void main(String[] args) { | |
long startMs = System.currentTimeMillis(); | |
long iterations = 1000000; | |
Map<String, AtomicInteger> results = new HashMap<>(); | |
for (int i = 0; i < iterations; i++) { | |
String result = (String) getRandomObjectFromProbabilities(items); | |
if (results.containsKey(result)) results.get(result).incrementAndGet(); | |
else results.put(result, new AtomicInteger(1)); | |
} | |
System.out.println(iterations + " iterations took " + (System.currentTimeMillis() - startMs) + "ms to calculate\n"); | |
for (Map.Entry<String, AtomicInteger> result : results.entrySet()) | |
System.out.println(result.getKey() + " generated " + result.getValue() + " times = " + ((int) (((double) result.getValue().intValue() / iterations) * 100)) + "%"); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment