数组的所有可能分布,来自数字

时间:2016-09-26 05:04:52

标签: ruby permutation

我不太清楚如何表达这一点,所以我只是举例说明。

如果我写:

some_method(["a", "b"], 3)

我希望能够返回某种形式的

[{"a" => 0, "b" => 3},
 {"a" => 1, "b" => 2},
 {"a" => 2, "b" => 1},
 {"a" => 3, "b" => 0}]

如果我传入

some_method(%w(a b c), 2)

预期的回报值应为

[{"a" => 2, "b" => 0, "c" => 0},
 {"a" => 1, "b" => 1, "c" => 0},
 {"a" => 1, "b" => 0, "c" => 1},
 {"a" => 0, "b" => 2, "c" => 0},
 {"a" => 0, "b" => 1, "c" => 1},
 {"a" => 0, "b" => 0, "c" => 2}]

描述这很难,所以如果你回答这个问题,请提前感谢!

2 个答案:

答案 0 :(得分:7)

以下是一种方法:

def some_method ary, num
 permutations = (0..num).to_a.repeated_permutation(ary.size).select do |ary| 
    ary.reduce(:+) == num 
 end

 return permutations.map { |a| (ary.zip a).to_h }
end

p some_method ["a", "b"], 3
#=> [{"a"=>0, "b"=>3}, {"a"=>1, "b"=>2}, {"a"=>2, "b"=>1}, {"a"=>3, "b"=>0}]
p some_method %w(a b c), 2
#=> [{"a"=>0, "b"=>0, "c"=>2}, {"a"=>0, "b"=>1, "c"=>1}, {"a"=>0, "b"=>2, "c"=>0}, {"a"=>1, "b"=>0, "c"=>1}, {"a"=>1, "b"=>1, "c"=>0}, {"a"=>2, "b"=>0, "c"=>0}]

根据@seph

的提示更新了答案

答案 1 :(得分:5)

此方法使用递归。

def meth(keys_remaining, total_remaining)
  first_key, *rest_keys = keys_remaining
  return [{ first_key=>total_remaining }] if rest_keys.empty?
  (0..total_remaining).flat_map { |n|  
    meth(rest_keys, total_remaining-n).map { |g| { first_key=>n }.merge(g) } }
end

meth ["a", "b", "c"], 2
  #=> [{"a"=>0, "b"=>0, "c"=>2}, {"a"=>0, "b"=>1, "c"=>1}, {"a"=>0, "b"=>2, "c"=>0},
       {"a"=>1, "b"=>0, "c"=>1}, {"a"=>1, "b"=>1, "c"=>0}, {"a"=>2, "b"=>0, "c"=>0}]

meth ["a", "b", "c", "d"], 4
  #=> [{"a"=>0, "b"=>0, "c"=>0, "d"=>4}, {"a"=>0, "b"=>0, "c"=>1, "d"=>3},
  #    {"a"=>0, "b"=>0, "c"=>2, "d"=>2}, {"a"=>0, "b"=>0, "c"=>3, "d"=>1},
  #    {"a"=>0, "b"=>0, "c"=>4, "d"=>0}, {"a"=>0, "b"=>1, "c"=>0, "d"=>3},
  #    {"a"=>0, "b"=>1, "c"=>1, "d"=>2}, {"a"=>0, "b"=>1, "c"=>2, "d"=>1},
  #    {"a"=>0, "b"=>1, "c"=>3, "d"=>0}, {"a"=>0, "b"=>2, "c"=>0, "d"=>2},
  #    {"a"=>0, "b"=>2, "c"=>1, "d"=>1}, {"a"=>0, "b"=>2, "c"=>2, "d"=>0},
  #    {"a"=>0, "b"=>3, "c"=>0, "d"=>1}, {"a"=>0, "b"=>3, "c"=>1, "d"=>0},
  #    {"a"=>0, "b"=>4, "c"=>0, "d"=>0}, {"a"=>1, "b"=>0, "c"=>0, "d"=>3},
  #    {"a"=>1, "b"=>0, "c"=>1, "d"=>2}, {"a"=>1, "b"=>0, "c"=>2, "d"=>1},
  #    {"a"=>1, "b"=>0, "c"=>3, "d"=>0}, {"a"=>1, "b"=>1, "c"=>0, "d"=>2},
  #    {"a"=>1, "b"=>1, "c"=>1, "d"=>1}, {"a"=>1, "b"=>1, "c"=>2, "d"=>0},
  #    {"a"=>1, "b"=>2, "c"=>0, "d"=>1}, {"a"=>1, "b"=>2, "c"=>1, "d"=>0},
  #    {"a"=>1, "b"=>3, "c"=>0, "d"=>0}, {"a"=>2, "b"=>0, "c"=>0, "d"=>2},
  #    {"a"=>2, "b"=>0, "c"=>1, "d"=>1}, {"a"=>2, "b"=>0, "c"=>2, "d"=>0},
  #    {"a"=>2, "b"=>1, "c"=>0, "d"=>1}, {"a"=>2, "b"=>1, "c"=>1, "d"=>0},
  #    {"a"=>2, "b"=>2, "c"=>0, "d"=>0}, {"a"=>3, "b"=>0, "c"=>0, "d"=>1},
  #    {"a"=>3, "b"=>0, "c"=>1, "d"=>0}, {"a"=>3, "b"=>1, "c"=>0, "d"=>0},
  #    {"a"=>4, "b"=>0, "c"=>0, "d"=>0}]