昨今、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

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA