The logic of big circle lottery -- interval

Keywords: Mobile

Part of original text from: https://blog.csdn.net/larva_s/article/details/87532195

1. Lottery demand

The prize is extracted according to the probability of prize configuration, in which the total probability is not necessarily 1. At this time, the prize is extracted according to the weight.

2. implementation

2.1 idea: interval

Section [0, 10): prize 1 [10, 65): Thank you for your participation [65, 98): prize 2 [98, 100): prize 3
probability Prize 1 probability: 10 Thank you participation probability: 55 Prize 2 probability: 33 Prize 3 probability: 2
  • Construct an interval according to the prize probability
  • Get random value [0, maximum value] through the API of random number Rondom
  • The prize matched to the corresponding interval according to the random value is the prize drawn
/**
 * Prizes
 */
@Data
@AllArgsConstructor
public class Award {

    private Integer id;
    private String name;
    private Integer weight;
}

/**
 * General lottery interface
 * @param <T>
 */
public interface ILotteryService<T> {

    T draw(List<T> awardList) throws DrawException;
}

/**
 * Interval realization lottery probability
 */
public class IntervalLotteryService implements ILotteryService<Award>{

    /**
     * Probability distribution by interval  
     * Prize 1 [0,10)
     * Prize 2 [10,90)
     * Prize 3 [90100)
     * Prize 4 [100980)
     * @param awardList
     * @return
     */
    @Override
    public Award draw(List<Award> awardList) throws DrawException {
        int listSize = awardList.size();
        if (awardList == null || listSize < 1){
            return null;
        }
        
        // Traverse the list, calculate the rightmost value of the interval, and package it into the int array
        int[] interval = new int[listSize];
        for (int i = 0; i < listSize; i++) {
            Award award = awardList.get(i);
            Integer weight = award.getWeight();
            
            if (i == 0){
                interval[0] = weight;
            }else {
                Integer lastAwardWeight = interval[i - 1];
                // The rightmost of the interval is the rightmost of the previous interval + its own weight
                interval[i] = weight + lastAwardWeight;
            }
        }
        
        // random int get random value
        int maxInterval = interval[listSize - 1];
        Random random = new Random();
        int ranVal = random.nextInt(maxInterval);
        
        // Traverse the int array, find out which interval the random value is in, get away, and return the away
        for (int i = 0; i < interval.length; i++) {
            if (ranVal >= interval[i] && ranVal < interval[i + 1]){
                return awardList.get(i + 1);
            }else if (ranVal < interval[0]){
                // Within the first interval
                return awardList.get(0);
            }
        }
        throw new DrawException("Lottery exception");
    }

    // test
    public static void main(String args[]){
        IntervalLotteryService lotteryService = new IntervalLotteryService();
        List<Award> awardList = Lists.newArrayList(
                new Award(1,"0.088 Probability prizes", 88),
                new Award(2,"0.333 Probability prizes", 333),
                new Award(3,"0.155 Probability prizes", 155),
                new Award(4,"0.424 Probability prizes", 424)
        );

        try {
            Map<String, Integer> statMap = Maps.newHashMap();
            for (int i = 0; i < 1000; i++) {
                Award drawAward = lotteryService.draw(awardList);
                String awardName = drawAward.getName();
                if (statMap.containsKey(awardName)){
                    Integer count = statMap.get(awardName);
                    statMap.put(awardName, count + 1);
                }else {
                    statMap.put(awardName, 1);
                }
            }

            statMap.forEach((k, v) -> System.out.println(k + " : " + v));

            /*
            0.088 Probability prize: 94
            0.155 Probability prize: 152
            0.333 Probability prize: 320
            0.424 Probability prize: 434
            */
        } catch (DrawException e) {
            System.out.println("Throwing anomaly");
        }
    }
}

3. problem

3.1 how to deal with the success of lottery but the failure of award?

If the prize fails to be awarded, including throwing exceptions, it is set that no prize can be drawn, and the bottom can be handled.

3.2 when a prize stock is consumed, how to deal with it?

You can still be selected, but only if you find that the inventory has been consumed when deducting the inventory, you will return to thank you for participating

Posted by seany123 on Fri, 07 Feb 2020 08:15:51 -0800