web-dev-qa-db-ja.com

指定された範囲内の長さを持つ配列のすべての可能な組み合わせを生成します

特定の範囲内の長さを持つ配列の要素のすべての可能な組み合わせをどのように生成できますか?例えば。:

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

次のような配列を生成する必要があります:

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

"abc"(3文字)から('a'..'f').to_aの最後の可能な組み合わせまで、5文字の長さを含めます。これを行う方法がわかりません。何か助けは?

24
fschuindt

_Array#combination_ はstdlibです:

_[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)に置き換えてください。

53
dbenhur
(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)}
13
sawa

この方法で前の質問に対する私の応答を変更して、必要なものを取得できます。

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)
2
oldergod

`

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でそれをハックアウトしました。そして、私はとても間違っていました。

3列までのa〜zのすべての組み合わせが必要だとします。

すべての組み合わせは26 * 26 * 26 = 26 ** 3 = 17576です。

配列の開始点0に対して1を減算してみましょう= 17575

また、マッピング変数が必要です。map26は、1つの列のベース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ループの開始値を使用して最小長を制御できます。

2
Emma's Fist