रैंडम नंबर आमतौर पर जिसे हम 'यूनिफॉर्म डिस्ट्रीब्यूशन' कहते हैं उसका पालन करते हैं, जिसका अर्थ है कि किसी भी नंबर के चुने जाने की समान संभावना होती है।
लेकिन अगर आप चाहते हैं कि कुछ नंबर दूसरों की तुलना में अधिक बार चुने जाएं तो आपको एक अलग रणनीति की आवश्यकता होगी: एक वेटेड रैंडम नंबर जनरेटर।
कुछ व्यावहारिक अनुप्रयोगों में शामिल हैं:
- एक वीडियो गेम में लूट टेबल, जहां दुश्मन अलग-अलग ड्रॉप दरों के साथ विभिन्न आइटम गिरा सकते हैं।
- एक रैफल, जहां अधिक टिकट वाले लोगों के जीतने की संभावना अधिक होती है।
सरल रणनीति
यदि आप रैफल उदाहरण के बारे में सोचते हैं तो आप एक स्पष्ट समाधान के साथ आ सकते हैं: एक सरणी उत्पन्न करें जिसमें प्रत्येक 'टिकट' के लिए आइटम की एक प्रति हो।
उदाहरण के लिए, यदि जॉन 4 रैफल टिकट खरीदता है और डेविड केवल 1 खरीदता है, तो जॉन के पास डेविड की तुलना में 4 गुना अधिक जीतने के मौके होंगे।
यहां एक कार्यशील कार्यान्वयन है:
users = { john: 4, david: 1 }
raffle = []
users.map do |name, tickets|
tickets.times { raffle << name }
end
p raffle # [:john, :john, :john, :john, :david]
p raffle.sample # :john
मैं व्यक्ति का नाम हर टिकट के लिए एक बार जोड़ रहा हूँ, और फिर उस सूची से एक रैंडम नाम चुन रहा हूँ। सूची में अधिक बार होने के कारण, उस नाम के चुने जाने की संभावना बढ़ जाएगी।
मुझे यह दृष्टिकोण पसंद है क्योंकि यह बहुत सरल है और एक बार आपकी सूची तैयार हो जाने पर विजेता चुनना बहुत तेज़ है।
वेट्स का योग
यह करने का एक और तरीका है जो अधिक मेमोरी-कुशल है, ट्रेड-ऑफ यह है कि रैंडम मान चुनना धीमा है।
विचार यह है कि 1 और सभी वेट्स के योग के बीच एक रैंडम नंबर चुनें, और फिर तब तक लूप करें जब तक आपको ऐसा वेट न मिल जाए जो इस नंबर से कम या बराबर हो।
यहां कोड है:
def random_weighted(weighted)
max = sum_of_weights(weighted)
target = rand(1..max)
weighted.each do |item, weight|
return item if target <= weight
target -= weight
end
end
def sum_of_weights(weighted)
weighted.inject(0) { |sum, (item, weight)| sum + weight }
end
यह कोड एक हैश लेता है जहां कुंजियाँ आइटम हैं और मान वेट्स हैं। आप इस मेथड को इस तरह कॉल कर सकते हैं:
random_weighted(cats: 5, dogs: 1) # :cats
आप इसे कई बार चलाकर परिणामों के वितरण को देखकर जांच सकते हैं कि यह अपेक्षा के अनुरूप काम करता है या नहीं।
यहां एक उदाहरण है:
counts = Hash.new(0)
def pick_number
random_weighted(cats: 2, dogs: 1)
end
1000.times { counts[pick_number] += 1 }
p counts
इसे कुछ बार चलाएं और आउटपुट को देखें कि अनुपात वही है जो होना चाहिए।
निष्कर्ष
जबकि अधिक परिष्कृत एल्गोरिदम हैं, ये दोनों आपकी अच्छी सेवा करेंगे। मुझे आशा है कि आपको यह लेख उपयोगी लगा, कृपया इसे अपने दोस्तों के साथ साझा करें ताकि मैं और अधिक लिखना जारी रख सकूं!