kota9さんのソフトウェアエンジニアなら1時間で解けるべき問題5に挑戦。勉強になりました。再帰ってこういう風に考えるんですね。
#lambdaを使って書いてみる
そうそうに挑戦はあきらめて、後学のために写してみることにしました。ただ写しても面白くないので、またまたlambdaしばりっていうことで。
box=lambda *x:x
unbox=lambda x:x[-1]
do=box
switch=unbox
前準備です。自前switch使いたいので。折角作ったので自前foldlも使う。
foldl=(lambda f,acc,xs:
switch(
xs == [] and do( acc )
or do( foldl(f, f(acc, xs[0]), xs[1:]) )
)
)
整数を二つとってくっつける関数f_nと
整数のリストをとってくっつける関数ff_n。
intしたりstrしたりがちょっとイケてない感じ。
f_n=lambda x,y:int(str(x)+str(y))
ff_n=lambda xs:foldl(f_n,0,xs)
ここから本題。拡張性を考慮して整数のリストにしてみました。
f_5=(lambda NUMS, n,M:
(lambda digits=NUMS[:n],
r_n=range(1,n),
out=[]:
(lambda n_digits=ff_n(digits):
(
out.append(str(n_digits)) if n_digits==M else None,
[[ out.append(x + "+" + str(ff_n(digits[-i:n])))
for x in f_5(NUMS, n-i , M - ff_n(digits[-i:n])) ] for i in r_n ],
[[ out.append(x + "-" + str(ff_n(digits[-i:n])))
for x in f_5(NUMS, n-i , M + ff_n(digits[-i:n])) ] for i in r_n ],
out,
)[-1]
)()
)()
)
ff_5=lambda NUMS, M: f_5(NUMS, len(NUMS), M)
NUMS=range(1,10)
print ff_5(NUMS,100)
できた。
正の整数のリストだったらいけるようです。
試しに適当な数のリストで1000になるパターンを調べてみると
>>> ff_5([1,5,4,2,3,7,9,34,57,64,23],1000)
['15-4+2+37+934+57-64+23', '1+5-42-3+7+934+57+64-23']
#appendは出来るのね...
元が += で書かれてるので、どうやって返り値を蓄積するかちょっと悩みました。
引数outにデフォルトで[]を定義しておいてそこにappendで要素をどんどん足していくっていうの、たぶん出来るんじゃね?と思って書いてみたら、その通り動いてくれているようです。
これってもうほとんど...
#代入できるって言ってもいいレベルじゃない?
例えば
a=(lambda :
(lambda b=[]:
(b.append(1),
b.append(2),
b[0]+b[1],
)[-1]
)()
)
計算結果を空のリストに蓄積して後で使うことができちゃいます。
ほとんどローカル変数ですよね。これ。
実行してみると
>>> a()
3
popしてinsertすれば再代入も可能。
やらないけどね。ダサくなっちゃうから。