約数の和が自分自身より大きな数をabundant numberと呼ぶ。28123より大きな数は全て2つのabundant numberの和として表せるが、28123以下の数では必ずしもそうではない。2つのabundant numberの和で表せない全ての数の和を求める。
abundant number はリスト内包表記を使えば網羅できそうだ。あとはそれらの和で表せない数というのをどのように表現するか。表せない数のリストが得られれば、その和を取るだけなのだが…。
しばらく悩んだが、欲しいのは表せない数のリストではなく、表せない数の和だと気付いた。そして表せる数はもうリストになっているのだから、全体の和から表せる数の和を引けば、残りが欲しい和になる。
しれっとdivsSumなる関数を使っているが、これはproblem21の使い回しである。
さて、上記のコードで答えは出るものの、ハッキリ言って遅い。しかし試行錯誤を繰り返すも、抜本的な改善には至らなかった。現状ではこれ以上速いコードが見つからない。
mksumsという関数は2つのabundant numberの和で表される数を網羅する関数である。全ての組み合わせを作るために、はじめはリスト内包表記を使った普通の方法を採用していたが、それよりもzipWithを使ってみた方が少しだけ早かった。 また、28123以下の数だけを対象にすれば良いので、filter ( < 28123 ) をしようとしたが、それよりも sort.takeWhile ( < 28123 )の方が早かったのでそうした。nubは重複を削除する関数で、いくつかの実装があるが、知られているものをいくつか試したが、処理速度に大きな違いは見られなかった。
というわけで、引き続き改善を模索する。
★★★