ตัวเลขสุ่มมักจะเป็นไปตามสิ่งที่เราเรียกว่า 'การกระจายแบบสม่ำเสมอ' ซึ่งหมายความว่ามีโอกาสเท่ากันที่จะมีการเลือกหมายเลขใดๆ
แต่ถ้าคุณต้องการให้เลือกหมายเลขบางหมายเลขบ่อยกว่าหมายเลขอื่น คุณจะต้องใช้กลยุทธ์ที่แตกต่าง:ตัวสร้างตัวเลขสุ่มแบบถ่วงน้ำหนัก .
การใช้งานที่ใช้งานได้จริง ได้แก่:
- โต๊ะยกเค้าในวิดีโอเกมที่ศัตรูสามารถดรอปไอเท็มต่างๆ โดยมีอัตราการดรอปที่แตกต่างกัน
- ราฟเฟิลที่ผู้ที่มีตั๋วมากกว่ามีโอกาสถูกรางวัลมากกว่า
กลยุทธ์ง่ายๆ
หากคุณนึกถึงตัวอย่างการจับฉลาก คุณจะพบวิธีแก้ปัญหาที่ชัดเจน:สร้างอาร์เรย์ที่มีหนึ่งสำเนาของรายการสำหรับ "ตั๋ว" แต่ละรายการ
ตัวอย่างเช่น หาก John ซื้อสลาก 4 ใบและ David ซื้อเพียง 1 ใบ John จะมีโอกาสชนะมากกว่า David ถึง 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
เรียกใช้สองสามครั้งแล้วดูที่ผลลัพธ์เพื่อดูว่าอัตราส่วนนั้นควรเป็นหรือไม่
บทสรุป
แม้ว่าจะมีอัลกอริธึมที่ซับซ้อนกว่านี้ แต่ทั้งสองอย่างนี้ควรให้บริการคุณเป็นอย่างดี ฉันหวังว่าคุณจะพบว่าบทความนี้มีประโยชน์ โปรดแบ่งปันกับเพื่อนของคุณเพื่อที่ฉันจะได้เขียนเพิ่มต่อไป!