大家好,我是 A Fei,又到了我們愉快的解題時間,這次我們要來做一道數列的題型。廢話不多說,直接進入題目:
(題目來源為 Codewars)
Given the triangle of consecutive odd numbers:
1
3 5
7 9 11
13 15 17 19
21 23 25 27 29
...
Calculate the sum of the numbers in the nth row of this triangle (starting at index 1) e.g.: (Input --> Output)
1 --> 1
2 --> 3 + 5 = 8
題目給你一個奇數數列的金字塔(或聖誕樹),要我們算出第 n 階上數字的總和。雖然這次題目敘述簡單明瞭,很棒,但是我卻解超~級~久~反覆嘗試將數列畫在紙上,想找出其中的規律,像是每一層第一個數相差 2, 4, 6, 8...,有規律但實在想不出解法,這時候就很佩服「數感」很好的人。
但我最後還是想出來了,耶!
以下為我的解答:
def row_sum_odd_numbers(n)
x = (1..n).inject(:+)
odd_arr = (1..x).map {|i| 2 * i - 1}
y = x - n
odd_arr[y, n].sum
end
讓我來為各位解說,x 代表的是「奇數數列的長度」,第一層有一個數(1)、第二層有三個數(1 + 2 = 3),以此類推。這邊用的 inject 就是大家熟悉的 reduce 方法,而 inject(:+) 就是總合的寫法,這個官網的範例有教,值得注意的是 inject 是屬於 Enumerable 類別下的方法,所以 Array 也可以使用。
接著把 1 ~ x 用 map ,將每個數字換算成奇數,當 n 帶入 1 時,odd_arr 為 [1]、當 n 帶入 2 時,odd_arr 為 [1, 3, 5],以此類推。到這裡我們已經可以得到,第 n 層時,所有會出現的奇數。
最後再把數列的長度 x 減去 n,會得到第 n 層第一個數的索引值 y(這題變數的命名都很隨便,請見諒),之後再用 odd_arr[y, n] 擷取出第 y 個值後 n 長度的陣列,再使陣列中的元素相加,就得到答案了!
當我還在沉浸破關的喜悅時,看到最佳解答瞬間讓我跌破眼鏡...
def row_sum_odd_numbers(n)
n**3
end
n 的三次方...
n 的三次方...
n 的三次方...
馬上試算了一下,還真的是這樣,自己繞了一大圈原來最佳解答這麼「樸素」,可惡,最討厭「數感」好的人啦~