简体   繁体   中英

Calculate weighted probability in Java

I have a HashMap. Where Key is the playerName and value is the ticketCount. Eg: player1 has 10 tickets and player2 has 20 tickets.

I want to create a method which will return a playerName when a random number(which is generated) is passed in it. Eg: If 3 is passed, it should return player1 etc.

I have the following approaches to calculate the probability, not sure if it's correct.

  1. Calculate probability ranges for each ticketCount and then make an if else statement to compare random number and ranges. Eg: if randomNumber <= .33 return player1 or if randomNumber >.33 and < .66, return player2.

  2. Make another array which has playerNames corresponding to indexes of ticketCounts. Eg: index 1-10 will have player1, etc. And then perform a binary search.

public class Lottery {

public void calculateWinner(HashMap lotteryMap){

    double total = 0;

    Set<String> keySet = lotteryMap.keySet();
    Iterator<String> keySetIterator = keySet.iterator();
    while (keySetIterator.hasNext()) {

       String key = keySetIterator.next();
       total = total + (Double)lotteryMap.get(key);
    }

    populateRangeArray(lotteryMap, total);


}

//Approach 1
public ArrayList<Double> populateRangeArray(HashMap lotteryMap, double total){
    ArrayList<Double> rangeArray = new ArrayList<Double>();
    Set<String> keySet = lotteryMap.keySet();
    Iterator<String> keySetIterator = keySet.iterator();
    while (keySetIterator.hasNext()) {

       String key = keySetIterator.next();
       double value = total/(Double)lotteryMap.get(key);
       rangeArray.add(value);
    }

    return rangeArray;
}

//Approach 2
public void populatePlayerArray(HashMap lotteryMap, double total){
    int newTotal = (int)total;
    String[] playerArray = new String[newTotal];

    for(int i=0;i<newTotal;i++){

    }
}

This is what I have so far. Not able to figure out approach2 code wise. :(

Your algorithm should depend on exact problem. If order matters (such as in tombola/raffle), then you can go to the second solution as long as the structure fit in memory. In this case, you can take Guava RangeMap :

Map<String, Integer> players = ImmutableMap.of( "player1",10, "player2",20 );

RangeMap<Integer, String> tickets = TreeRangeMap.create();
int lower = 0;
for (Entry<String, Integer> player : players.entrySet()) {
  int upper = lower + player.getValue();
  tickets.put(Range.closed(lower, upper - 1), player.getKey());
  lower = upper;
}

Integer ticket = ThreadLocalRandom.current().nextInt(0, lower);
String  winner = tickets.get(ticket);
System.out.printf("And the winner is %s with ticket #%d%n", winner, ticket);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM