質問: i.toString().split('').reduce((p, c) => p + parseInt(c), 0); return (n >= A && n <= B); }); console.log(nums.reduce((p, c) => p + c, 0)); } main(require('fs').readFileSync('/dev/stdin', 'utf8')); ``` ### 試したこと 各関数について全て調べた
回答: ラムダ式、クロージャなどの要素は理解できているとみなして解説します。 `Array.from(array,map)` 配列arrayからmapで定義した処理を通して新しい配列を作ります。 1引数目:`new Array(N)` 空の要素の配列を要素N個分作ります。 2引数目:`(v,i) => ++i` これは適用するmap関数の中身です。`array.map((v,i) => i++)`と同じ動作。 mapに入れる関数(今回はラムダ式)の引数は(処理する値, インデックス, もとの配列)の3つがあり、後ろ2つは省略可能。 今回のコードでは3番目の引数が省略されています。インデックス+1したものを新しい配列として作っています。なので処理結果は`[1,2,3,4...]`になります。 `(省略).filter((i) => {...})` filterは配列の各要素を指定の条件で検査し、合格(返り値がtrue)の要素だけで構成した新しい配列を返します。 これもラムダ式になっていますが条件関数本体はクロージャの中にあります。前項で作った配列の中身が1つずつ`i`に入る。 で、クロージャの中身の解説を順番に。 `i.toString().split('')` 数値`i`を文字列にして、1文字ずつ分解して配列にする。`123`が`['1','2','3']`となる。 `.reduce((p, c) => p + parseInt(c), 0)` 上記で作成した配列の要素それぞれに対し、引数の関数で計算処理を行い、単一の値を返します。 `p`が処理の戻り値として返したい値で、`c`は配列の各要素になります。 ここでは`p`にparseInt(c)の値をどんどん足しこんでいく処理になります。`p = p + parseInt(c)`という処理を配列の要素分繰り返すイメージで良いでしょう。 最後の`0`は`p`の初期値です。これを設定し忘れるとこの処理は文字列連結になってしまいます。 `return (n >= A && n <= B)` filter関数の最後の処理。各桁を足した数`n`がA以上B以下であればtrue、それ以外ならfalse。 filter関数はこの処理がtrueになった値だけで構成された新しい配列を返します。 最終的に`nums`は各桁の総和がA以上B以下の整数の配列となります。 最後、console文の中身。 `nums.reduce((p, c) => p + c, 0)` 先ほどのreduce関数と同じように配列の中の数値の総和を求めています。 なお、変数名を日本語で書き下し、処理を分割して記述するとこんな感じになります。 ``` var 元の配列 = Array.from(new Array(N), (v, i) => ++i); var 条件に合致した数字の配列 = 元の配列.filter((数字) => { var 各桁に分解した配列 = 数字.toString().split(''); var 各桁の総和 = 各桁に分解した配列.reduce((合計,数字) => 合計 + parseInt(数字),0); return (A <= 各桁の総和 && 各桁の総和 <= B); }); console.log(条件に合致した数字の配列.reduce((合計,数字) => 合計 + 数字,0)); ```