/*
 * [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
    }