まず、誰もが指摘している大きな問題があります。階乗を実際に合計したり、 に渡すことができる値を返したりするのではなくsum
、単に階乗を出力しているだけです。
しかし、それを解いたとしても、実際には を計算することにはなりませんsum(math.factorial(i) for i in range(1000))
が、sum(math.factorial(i) for i in range(1, 1001))
. 前者が必要な場合は、1! ではなく 0! から始める必要があります。
mgilson が指摘したように、階乗ごとに最初からやり直す必要はありません。累積階乗を実行することの要点は、階乗と合計をロックステップで累積できるため、各階乗を 1 回生成するだけで済みます。
import itertools
def factorials():
fact = 1
for i in itertools.count(1):
yield fact
fact *= i
def cum_factorials():
cum = 0
for fact in factorials():
cum += fact
yield cum
def cum_factorial(n):
cf = cum_factorials()
consume(cf, 1000)
return next(cf)
(これには、レシピconsume
の関数、またはインポートされた関数が必要です。または、自分で記述する方法は明らかです。)itertools
more-itertools
明らかに、累積階乗の無限リストを生成して n 番目のものを選択する必要はありませんが、Haskell プログラマーが言語の選択を笑うのを防ぐことができます。
もっと真剣に、紙の上でこれを行う方法を想像してみてください。まず、階乗のリストを書き留めます。
1
1 * 1 = 1
1 * 2 = 2
2 * 3 = 6
6 * 4 = 24
...
次に、別の列を横に書き、その時点までの階乗を合計します。
1 1
1 * 1 = 1 1 + 1 = 2
1 * 2 = 2 2 + 2 = 4
2 * 3 = 6 4 + 6 = 10
6 * 4 = 24 10 + 24 = 34
24 * 5 = 120 34 + 120 = 154
... ...
では、Python で同じことを行うにはどうすればよいでしょうか。
1 つのオプションは、次のように、アルゴリズムを順番に記述できるものに再編成することです。
def cum_fact(n):
cumulative_sum = 1
latest_factorial = 1
for i in range(1, n):
latest_factorial *= i
cumulative_sum += latest_factorial
return cumulative_sum
しかし、それは紙の上でやったよりも実際には理解するのが難しく、間違えやすい.
別の方法は、Python に紙で行ったことを実行させる方法を理解することです: 無限シーケンスを取り、そのシーケンスに(1, 2, 3, 4, …)
単純な変換を繰り返し適用して新しいものを取得し、別の単純な変換を繰り返し適用して新しいものを取得します。. そして、そのシーケンスの 1001 番目の値が必要なので、最初の 1000 を破棄して次の値を取得します。*=
(1, 1, 2, 6, 24, …)
+=
(1, 2, 4, 10, 34, …)
itertools.count(1)
はその最初のシーケンスを提供します(1, 2, 3, …)
。次のように記述できます。
def count(n):
while True:
yield n
n += 1
それがジェネレータ関数です。1 つの段落ですべての概念を説明できるとは思いませんが、基本的な考え方は次のとおりです。値を返す代わりに、値のシーケンスを生成します。にヒットするたびyield
に、呼び出し元は値を取得します。次の値を要求するたびに、残ったところから右に移動し、次の まで進みyield
ます。インタラクティブ インタープリターでしばらくアイデアを試してみると、うまくいくかもしれませんが、Google でチュートリアルを探したほうがよいでしょう。
次に、折り畳み関数を使用して各変換を適用することもできますが、この時点で熟考するには少し高度すぎる可能性があるため、さらに 2 つのジェネレーター関数を使用して明示的に記述しました。
最後に、consume
それ自体が少し異なります。これはジェネレーターではなく、次のようにイテレーターを受け取って変更する関数です。
def consume(iter, n):
for i in range(n):
next(iter)
したがって、 があり、最初の 3 つの要素があれば[1, 2, 3, 4, 5, 6, …]
、consume
が得られ[4, 5, 6, …]
ます。