私はTom Davisのarticle「Catalan Numbers」がCatalan Numbersを定義するための1つの再帰的方法を説明するのに非常に役立つことを発見しました。 N
の一致する括弧(例えば、1(); 2())のすべてのユニークな配列の集合を見つけるのに適用できるので、私はそれを自分自身で説明しようとするでしょう(私は理解しました。 ()、(())など)。 N > 1
について
は(A)B
がA
とB
各括弧の唯一バランスセットを持つN
一致括弧の一の構成を表してみましょう。 A
にk
の一致するセットが含まれている場合、B
はN - k - 1
(0 <= k <= N - 1
)のいずれかになります。 C_2
を列挙するに
C_0 => .
C_1 => (.)
、我々はすべての方法でAB
としてC_1
を手配し、A
の周りに二かっこを配置します:次の例では
、ドットグループは、括弧のゼロセットを有することを意味する
.() = AB = C_0C_1 => (.)()
() . = AB = C_1C_0 => (()) .
C_3
の場合、それぞれが独自の組み合わせを持つN - 1
の3つのパーティションがあります。C_0C_2, C_1C_1, C_2C_0
C_0C_2 = AB = .()() and . (()) =>()()(),()(())
C_1C_1 = AB =()() => (())()
C_2C_0 = AB =()() . and (()) . => (()()), ((()))
N
の各セットを保持し、各パーティションの組み合わせを反復することで、この方法をコーディングできます。個々のアレンジをビットとして保持します:左は0、右は1です(これはバイナリ文字列としてキャストされたときに後方に表示されます)。
def catalan
Enumerator.new do |y|
# the zero here represents none rather than left
s = [[0],[2]]
y << [0]
y << [2]
i = 2
while true
s[i] = []
(0..i - 1).each do |k|
as = s[k]
bs = s[i - k - 1]
as.each do |a|
bs.each do |b|
if a != 0
s[i] << ((b << (2*k + 2)) | (1 << (2*k + 1)) | (a << 1))
else
s[i] << (2 | (b << 2))
end
end # bs
end # as
end # k
y.yield(s[i])
i = i + 1
end # i
end # enumerator
end
catalan.take(4)
# => [[0], [2], [10, 12], [42, 50, 44, 52, 56]]
yielderは怠惰です:
catalan.take(4).last.map{|x| x.to_s(2)}
# => ["101010", "110010", "101100", "110100", "111000"]
旧世代は、以前のすべてを保つために私たちを義務づける:リストは無限ですが、我々は我々が(例えば.takeを使用して)好きなように少しを生成することができます次のものを発行するために設定します。あるいは、よりオーガニックなタイプの蛇行再帰によって要求セットを構築することもできます。この次のバージョンでは、ブロックにそれぞれ配置を生み出すので、私たちは入力できます
catalan(4){
|x| (0..7).reduce(""){
|y,i| if x[i] == 0 then y + "(" else y + ")" end
}
}.take(14)
# => ["(((())))", "((()()))", "((())())", "((()))()", "(()(()))", "(()()())",
# "(()())()", "(())(())", "(())()()", "()((()))", "()(()())", "()(())()",
# "()()(())", "()()()()"]
を直接世代:
def catalan(n)
Enumerator.new do |y|
s = [[0,0,0]]
until s.empty?
left,right,result = s.pop
if left + right == 2 * n
y << yield(result)
end
if right < left
s << [left, right + 1, result | 1 << (left + right)]
end
if left < n
s << [left + 1, right, result]
end
end
end
end
あなたの解決策は*正しい*ではありません。 'parens(4)'は ''(())(()) ''を含みません。 – ruakh