繁体   English   中英

仅显示总和小于或等于目标数的两个排列 arrays 的组合

[英]Show only the combinations of two permutated arrays that have a sum less than or equal to target number

我有两个 arrays: teams = [1,2,3]drivers = [4,5,6] 使用排列,我设法显示了两个 arrays 的所有组合,但设法定义了我想从每个数组中使用的值的数量。 因此,在“团队”中我使用了 1 个值,在“驱动程序”中我使用了两个。 我只想显示总和小于或等于 10 的组合,并删除所有重复项。

    teams = [1,2,3]
    drivers = [4,5,6]
    team = teams.permutation(1).to_a
    driver = drivers.permutation(2).to_a
    array = team.product(driver)
    target = 11

这是使用 1 个来自团队的数字和 2 个来自司机的数字成功输出两个 arrays 的所有组合,如下所示:

[[1], [4, 5]], [[1], [4, 6]], [[1], [5, 4]], [[1], [5, 6]], [[1], [6, 4]], [[1], [6, 5]], [[2], [4, 5]],等等...

要仅显示小于或等于 10 的值,我的预期结果将是: [[1], [4, 5]], [[1], [5, 4]],

然后没有重复会让我只剩下: [[1], [4, 5]]

我尝试添加以下代码行,但出现未定义的方法“<=”错误:

@array = array[0].product(*array[1..-1]).select { |a| a.reduce(:+) <= target }

我也试过这个但没有运气:

result = array.combination(1).select{|combi| combi.sum <= target}

@array = result

我猜这与排列有关?

teams = [1,2,3]
drivers = [2,5,4,5,6,4,5,7]
max_driver_sum = 10

我假设drivers可以包含重复元素(如我的示例),但我将在最后解释如果没有重复元素,计算将如何简化。


作为第一步,让我们在重复值和不重复值之间划分drivers

counts = drivers.tally
  #=> {2=>1, 5=>3, 4=>2, 6=>1, 7=>1}

dup_drivers, uniq_drivers = counts.partition { |_d,n| n > 1 }
                                  .map { |arr| arr.map(&:first) }​
  #=> [[5, 4], [2, 6, 7]]

所以,

dup_drivers
  #=> [5, 4]

uniq_drivers    
  #=> [2, 6, 7]

请参阅Enumerable#tallyEnumerable#partition

这里,

counts.partition { |_d,n| n > 1 } 
 #=> [[[5, 3], [4, 2]], [[2, 1], [6, 1], [7, 1]]]

首先计算两个驱动程序相等的唯一组合:

dup_combos = teams.each_with_object([]) do |t,arr|
  max_driver = (max_driver_sum - t)/2
  dup_drivers.each do |d|
    arr << [[t],[d,d]] if d <= max_driver
  end
end
  #=> [[[1], [4, 4]], [[2], [4, 4]]]

接下来,计算两个驱动程序不相等的唯一组合:

all_uniq = uniq_drivers + dup_drivers
  #=> [2, 6, 7, 5, 4]
all_uniq_combos = all_uniq.combination(2).to_a
  #=> [[2, 6], [2, 7], [2, 5], [2, 4], [6, 7], [6, 5],
  #    [6, 4], [7, 5], [7, 4], [5, 4]]
uniq_combos = teams.each_with_object([]) do |t,arr|
  adj_driver_sum = max_driver_sum - t
  all_uniq_combos.each do |combo|
    arr << [[t],combo] if combo.sum <= adj_driver_sum
  end
end
  #=> [[[1], [2, 6]], [[1], [2, 7]], [[1], [2, 5]], [[1], [2, 4]],
  #   [[1], [5, 4]], [[2], [2, 6]], [[2], [2, 5]], [[2], [2, 4]],
  #   [[3], [2, 5]], [[3], [2, 4]]]

参见数组#combination


最后一步是组合两组组合:

a1 = dup_combos + uniq_combos
  #=> [[[1], [4, 4]], [[2], [4, 4]], [[1], [2, 6]], [[1], [2, 7]],
  #    [[1], [2, 5]], [[1], [2, 4]], [[1], [5, 4]], [[2], [2, 6]],
  #    [[2], [2, 5]], [[2], [2, 4]], [[3], [2, 5]], [[3], [2, 4]]]

排序后,这个结果如下。

a1.sort
  #=> [[[1], [2, 4]], [[1], [2, 5]], [[1], [2, 6]], [[1], [2, 7]],
  #    [[1], [4, 4]], [[1], [5, 4]],
  #    [[2], [2, 4]], [[2], [2, 5]], [[2], [2, 6]], [[2], [4, 4]],
  #    [[3], [2, 4]], [[3], [2, 5]]]

请注意, Array#uniq没有在前面使用。 如果需要,当然可以替换掉上面的一些变量。


如果drivers不包含重复项,则所需数组由uniq_combos给出,其中all_uniqall_uniq_combos的计算中被drivers替换。 例如,如果

teams = [1,2,3]
drivers = [2,5,4,6,7]
max_driver_sum = 10

然后

all_uniq_combos = drivers.combination(2).to_a
  #=> [[2, 5], [2, 4], [2, 6], [2, 7], [5, 4], [5, 6],
  #    [5, 7], [4, 6], [4, 7], [6, 7]]

combos = teams.each_with_object([]) do |t,arr|
  adj_driver_sum = max_driver_sum - t
  all_uniq_combos.each do |combo|
    arr << [[t],combo] if combo.sum <= adj_driver_sum
  end
end ​
  #=> [[[1], [2, 5]], [[1], [2, 4]], [[1], [2, 6]], [[1], [2, 7]],
  #    [[1], [5, 4]], [[2], [2, 5]], [[2], [2, 4]], [[2], [2, 6]],
  #    [[3], [2, 5]], [[3], [2, 4]]]

combos.sort
  #=> [[[1], [2, 4]], [[1], [2, 5]], [[1], [2, 6]], [[1], [2, 7]],
  #    [[1], [5, 4]],
  #    [[2], [2, 4]], [[2], [2, 5]], [[2], [2, 6]],
  #    [[3], [2, 4]], [[3], [2, 5]]]

这是一种方法

teams = [1, 2, 3]
drivers = [2, 6, 5, 4]
team = teams.permutation(1).to_a
driver = drivers.permutation(2).to_a
array = team.product(driver)

target = 10

res = array.select {|i| i.map(&:sum).sum <= target}.compact
==> [[[1], [2, 6]], [[1], [2, 5]], [[1], [2, 4]], [[1], [6, 2]],
     [[1], [5, 2]], [[1], [5, 4]], [[1], [4, 2]], [[1], [4, 5]],
     [[2], [2, 6]], [[2], [2, 5]], [[2], [2, 4]], [[2], [6, 2]],
     [[2], [5, 2]], [[2], [4, 2]], [[3], [2, 5]], [[3], [2, 4]],
     [[3], [5, 2]], [[3], [4, 2]]]

获得独特的物品(修改后也适用于团队>车手的价值)

t1 = res.map {|i| i[0]}
d2 = res.map {|i| i[1].flatten.sort}

t1.zip(d2).uniq
==> [[[1], [2, 6]], [[1], [2, 5]], [[1], [2, 4]], [[1], [4, 5]],
     [[2], [2, 6]], [[2], [2, 5]], [[2], [2, 4]], [[3], [2, 5]],
     [[3], [2, 4]]]

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM