在Ruby中查找小于某个数字的组合

时间:2015-11-10 06:02:54

标签: ruby

假设我有一个数组[1,2,3],我希望这些数字的每个组合都不超过4.所以我会[1,2,3] .someMethod(4)和它会给我:

[1,1,1,1]
[1,1,2]
[1,3]
[2,2]

到目前为止,我有:

(1..4).flat_map{|size| [1,2,3].repeated_combination(size).to_a }

但是这给了我所有可能的组合,包括超出我给定限制的组合。有没有一种好方法可以只获得超出我限制的组合?

4 个答案:

答案 0 :(得分:3)

arr = [1,2,3]

(arr+[0]).repeated_combination(4).select { |a| a.reduce(:+) == 4 }.map { |a| a - [0] }
   #=> [[1, 3], [2, 2], [1, 1, 2], [1, 1, 1, 1]]

如果需要,将==更改为<=

此答案与其他答案一样,假设arr包含自然数字,包括1

答案 1 :(得分:2)

您可以使用select方法过滤掉您不想要的数组。只需选择总和为== 4的所有数组(总和由inject方法计算)。

all_arrs = (1..4).flat_map do |size|
  [1,2,3].repeated_combination(size).to_a
end

valid_arrs = all_arrs.select do |arr|
  arr.inject { |a, b| a + b } == 4
end

print valid_arrs

# Output:
# [[1, 3], [2, 2], [1, 1, 2], [1, 1, 1, 1]]

答案 2 :(得分:2)

results = (1..4).each.with_object([]) do |size, results| 
  [1,2,3].repeated_combination(size) do |combo|
    results << combo if combo.reduce(:+) == 4
  end
end

p results

--output:--
[[1, 3], [2, 2], [1, 1, 2], [1, 1, 1, 1]]

参数化算法:

def do_stuff(values, target_total)
  (1..target_total).each.with_object([]) do |size, results| 
    values.repeated_combination(size) do |combo|
      results << combo if combo.reduce(:+) == 4
    end
  end
end

p do_stuff([1, 2, 3], 4)

答案 3 :(得分:1)

递归方法。

def some_method(a, n)
  return [[]] if n == 0

  a.select { |e| e <= n }.\
    flat_map { |e| some_method(a,n-e).map { |es| ([e] + es).sort } }.\
    sort.\
    uniq
end

p some_method([1,2,3], 4)
# => [[1, 1, 1, 1], [1, 1, 2], [1, 3], [2, 2]]

编辑:这是另一个递归版本,没有过滤重复但顺序相反。我添加了评论以使其更清晰。

def some_method(a, n)
  return [[]] if n == 0           # bottom (solution) found
  return [] if a.empty? || n < 0  # no solution

  max = a.max
  # search all solutions with biggest value
  l = some_method(a, n-max).map { |e| [max] + e }
  # search all solutions without biggest value
  r = some_method(a-[max],n)

  l + r
end

p some_method([1,2,3], 4)
# => [[3, 1], [2, 2], [2, 1, 1], [1, 1, 1, 1]]