f=lambda n,k=1:k/n or n*f(n,k+1)+k*f(n-1,k)
オンラインでお試しください!
別のアプローチ
このチャレンジを投稿して以来、この問題の再帰的な解決策を考え出そうとしました。私はペンと紙だけを使って失敗しましたが、ゴルフを実際の問題に変えることに成功しました。
次のように機能するk + mの候補を持つゲームショーを想像してください。
ラウンド1では、すべての候補者が特定のタスクをできるだけ早く達成する必要があります。k個のタスク最速を達成する候補者が勝つ1のk $(1 kilodollar)ラウンド3にそれぞれ、事前に。
ラウンド2では、残りのm人の候補者がもう1つのkに参加する2回目のチャンスを得ます。各候補者に質問があります。質問に正しく答えると、1 k $を獲得してラウンド3に進みます。ただし、質問に答えられなかった場合、ゲームから除外されます。3ラウンドのこの手段は間がありますKとK +メートル彼らの質問に答えることができますどのように多くに応じて、候補者。
ラウンド3は、ラウンド1と同様のm個のコンテストで構成されます。各コンテストで、参加者は特定のタスクを達成する必要があります。ラウンド1とは異なり、賞を受け取る候補者は1人だけですが、すべての候補者は次のコンテストに参加できます。各コンテストは、その前のコンテストの2倍の金額を支払います。最初のものは2 k $を支払い、最後のものは2 m k $を支払います。
賞品はすべて2の累乗であるため、候補者が獲得した賞金の金額を知ることは、候補者がラウンド3に進出したかどうか、およびラウンド3のコンテストで勝ったことがわかることを意味します。
ゲームショーを見ているときに、ラウンド1がすでに終わっていると仮定すると、どのk候補者がすでにラウンド3に到達し、どのm候補者がまだラウンド2でスタックしているのかがわかります。
2番目のラウンドのm候補のうちどれがラウンド3に進んでいるかがわかれば、この特定のシナリオで起こりうる結果を簡単に計算できます。j人の候補者が進んだ場合、ラウンド3 にはk + jの合計候補者がいるため、各コンテストでk + jの可能な結果があります。M 3ラウンドの個々のコンテスト、このことができる(K + J)Mアウトカム全てに対してm個のコンテスト。
さて、jは間の任意の値を取ることができます0およびメートル、これに応じて、候補者がそれぞれの固定値についてラウンド2に正しく答えるJ、あるm個の CのJの異なる組み合わせjは、我々が呼び出した場合、ラウンド3に進出している可能性が候補者は、kラウンド3候補とmラウンド2候補g(m、k)の可能な結果の総数は、次の式を取得します。
k = 1を修正すると、次の特別なケースが得られます。これは、元の問題を解決するための新しいアプローチを構成します。
再帰的な数式
ここで、第1ラウンド後のコマーシャル中に眠りに落ち、第3ラウンドの最後のコンテストで2 m k $の大賞を獲得したのは誰なのかを知るために目覚めたとします。候補者が合計でどれだけの賞金を獲得したかなど、他の情報はありません。残りの賞金はいくつの方法で分配できますか?
勝者が第2ラウンドのm候補の1人だった場合、すでに第3ラウンドに進んでいるはずです。したがって、ラウンド3 には実質的にk + 1の候補がありますが、ラウンド2にはm-1の候補しかありません。最後のコンテストの勝者がわかっているため、結果が不確実なm-1のコンテストしかないため、g(m -1、k + 1)考えられる結果。
勝者がラウンド2をスキップしたk個の候補の1つである場合、計算は少し複雑になります。前と同じように、残りのラウンドはm-1ラウンドのみですが、ラウンド3にはk候補、ラウンド2にはm候補が残っています。ラウンド2候補の数とラウンド3コンテストの数は異なるため、可能な結果gの単純な呼び出しで計算されます。ただし、最初のラウンド2の候補者が(正誤を問わず)回答した後、ラウンド2の候補者の数はm-1ラウンド3のコンテストに再び一致します。候補が進む場合、k + 1ラウンド3の候補があるため、g(m-1、k + 1)可能な結果; 候補が削除された場合、ラウンド3の候補の数はkのままであり、g(m-1、k)の可能な結果があります。候補は前進するかしないかのいずれかなので、これらの2つのケースを組み合わせた結果はg(m-1、k + 1)+ g(m-1、k)になります。
ここで、大賞を獲得できたすべてのk + m候補の潜在的な結果を追加する場合、結果はg(m、k)と一致する必要があります。あるM 2競技ラウンドとリード- G(1、K + 1 m)の電位成果それぞれ、及びkは 3ラウンド競技をするリードそのG(M - 1、K + 1)+ G(M - 1、k)はもの。まとめると、次のアイデンティティが得られます。
ベースケースと一緒に
これら2つの式は、関数gを完全に特徴付けます。
ゴルフの実装
ながら
g=lambda m,k=1:0**m or(m+k)*g(m-1,k+1)+k*g(m-1,k)
(49バイト、0**m
収率1回mはに低下0)あるいは
g=lambda m,k=1:m<1 or(m+k)*g(m-1,k+1)+k*g(m-1,k)
(48バイト、1の代わりにTrueを返します)は有効なソリューションになりますが、保存するバイトがまだあります。
最初の引数としてラウンド2候補の数mの代わりにラウンド1候補の数nを取る関数fを定義すると、
再帰式を取得します
ベースケース付き
最後に、
Pythonの実装
f=lambda n,k=1:k/n or n*f(n,k+1)+k*f(n-1,k)
(n = kで1を1回k/n
生成)は、1から始まるインデックス付けで手元のタスクを解決します。