2016-02-18 68 views

回答

2

你可以通過執行以下步驟:

  • 獲取不受約束的樣品
  • 如果在有限的重複值的n情況下,最多m被允許,刪除所有n並添加返回m
  • 隨機選擇n-m值的數組由初始範圍的元素減去限定的重複值
  • 洗牌所得陣列

代碼

def random_with_limit(range, sample_size, limited_repeat_value, max_instances) 
    a = Array.new(sample_size) { rand range } 
    extra = a.count(limited_repeat_value) - max_instances 
    puts "inital number of #{limited_repeat_value} = #{max_instances+extra}" 
    return a if extra <= 0 
    b = [*range]-[limited_repeat_value] 
    (a-[limited_repeat_value]). 
    concat([limited_repeat_value]*max_instances). 
    concat(Array.new(extra) { b.sample }). 
    shuffle 
end 

puts語句僅用於說明包括在內。

實例

我已經創建了一個輔助用於顯示隨機選擇的範圍內的每個元素的號碼。此方法還會打印初始不受限制的示例中指定元素的實例數。

def show_result(range, sample_size, limited_repeat_value, max_instances) 
    random_with_limit(2..11, 50, 4, 3).sort.chunk(&:itself).map { |n,dups| 
    "#{n} (#{dups.count})" } 
end 

show_result(2..11, 50, 4, 3) 
    # inital number of 4 = 4 
    #=> ["2 (6)", "3 (10)", "4 (3)", "5 (5)", "6 (5)", 
    # "7 (6)", "8 (5)", "9 (2)", "10 (6)", "11 (2)"] 
show_result(2..11, 50, 4, 3) 
    # inital number of 4 = 3 
    #=> ["2 (7)", "3 (5)", "4 (3)", "5 (3)", "6 (4)", 
    # "7 (6)", "8 (5)", "9 (6)", "10 (7)", "11 (4)"] 
show_result(2..11, 50, 4, 3) 
    # inital number of 4 = 2 
    #=> ["2 (5)", "3 (5)", "4 (2)", "5 (4)", "6 (8)", 
    # "7 (8)", "8 (1)", "9 (7)", "10 (4)", "11 (6)"] 
show_result(2..11, 50, 4, 3) 
    # inital number of 4 = 7 
    #=> ["2 (2)", "3 (8)", "4 (3)", "5 (8)", "6 (5)", 
    # "7 (3)", "8 (3)", "9 (6)", "10 (5)", "11 (7)"] 

替代做法

  • 確定有限重複值的情況下的指標
  • 如果有n > m,隨機
  • 選擇n-m在與隨機的n-m選定索引替換值在第一個解決方案中選擇的值

def random_with_limit(range, sample_size, limited_repeat_value, max_instances) 
    a = Array.new(sample_size) { rand range } 
    extra = a.count(limited_repeat_value) - max_instances 
    puts "inital number of #{limited_repeat_value} = #{max_instances+extra}" 
    return a if extra <= 0 
    idx = a.each_with_index.select { |x,_| x == limited_repeat_value }.map(&:last) 
    b = [*range]-[limited_repeat_value] 
    idx.shuffle.first(extra).each { |i| a[i] = b.sample } 
    a 
end 

show_result(2..11, 50, 4, 3) 
    # inital number of 4 = 6 
    # => ["2 (2)", "3 (3)", "4 (3)", "5 (4)", "6 (7)", 
    #  "7 (12)", "8 (4)", "9 (7)", "10 (5)", "11 (3)"] 
show_result(2..11, 50, 4, 3) 
    # inital number of 4 = 2 
    #=> ["2 (9)", "3 (3)", "4 (2)", "5 (6)", "6 (6)", 
    # "7 (3)", "8 (2)", "9 (5)", "10 (9)", "11 (5)"] 
show_result(2..11, 50, 4, 3) 
    # inital number of 4 = 4 
    #=> ["2 (3)", "3 (3)", "4 (3)", "5 (5)", "6 (4)", 
    # "7 (7)", "8 (6)", "9 (4)", "10 (7)", "11 (8)"] 
+0

做得很漂亮。謝謝 – Misha

2

我認爲沒有默認的方法來做到這一點。你需要寫一些代碼,例如馬克·塔爾博特檢查這個答案:https://stackoverflow.com/a/9458016/1306709


a = (100..999).to_a.shuffle 

那麼你需要一個新的ID

new_id = a.pop 

這保證了數字不會被重用。每次。當然,當數組中的元素用盡時,您會遇到問題。


所以如果你需要重複幾次 - 結合了幾臺用相同的數字,並從中pop

+4

如要重複項目時, 「乘」 陣列:'一個=((100..999).to_a * N).shuffle'。 –

+1

Борядякую:)。這對我來說並不是很好的例子,因爲他的目標是不重複的隨機數。我需要有限數量的重複隨機數。 – Misha

+0

謝謝@約旦你有一個好方法 – Misha

相關問題