Вот еще одна эвристика. 1 Я скоро объясню процедуру.Нам дано:
arr = [[[0,1], [2], [3], [4]],
[[5,6], [7,8], [9,10,11], [12,13,14,15]],
[[16,17,18], [19,20,21], [22], [23,24]],
[[25,26,27,28], [29,30,31], [32,33,34,35], [36,37,38,39]]
]
nbr_groups = 4
Давайте сначала сгладим один уровень и отсортируем полученные массивы по размеру.
sorted = arr.flatten(1).sort_by(&:size)
#=> [[2], [3], [4], [22], [0, 1], [5, 6], [7, 8], [23, 24], [9, 10, 11],
# [16, 17, 18], [19, 20, 21], [29, 30, 31], [12, 13, 14, 15],
# [25, 26, 27, 28], [32, 33, 34, 35], [36, 37, 38, 39]]
Нам нужно сгруппировать элементы sorted
в массив result
содержащие nbr_groups
массивы.Это будет сделано путем "зачистки" элементов sorted
в result
.Подметание состоит из nbr_groups
прямых назначений, чередующихся с тем же числом обратных назначений.
Теперь создайте перечислитель.
a = nbr_groups.times.to_a
#=> [0, 1, 2, 3]
idx = [*a, *a.reverse].cycle
#=> #<Enumerator: [0, 1, 2, 3, 3, 2, 1, 0]:cycle>
Предлагаемая мной эвристика начинается с назначения первого nbr_groups
элементы от sorted
до result
, так что первый элемент sorted
назначен первому элементу result
, второй элемент sorted
назначен второму элементу result
и т. д.один.Следующие nbr_group
элементы sorted
аналогично присваиваются result
, но на этот раз в обратном порядке: nbr_groups+1
'-й элемент sorted
назначается последнему элементу result
, nbr_groups+2
'элемент sorted
назначен предпоследнему элементу result
и т. д.Эти чередующиеся назначения продолжаются до тех пор, пока не будут назначены все элементы sorted
.
result = sorted.each_with_object(Array.new(nbr_groups) { [] }) do |a,arr|
arr[idx.next] << a
end
#=> [[[2], [23, 24], [9, 10, 11], [36, 37, 38, 39]],
# [[3], [7, 8], [16, 17, 18], [32, 33, 34, 35]],
# [[4], [5, 6], [19, 20, 21], [25, 26, 27, 28]],
# [[22], [0, 1], [29, 30, 31], [12, 13, 14, 15]]]
Теперь давайте посмотрим, насколько равномерно были выполнены эти задания:
result.map { |a| a.sum(&:size) }
#=> [10, 10, 10, 10]
Этот результат вызвал улыбку на моем лице.То, что все элементы result
имеют одинаковый размер, является, конечно, чисто случайным.
1.Как отметил @glyoko в комментарии, проблема является NP-полной, поэтому следует прибегнуть к использованию эвристики для всех, кроме самых маленьких задач.