/* * [RandomWithIntWeights.java] * * Summary: random choices with int weights. * * Copyright: (c) 2014-2017 Roedy Green, Canadian Mind Products, http://mindprod.com * * Licence: This software may be copied and used freely for any purpose but military. * http://mindprod.com/contact/nonmil.html * * Requires: JDK 1.8+ * * Created with: JetBrains IntelliJ IDEA IDE http://www.jetbrains.com/idea/ * * Version History: * 1.0 2014-07-30 initial version */ package com.mindprod.example; import org.jetbrains.annotations.NotNull; import java.util.Random; import static java.lang.System.*; /** * random choices with int weights. * * @author Roedy Green, Canadian Mind Products * @version 1.0 2014-07-28 initial version * @see com.mindprod.example.RandomWithFloatWeights * @since 2014-07-28 */ public final class RandomWithIntWeights { /** * build the translator table for generated weighted random numbers * * @param weights array of weights * * @return translator table */ @NotNull private static int[] buildTranslator( @NotNull final int[] weights ) { // we want to create an array[67] with the first 15 slots 0, the next 20 1, the next 1, 2 etc. int totalWeights = 0; for ( int weight : weights ) { totalWeights += weight; } // create an array 67 long final int[] translator = new int[ totalWeights ]; int k = 0; for ( int i = 0; i < weights.length; i++ ) { final int weight = weights[ i ]; for ( int j = 0; j < weight; j++ ) { translator[ k++ ] = i; } } return translator; } /** * Print out 30 ice cream flavours, but weighting toward choclate strawberry and orange. * * @param args not used */ public static void main( String[] args ) { // we have 7 flavours of ice ceram final String[] flavours = { "chocolate", "strawberry", "vanilla", "orange", "lime", "Cherry Garcia", "bubble gum" }; // we want to randomly pick a different flavour with these weights: // 30% 40% 2% 36% 20% 4% 2% (Ben & Jerry is very expensive). This adds up to 134%, but that is ok. // Each of these is a multiple of 2. We can make the program more efficient if there is no common divisor // So we divide our weights by 2 producing: // 15 20 1 18 10 2 1 which adds up to 67. Must be 7 weights, one weight for each flavour. final int[] weights = { 15, 20, 1, 18, 10, 2, 1 }; final int[] translator = buildTranslator( weights ); final Random wheel = new Random(); for ( int i = 0; i < 30; i++ ) { final int rawChoice = wheel.nextInt( translator.length ); final int weightedChoice = translator[ rawChoice ]; out.println( flavours[ weightedChoice ] ); // different every time run, but mostly chocolate, orange and stawberry } } // end main }