Похоже, это будет работать для вас:
arr = [1,3,5,3,6,1,4,6,7,6,6,6,6,6]
arr.group_by(&:itself).transform_values{|v| arr.size / v.size}.flat_map do |k,v|
[k] * v
end.sample
Мы группируем элементы и подсчитываем их, затем создаем новый Array
с инвертированным количеством элементов, что способствует уменьшению количества вхождений. например
arr.group_by(&:itself).transform_values{|v| arr.size / v.size}.flat_map do |k,v|
[k] * v
end.group_by(&:itself).transform_values(&:size)
#=> {1=>7, 3=>7, 5=>14, 6=>2, 4=>14, 7=>14}
Так как 5 произошло однажды, теперь это происходит 14 раз (то же самое с 4 и 7).
Таким образом, 5, 4 и 7 имеют одинаковую вероятность быть выбранными и каждый в два раза чаще, чем 1 и 3, что произошло в два раза и в 7 раз чаще, чем 6.
Также может быть что-то подобное может быть более эффективным
grouping =arr.group_by(&:itself).transform_values(&:size).
scale = grouping.values.uniq.reduce(&:lcm)
grouping.flat_map do |k, v|
[k] * (scale / v)
end.sample