Skip to content

Instantly share code, notes, and snippets.

@khanha2
Last active February 20, 2023 14:25
Show Gist options
  • Save khanha2/30af22e2e7cc33be3f0a2c4cb3c44a1c to your computer and use it in GitHub Desktop.
Save khanha2/30af22e2e7cc33be3f0a2c4cb3c44a1c to your computer and use it in GitHub Desktop.
Randomize with probability list
import random
from typing import List, Tuple
class Randomizer:
MAX_VALUE = 100.0
# Xác suất xuất hiện phần tử (0 <= x <= 1), hoặc tỉ trọng đóng góp
# trong tổng số lần gọi của mỗi phần tử
__probability_map = {}
# Số lần xuất hiện của mỗi giá trị sau khi gọi hàm get value
__value_getting_times_map = {}
# Số lần gọi hàm lấy giá trị
__call_get_value_times = 0
# Mảng lưu các giá trị
__values = []
def __init__(self, probability_list: List[Tuple[str, float]]) -> None:
# Kiểm tra tổng giá trị xác suất có hợp lệ hay không
total_probability = 0.0
for (_value, probability) in probability_list:
total_probability += probability
if total_probability != self.MAX_VALUE:
raise 'Total probability values must equal to 100'
# Khởi tạo xác suất xuất hiện phần tử
for (value, probability) in probability_list:
self.__values.append(value)
self.__probability_map[value] = probability / self.MAX_VALUE
def get_value(self) -> str:
picked_value = None
while True:
# Lựa chọn ngẫu nhiên một giá trị trong danh sách
index = random.randint(0, len(self.__values) - 1)
value = self.__values[index]
# Lấy số lần xuất hiện hiện tại của giá trị
value_getting_times = self.__value_getting_times_map.get(value, 0)
value_probability = self.__probability_map[value]
# Trong trường hợp xác xuất của giá trị = 0
# => lựa chọn phần tử khác
if value_probability == 0:
continue
# Trong trường hợp số lần gọi hàm lớn hơn 0
if self.__call_get_value_times > 0:
# Trong trường hợp tỉ lệ số lần xuất hiện bằng giá trị xác suất
# => lựa chọn phần tử khác
ratio = value_getting_times / self.__call_get_value_times
if ratio > self.__probability_map[value]:
continue
# Trong trường hợp số lần xuất hiện chưa bằng giá trị xác suất
# => chọn phần tử này
picked_value = value
self.__value_getting_times_map[picked_value] = value_getting_times + 1
break
self.__call_get_value_times += 1
return picked_value
# Test
probability_list = [('A', 0), ('B', 55), ('C', 45)]
randomizer = Randomizer(probability_list)
calling_times = 2500
randomized_values = []
for _ in range(calling_times):
randomized_values.append(randomizer.get_value())
for (value, probability) in probability_list:
count = 0
for randomized_value in randomized_values:
if value == randomized_value:
count += 1
ratio = 100.0 * (count / calling_times)
if probability == ratio:
print(
f"Passed {value} with: {count} / {calling_times}, ratio: {ratio}, probability: {probability}"
)
else:
print(
f"Failed {value} with: {count} / {calling_times}, ratio: {ratio}, probability: {probability}"
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment