生成长度在给定范围内的数组的所有可能组合

Posted

技术标签:

【中文标题】生成长度在给定范围内的数组的所有可能组合【英文标题】:Generate all possibles combinations of an array with a length within a given range 【发布时间】:2013-01-04 02:11:16 【问题描述】:

如何生成长度在给定范围内的数组元素的所有可能组合?例如:

('a'..'f').to_a.all_possibilities(3, 5)

应该产生一个像这样的数组:

['abc', 'abd', 'abe', 'abf', ..., 'abcde', 'abcdf', 'abcda', ...]

包括从"abc"(三个字符)到('a'..'f').to_a 与五个字符长度的最后一个可能组合。我不知道该怎么做。有什么帮助吗?

【问题讨论】:

澄清一下,'abcda' 是一个错误吗?是否允许重复? 'aaa' 是你想要的结果吗?另外,这与your previous question 有何不同? ruby-doc.org/core-1.9.3/Array.html#method-i-combination @Amadan 组合不包括重复。 @Amadan 我想要重复。我需要产生所有的可能性。而我之前的问题我没有要求最小长度,所以最小长度总是de array.size。 @sawa 好的,对不起,我现在明白了。 【参考方案1】:

Array#combination 是标准库:

[1] pry(main)> a = ('a'..'f').to_a
=> ["a", "b", "c", "d", "e", "f"]
[2] pry(main)> a.combination(3).to_a
=> [["a", "b", "c"],
 ["a", "b", "d"],
 ["a", "b", "e"],
 ["a", "b", "f"],
 ["a", "c", "d"],
 ["a", "c", "e"],
 ["a", "c", "f"],
 ["a", "d", "e"],
 ["a", "d", "f"],
 ["a", "e", "f"],
 ["b", "c", "d"],
 ["b", "c", "e"],
 ["b", "c", "f"],
 ["b", "d", "e"],
 ["b", "d", "f"],
 ["b", "e", "f"],
 ["c", "d", "e"],
 ["c", "d", "f"],
 ["c", "e", "f"],
 ["d", "e", "f"]]

如果你想要所有尺寸最小到最大的组合:

(min..max).flat_map|size| a.combination(size).to_a 

如果要将它们转换为字符串,只需将 .to_a 替换为 .map(&:join)

【讨论】:

+1 给你。你能解释一下(min..max).flat_map|size| a.combination(size) 吗? a.combination(size) 生成一个数组数组,每个数组都是可以由a 组成的唯一组合。 (min..max) 是一个包容性的range,以min 开头,以max 结尾。 flat_map 枚举范围的值,将每个值生成块并生成一个连接所有块结果的结果。 你如何获得所有的组合,包括重复使用相同的元素?像 ["a","a","a"],["a","b","a"] 也可以,而 ["a","b","a"] 会不同到 ["b","a","a"]。 没关系。我想出了如何使用 .repeated_permutation() 方法:)【参考方案2】:
(3..5).flat_map|n| ('a'..'f').to_a.combination(n).map(&:join)

编辑:为了满足 OP 的明确意图,请使用repeated_permutation

(3..5).flat_map|n| ('a'..'f').to_a.repeated_permutation(n).map(&:join)

【讨论】:

它不会生成所有可能的组合。我的意思是,我的名字是“费尔南多”。 8 个字符长度,但字母“n”重复两次,因此总共 7 个字母。我这样做:'array = ["F", "E", "R", "N", "A", "D", "O"] puts (3..8).flat_map|n| array.combination(n).map(&:join)' 但它不会生成我的名字。而且这段代码输出的组合很少,所有的可能性都应该返回一个非常大的输出。 @user1986332 只有当您的数据数组长度大于或等于您的最大范围 int 时,您的答案才有效。 @user1986332 如果是这样,那么您的问题措辞不当。通常当你说组合时,它不包括重复。 我再次使用我的名字的例子,但仍然没有生成它。 带有3..8%[F E R N A D O] 的结果数组的长度将是7^3 + 7^4 + 7^5 + 7^6 + 7^7 + 7^8 = 6725544。它在我的电脑上运行了几分钟,现在达到了 1580000 左右:四分之一。我怀疑你真的想要这个。【参考方案3】:

您可以通过这种方式修改我对您之前问题的回答以获得您想要的。

class Array
  def all_possibilities(from, to)
    (from..to).flat_map do |i|
      if i < size
        permutation(i).to_a 
      else
        permutation(to - i).flat_map do |e|
          (self + e).permutation.to_a
        end
      end
    end.map(&:join)
  end
end

array = ["F", "E", "R", "N", "A", "D", "O"]
array.all_possibilities(3, 8)

【讨论】:

【参考方案4】:

`

D = length of array
N = number of possible values. i.e a-z = 26
possible combinations = N ^ D
array = [possible values]

map26 = '0123456789abcdefghijklmnop'
map10 = 'abcdefghijklmnopqrstuvwxyz'

combo = '' 
for 0...N ** D do |i|
  i.to_s(D).split(//).each do |v|  
    combo += map10[map26.index(v)].chr
  end
  puts combo
  combo = ''
end

`

编辑:请原谅上面的简短,在浏览另一个答案时在 iPad 上破解它。我错了。

假设您想要从 a-z 到最多 3 列的所有组合。

所有组合都是 26 * 26 * 26 = 26 ** 3 = 17576

让数组的 0 个起点 = 17575 减去 1

我们还需要一个映射变量,map26 是一列的 base 26 查找

map26 = '0123456789abcdefghijklmnop'
map10 = 'abcdefghijklmnopqrstuvwxyz'

回到我们的最大组合

17575.to_s(26)
=> "ppp"

从map26中提取'p'的索引,放到map10中:

map10[map26.index('p')]   (add .chr for ruby ~ 1.8)
=> "z"

因此,如果您对上面的“ppp”进行切片和切块,您将获得最大的“zzz”组合

从映射变量中也可以看出“000”会映射到“aaa”

我已经修改了原始代码以包含这些更改。

关于原题,可以用D来控制字符串的最大长度,用for循环的起始值来控制最小长度。

【讨论】:

以上是关于生成长度在给定范围内的数组的所有可能组合的主要内容,如果未能解决你的问题,请参考以下文章

给定一个任意长度的java数组,如何算出数组内的数能组合出来的最大整数?

二维数组中长度为 8 的所有可能组合

从给定的单词列表中生成具有“N”长度的所有可能组合(寻找不重复)

随机生成指定范围内的随机数,放在指定长度的数组内

基于字符集的固定长度的所有字符串组合

使用一组字符串生成所有可能的组合