Параметры и переменные
Дано:
tot
, желаемая сумма, целое или нечетное кратное 0.5
;и size
, общее количество 0
, 0.5
и 1
, что составляет tot
, с требованием, что size >= tot
.
мы определяем три переменные:
n0
равно числу нулей; n0pt5_pairs
равноколичество пар 0.5
х;и n1
равно числу единиц.
Случай 1: tot
является целым числом
Нам требуется:
0 <= n0pt5_pairs <= [tot, size-tot].min
Обратите внимание, потому что n1 = tot - n0pt5_pairs
, 2 * n0pt5_pairs + n1 = n0pt5_pairs + tot > size
, если n0pt5_pairs > size-tot
.Таким образом, общее число 0.5
и единиц превышает size
, если число 0.5
пар превышает size-tot
.
При заданном значении для n0pt5_pairs
, которое удовлетворяет вышеуказанному требованию,n0
и n1
определены:
n1 = tot - n0pt5_pairs
n0 = size - 2*n0pt5_pairs - n1
= size - tot - n0pt5_pairs
Поэтому мы можем случайным образом выбрать случайную тройку [n0, 2*n0pt5_pairs, n1]
следующим образом:
def random_combo(size, tot)
n0pt5_pairs = rand(1+[tot, size-tot].min)
[size-tot-n0pt5_pairs, 2*n0pt5_pairs, tot-n0pt5_pairs]
end
Например:
arr = random_combo(17, 11)
#=> [3, 6, 8]
Используется для генерации массива
arr1 = [*[0]*arr[0], *[0.5]*arr[1], *[1]*arr[2]]
#=> [0, 0, 0, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 1, 1, 1, 1, 1, 1, 1, 1]
, который мы перемешиваем:
arr1.shuffle
#=> [1, 0, 0.5, 1, 0.5, 0, 1, 1, 0, 1, 1, 1, 0.5, 0.5, 1, 0.5, 0.5]
Примечание arr1.size #=> 17
и arr.sum #=> 11
.
Случай 2: tot
- кратное 0,5
Если
tot = n + 0.5
, где n
- целое число, каждая комбинация 0
, 0.5
и 1
будут иметь по крайней мере один 0.5
.Поэтому мы можем вычислить число 0
и 1
вместе с числом 0.5
, превышающим единицу .Для этого мы просто уменьшаем tot
на 0.5
(делая его равным целому числу) и size
на единицу, используем generate_for_integer
для решения этой проблемы, затем для каждого массива из трех элементов, возвращаемого этим методом, увеличиваемколичество 0.5
по одному.
def generate(size, tot)
return nil if size.zero?
is_int = (tot == tot.floor)
tot = tot.floor
size -= 1 unless is_int
n0pt5_pairs = rand(1+[tot, size-tot].min)
[*[0]*(size-tot-n0pt5_pairs), *[0.5]*(2*n0pt5_pairs + (is_int ? 0 : 1)),
*[1]*(tot-n0pt5_pairs)].
shuffle
end
ge = generate(17, 10)
#=> [0, 1, 0, 1, 0.5, 0.5, 0, 0.5, 0.5, 1, 1, 1, 1, 0.5, 0.5, 0.5, 0.5]
ge.size #=> 17
ge.sum #=> 10.0
go = generate(17, 10.5)
#=> [0.5, 0.5, 0.5, 1, 0, 0.5, 0.5, 1, 1, 0.5, 1, 1, 0.5, 1, 0.5, 0.5, 0]
go.size #=> 17
go.sum #=> 10.5