昨今、codewarsの問題に取り組んでいます。その備忘録。
今回の問題
Given two integers a and b, which can be positive or negative, find the sum of all the integers between and including them and return it.
If the two numbers are equal return a or b.
(1, 0) --> 1 (1 + 0 = 1)
(1, 2) --> 3 (1 + 2 = 3)
(0, 1) --> 1 (0 + 1 = 1)
(1, 1) --> 1 (1 since both are same)
(-1, 0) --> -1 (-1 + 0 = -1)
(-1, 2) --> 2 (-1 + 0 + 1 + 2 = 2)
要約すると、下記を満たす関数を書け
・a,bの2つの数値を与えられ、その間にある数を全て足す
・a,bはどちらが大きいかはランダム
・もしa,bが同じ数値だった場合はその数を返す
これがどうにもエラーばかり出てしまい、心が折れて答えを見てしまいました…
ベストプラクティス
ベストプラクティスは下記。
const GetSum = (a, b) => {
let min = Math.min(a, b),
max = Math.max(a, b);
return (max - min + 1) * (min + max) / 2;
}
ところが答えを見てもよく理解できず。。
a,bがどちらがmin,maxかを求めたあと、returnされている数式がよくわからない。。
数式を調べた
ガウスの等差数列の和
色々調べた結果、数式は等差数列の和の公式だとわかった。
(x:解、n:数列の長さ、とする)
x = n * (a + b) / 2
数学者ガウスさんはこの問題を与えられたときに(小学生だったそうです)下記のように考えた。
最初と最後の数字を足して101、二番目と最後から二番目を足して101、それを順々にやっていくと101が100個できる。
101×100=10100
それは二つの数列を足した数なので、それを2で割れば答えがでるというもの。
(つまりは101*100*1/2=5050が答え)
図で考えると理解しやすい
a=1,b=5の場合で考える。上の図のように、ブロックで考えてみる。
二つの数列のブロックを足してみると、長方形ができるので、それぞれの縦横をかける。知りたいのは黄色に塗られている部分(ちょうど半分)なので、二で割った数が答え。
これで等差数列の和について少し理解が深まった、なるほど、そういう考えか。
数列の長さの求め方
n = (max – min + 1)の意味がよく理解できなかったが、下記の式を基に考えればいいのだと分かった。
例:
a : 始まりの数値
b : 終わりの数値
n : 数列の長さ
d : 公差(いくつずつ増えてるか)
b = a + d * (n - 1)
これを利用してあげると、n(数列の長さ)も求めらる。今回の問題では、d=1なので、
n = (b - a) + 1
で求めてるということですね。
数学知らないと難しい。。
c.sakyou