How to choose variables at a consistent probablility

I want to make a custom probability chooser.
This may sound strange but let me give an example:

local x={a,b,c,d,e}
print(table.find(math.random(1,#x)))

This has a 20% chance to print a, as well as a 20% chance to print everything else.
If I want to print “a” more often, how would I do that?
I have thought of doing math.random twice and adding the values together followed by dividing the answer by two and rounding down. But that does not give me the control to print one variable more often.
I have also thought of having the probability be tied to the variable in a nested array, or a multiplier.
I also could not find any other resources to do this as this is a rather strange topic that is hard to describe.
Say the desired percentages are a:50%.b:25.c:10%.d:15%. How would I print these variables with this probability?

1 Like
local array={{"a",0.5},{"b",0.25},{"c",0.1},{"d",0.15}}
local Count={}
for i=1,10000 do
	local function chose()
		local index=math.random(1,#array)
		if math.random()<array[index][2] then
			table.insert(Count,array[index][1])
		else
			chose()
		end
	end
	chose()
end

seems to work

1 Like

People generally refer to variable probabilities in random number generation as weights. Many popular methods exist, but this is my personal favorite since it picks the result on a numerical basis rather than recursively adding items to a giant list according to their weight:

local random = Random.new();
local selections: { [string]: number } = { --an example of how i format my weighted probability tables
	['godly fish'] = 1;
	['golden fish'] = 100;
	['talapia rizz'] = 500;
	['cod modern warfare'] = 1200;
	['stank tuna'] = 3000;
	['a rock'] = 5000;
};

local function pick(selection: { [string]: number })
	local threshold = 0;

	for _, weight in selection do
		threshold += weight;
	end

	local dice = random:NextNumber(0, threshold);

	threshold = 0;

	for item, weight in selection do
		threshold += weight;

		if threshold > dice then return item; end
	end
end

print(pick(selections)); --testing the function if you want to try it out yourself

The function essentially sums the weights, generates a pseudorandom number from zero to the sum, then sums the weights again and returns the first item whose weight caused the sum to exceed the random number.

4 Likes

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.