Panda Noir

JavaScript の限界を究めるブログです。

forもifも使わないプログラミング入門2

前回は1から2016までの総和を取りました。今回はもうちょっと応用していきます。

1から2016までのうち、偶数のみを取り出して総和をとる

はい。いよいよ数式では難しくなってきました。いけないことはありませんが( (1+1008)1008/22 )、わかりづらいですよね。

しかし、rangeとreduceを使うだけでは、これもまたうまく動きません。そこで今回はfilterを使います。

filterとはその名のとおり絞り込むものです。これを使うとこのように書けます。

document.write(range(1, 2016).filter(n => n % 2 === 0).reduce((a, b) => a + b, 0));

%は割った余りを求める演算子、===は両辺が等しいか比べる演算子です。つまり n % 2 === 0 は「nを2で割った余りが0かどうか」、ということです。

filterは数列を先頭から順にnに入れていき、nを2で割った余りが0である要素、つまり偶数のみを抽出します。

だから、 range(1, 2016).filter(n => n % 2 === 0) というのは {2, 4, 6, 8, ... , 2014, 2016} という数列のことです。あとは前回の復習で総和取ってるだけです。

説明された後でコードを見返すと、実にコードが言葉をそのまま表していることがわかると思います。

1から2016までのうち完全数であるものを取りだしてみる

今回は総和を取りません。

完全数とは

まず完全数とはなんぞや?という人のために説明しておきます。完全数とは、その数の約数(その数自身は除く)の総和がその数自身である数のことです。

…わかりにくいので例を挙げます。例えば6です。6の約数は1,2,3,6で、6自身を除いた和が1+2+3=6であり、完全数となっています。他にも28や496なんかがあります。 1+2+4+7+14=28, 1+2+4+8+16+31+62+124+248=496です。

というかぶっちゃけ言うと今回の答えは{6,28,496}です。意外と完全数って少ないんですよね。

完全数を明文化してみる

以上を踏まえて完全数を文章にしてみます。

完全数とは、その数未満の数のうち、その数の約数であるものの総和と等しい数のことである。

こうですね。さて、明文化までできた、filterもreduceも使える、ここまでくれば自力で書けます。やってみたい人はどうぞ。しかし、まださすがに難しいと思うので答えもすぐ下に載せておきます。

コーディング

上の文章は実はコーディングしやすいように書きました。ちょっと違和感ありませんでしたか?「その数未満の数のうち」は約数って書けばいいじゃんとか。

…まあそれはさておき。コードはこちら。

document.write(range(1, 2016).filter(n =>
    n === range(1, n - 1).filter(m => n % m === 0).reduce((a, b) => a + b, 0)
));

このコード、口で説明しようとすると意外と厄介です。でも、先ほどの文章をそのままコードにしていることがわかるでしょうか?

終わりに

…そろそろ厳しくなってきました。rangeやreduceはforに意味を持たせて可読性は上げてくれるのですが、やはり限界があります。