約数について三角数について、イケてる書き方を教えてもらったのでさっそく試してみた。
primeFactors 関数を少し修正。
前回は割れるだけ割ったあとに割れた回数だけ replicate してリストを作っていたが、
[(基数, 指数)]のタプルのリストを返すようにしてみた。
primeFactors 50
-- 前回のバージョンでは [5,5,2]
-- 今回のバージョンでは [(5,2),(2,1)]
あとはwikipediaの約数の個数を参考に、 指数に1を足した値同士の積を取って約数の個数を求めるようにした。
最初 foldl (\n (_, a) -> n * (a + 1)) 1 $ primeFactors triNum として求めていたが、
Twitter でコメントをもらって product . map ((+1).snd) $ primeFactors triNum にしてみた。

少し悩んだのが updateList のところで、これは[(基数, 指数)]のタプルのリストの中に基数nを加えるとき、
すでにリストの中にあれば指数をインクリメントし、リストの中になければ指数1の新しいタプルを追加する、
と処理をやりたかったので作成した。
list=[(2,1),(5,2)] の場合、n=1 であれば[(1,1),(2,1),(5,2)]を、n=2であれば[(2,2),(5,2)]を返す、という具合。
しかしこれはもっとスマートに書けそうな気がするなぁ…。
find や lookup を使うか、elem や elemIndex を使うか…
巧いやり方が思いつかなかったのでガードとか if とか使って泥臭く実装してみたが。

Copyright© 2011-2021 Shunsuke Otani All Right Reserved .