2

I'm trying to figure out a random amount calculator but by rarity for example:

choices = [10,100,1000,10000] 

10 being the most common, 100 more common, 1000 rare, and 10000 extremely rare

I've tried this

import random def getAmmounts(): choices = [10, 100, 1000, 10000] values = [random.choice(choices) for i in range(10)] return values 

Which returns a good amount of values but they're not that random 10000 appears quite often when it should almost hardly ever appear when I called on it the data what I received was:

[1000, 10000, 100, 1000, 10000, 10, 1000, 10000, 100, 100] 

Two 10000's are in there and hardly any 10 values when 10s and 100s should be most common then an occasional 1000 in the mix but hardly ever a 10000 value. Is there any way to set up a priority type function that does this? Some good example data of what this should return after all said in done would be:

[10,10,100,10,10,100,1000] 

And the occasional 10000 but it should be extremely rare, any idea on how to set this up?

5
  • Exactly how common (i.e., with what probability) should each number be? Commented Nov 18, 2013 at 19:59
  • @jwodder the probability of each is not an exact amount but 10sshould be the most common so out of data with 20 values 10 should appear about 6-10 times but never exact the 100 value probably 3-5 the thousand once or twice but hardly ever the occurrence of a 10000 value Commented Nov 18, 2013 at 20:01
  • @user2925490 What jwodder asks is actually a hint at the overarching solution. You want to assign probability to these values, where, say, 10 appears 80% of the time, 100 appears 10% of the time, 1000 appears 8% of the time, and 10000 appears 2% of the time. When assigning actual percentages to this, however, keep in mind how many times getAmounts() will run in real time, so that if a user can run getAmounts() 1000 times in a minute per your implementation of it, you will still have 10000 be a rare number (once or twice). This will require prob/stats math. Commented Nov 18, 2013 at 20:01
  • 2
    Also a dup of this, this, this, this, this, and probably dozens of other questions. Commented Nov 18, 2013 at 20:03
  • @user2925490 In addition to what I just said, you said you want 10 to appear 6 out of 20 times. Readjusting this to be a statistics problem, notice that 6 of 20 can be expressed as a percentage ((6/20)*100 = 30%!) Commented Nov 18, 2013 at 20:03

6 Answers 6

4

Your code does not assign any probabilities. You might intend for 10 to be less rare than 10000 but Python isn't going to know that.

You can simulate probability using the random.random to generate a random number between 0 and 1 and returning the appropriate number depending on the number generated.

For example

import random def make_number(): val = random.random() if val < 0.1: #10% return 10000 elif val < 0.3: # 20% return 1000 elif val < 0.6: # 30% return 100 else: # 40% return 10 values = [make_number() for i in range(10)] print (values) 
Sign up to request clarification or add additional context in comments.

3 Comments

This is good but be careful with the logic here when you implement it, OP. If you change the operator sign, you could run into problems because of the stacked elif structure. For instance, you can't flip the signs to > or you'll have problems.
After writing it, it also looked pretty difficult to maintain. I'd use a hash to store probabilities which would be much easier to maintain. Or something clean like the answer in this question, since you could easily add or remove cases.
@Keikoku Modified it a little bit and it worked great, and thanks to all the others that gave an answer all of them helped when I was modifying it to fit my needs.
2

The input list gets equal probability for each item. Feed it a list with the proportions you want.

choices = [10, 10, 10, 100] 

would make 10 three times as likely as 100.

1 Comment

Manually adjusting probability like this is a good way to start, but i gets messy when you have the implementation scale upwards even a little. In the long run it's more helpful to study up on probability/statistics (very basic versions) to understand how to have the computer generate at proportion for you.
2

Why don't you generate a number and then assign based on a range:

x = randint(1,11) if x == 10: #This is the rarest, occurring only 10% of the time elif x < 10 and x >= 8: #9 or 8 aka 20% elif x < 8 and x >= 5: #7, 6, 5 aka 30% 

You can tweak it how ever you like or make the range longer to get more specific chances.

2 Comments

This solution is a stage more elegant than Jud's or triplee's, because where they have you manually add entries to desired probability, this uses a range to do it for you. It's not quite as elegant as a direct implementation, but I'd choose this over anything else I've seen.
If I understand correctly, the first part of each elif line is superfluous, as the elif is not looked at if the if/elif above it is true. So if x == 10, elif x >= 8, elif x >= 5, else Am I correct?
2

You can produce a random number

import random x = random.random() % this produces a random number between 0 and 1 

and you can use the randomly generated number to choose between 10, 100, 1000 and 10000:

if x < 0.5: # x is between 0 and .50, so 50% chance choice = 10 else if x < 0.75: # x is between .50 and .75, so 75-50 = 25% chance choice = 100 else if x < 0.9: # x is between .75 and .90, so 90-75 = 15% chance choice = 1000 else: choice = 10000 # x is between .90 and 1, so 100-90 = 10% chance (5 times less likely than the first one) 

this outputs 10 on 50% of the runs, 100 on 25% of the runs, 1000 on 15% of the runs and 10000 on 10% of the runs. You can customize the ranges to whatever distribution over [10,100,1000,10000] you'd like!

1 Comment

Never thought about using a random decimal number to do it, I want to edit my answer now to use that, but I don't want to be stealing your idea ;) I like my use of a list rather than straight up assigning a value, since you would have to go in a change the code if you wanted to change the values, if you aren't using a list of values.
0

A quick (though not necessarily the best) solution would be to stick multiple copies of the numbers you wish to appear more often in the list:

import random def getAmmounts(): choices = [10] * 80 + [100] * 15 + [1000] * 4 + [10000] * 1 values = [random.choice(choices) for i in range(10)] return values 

3 Comments

This is technically a solution, but a really messy one that can't really scale to any application. It's a lot more useful to put the time into learning a statistics-based answer.
Hence my "quick but not the best". I don't know how flexible a solution the OP needs.
Perfectly true, I'm reviewing them all to see how close to a direct implementation we can get OP to use; the more direct, the (harder) better it will be, probably.
0
import random def getAmounts(): amount = random.random(1,10) if amount == 10: return 10000 elif amount > 8: return 1000 elif amount > 5: return 100 else: return 10 

Or, if you want to use a list, you could do something like (I do not have IDLE open, and it takes a long time to load, so if I'm off a little, I apologize.)

import random def getAmounts(): values = [10, 100, 1000, 10000] amount = random.random(1,10) if amount == 10: return values[3] elif amount > 8: return values[2] elif amount > 5: return values [1] else: return values[0] 

Using lists, you could always change the actual values you return, so if instead of 10, 100, 1000, 10000, you want to return 50, 500, 5000, and 50000 you could just reassign the values list, and the code still works, without having to go through and change every line.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.