木を数える


11

ツリーはないサイクルの接続、無向グラフです。あなたの仕事は、与えられた数の頂点にいくつの木があるかを数えることです。

2つのツリーは、同型でない場合、別個と見なされます。2つのグラフは、それぞれの頂点が1つのグラフの2つの頂点の間にエッジがあるようにペアリングできる場合に同型です。より詳細な説明については、上記のリンクを参照してください。

サイズ1から6の異なるツリーのすべてがどのように見えるかを確認するには、こちらをご覧ください

出力しようとしているシリーズは、OEISでA000055です。

制限:ソリューションは、入力で実行するのに数分以内にかかる必要があります6。これは、指数時間アルゴリズムを排除することを意図していませんが、すべてのエッジセットに対するブルートフォースなどの二重指数時間アルゴリズムを排除することを意図しています。

入力:負でない整数。

入力は、STDIN、コマンドラインパラメーター、関数入力など、標準的な手段によるものです。

出力:入力と同じ数の頂点を持つ個別のツリーの数。

出力は、STDOUT、関数の戻り値などを含む標準的な手段によるものです。

例: 0, 1, 2, 3, 4, 5, 6, 7を返す必要があり1, 1, 1, 1, 2, 3, 6, 11ます。

得点:ゴルフをバイト単位でコーディングします。最短のコードが勝つように!

標準的な抜け穴は禁止されています。

回答:


3

CJam(69バイト)

]qi:X,{1e|,:):N{N\f{1$%!*}W$.*:+}%1$W%.*:+N,/+}/W\+_1,*X=\_W%.*:+-Y/z

オンラインデモ

説明

基本的な考え方は、OEISで説明されている生成機能を実装することです。入力は厄介な特殊なケースですが、私が最後に微調整を行った結果、そのケースではが生成されるため、(絶対値)が整頓されます。それがここで最も奇妙なトリックです。1 z01z

.*:+は3回繰り返され、として抽出されると1バイト節約できるように見え{.*:+}:F~ます。ただし、これは外側のループをまったく実行しないため、特殊なケースで中断します。0


A000081の補助生成関数を使用します。その用語には繰り返しがあります

a[0] = 0
a[1] = 1
For n >= 1, a[n+1] = (sum_{k=1}^n a[n-k+1] * sum_{d|k} d * a[d]) / n

一部の言語には逆メビウス変換組み込み機能があると確信していますが、CJamにはありません。私が見つけた最良のアプローチは、をマッピングする配列を構築し、それからusingを使用して点ごとの乗算をことです。ここでは築いてきたために便利であることに注意してください、我々は重みを設定するときに、ゼロによる除算を避けたいので、インデックス1から始まるの。また、ポイントワイズ演算に指定された2つの配列が同じ長さでない場合、長い方の値はそのまま残されることに注意してください。したがって、最初の項を取るか、重みの配列をまで上げる必要があります。d a a k a ndkd×a[d]dk % d == 0 ? d : 0a.*akan。後者の方が短いようです。したがって、この逆メビウス変換は、N\f{1$%!*}W$.*:+

我々はメビウス逆変換の結果を呼び出した場合M、我々は今持っている

a[n+1]=1nk=1na[nk+1]×M[k]

aM1nn+1a

 qi:X,{   ,:):N{N\f{1$%!*}W$.*:+}%1$W%.*:+N,/+}/

補助生成関数のポイントは、A000055の数式セクションで与えられます。

G.f.: A(x) = 1 + T(x) - T^2(x)/2 + T(x^2)/2,
where T(x) = x + x^2 + 2*x^3 + ... is the g.f. for A000081.

a

[x=0]+a[x]+12(a[x/2]i=0na[i]×a[ni])

a[x/2]x1,*X=

0\+a[0]=0X=0W\+2a[x]+i=0na[i]×a[ni]2a[x]

だから私たちは説明しました

 qi:X,{   ,:):N{N\f{1$%!*}W$.*:+}%1$W%.*:+N,/+}/W\+_1,*X=\_W%.*:+-Y/

1]N=1

1]qi:X,1>{ ... }/

X=0a[-1 1]0[x=0]X!+1e|

a1N=0

]qi:X,{ ... /+}/

明らかにゼロによる除算を行います。しかし、しようとすると

]qi:X,{1e| ... /+}/

その後、動作します。我々が得る

             e# Stack: [] 0
1e|          e# Stack: [] 1
,:):N        e# Stack: [] [1]
{            e# We only execute this loop once
  N\f{1$%!*} e#   1 divides 1, so stack: [] [1]
  W$.*       e#   Remember: if the two arrays supplied to the pointwise operation
             e#   are not the same length then the values from the longer one are
             e#   left untouched. Stack: [] [1]
  :+         e#   Fold over a singleton. Stack: [] 1
}%           e# And that was a map, so stack: [] [1]
1$W%.*:+     e# Another [1] [] .*:+, giving the same result: 1
N,/          e# 1 / 1 = 1
+            e# And we append 1 to a giving [1]

必要な値を正確に生成します。

X=01[-1](112(1×1))=10111z


1

Pyth、35バイト

l{m`SmSSMcXdUQk2.pQusm+L,dhHGhHtQ]Y

デモンストレーション。

このプログラムは2つの部分に分けることができます。まず、可能なすべてのツリーを生成し、次に重複を削除します。

このコードはツリーを生成します:usm+L,dhHGhHtQ]Y。ツリーは、次のようなエッジの連結リストとして表されます。

[0, 1, 0, 2, 2, 3, 1, 4]

各数字は頂点を表し、2つの数字はすべてエッジです。既に存在する可能性のある各頂点と新たに作成された頂点のそれぞれにエッジを繰り返し追加し、これを前のステップの可能な各ツリーに追加することにより構築されます。これにより、考えられるすべてのツリーが生成されます。すべてのツリーは、頂点とエッジを既存のツリーに繰り返し追加することで生成できるためです。ただし、同型ツリーが作成されます。

次に、各ツリーに対して、可能なすべての再ラベル付けを実行します。これは、頂点のすべての可能な順列(m ... .pQ)をマッピングし、次に、を使用してツリーを標準の順序からその順序に変換することにより行われXdUQkます。dツリー、k順列です。

次に、を使用してエッジを個別のリストに分離しc ... 2、で各エッジ内の頂点をSMソートし、でツリー内のエッジをソートし、S各ツリーの正規表現を提供します。これら2つのステップはコードmSSMcXdUQk2.pQです。

これで、各ツリーのすべての可能な再ラベル付けで構成されるリストのリストができました。これらのリストをでソートしますS。2つの同型ツリーは、ツリーのグループに再ラベル付けできる必要があります。この事実を使用して、各リストをで文字列に変換し`、でそれらのリストのセットを形成し{、でその長さを出力しlます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.