iT邦幫忙

2021 iThome 鐵人賽

DAY 7
0
自我挑戰組

從真「新」鎮出發!30天的刷題修行篇,讓寫程式成為新必殺技系列 第 7

奇數金字塔,你想得出來最佳解答嗎?Ruby 30 天刷題修行篇第七話

大家好,我是 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 的三次方...

馬上試算了一下,還真的是這樣,自己繞了一大圈原來最佳解答這麼「樸素」,可惡,最討厭「數感」好的人啦~


上一篇
初探編碼的世界,Ruby 30 天刷題修行篇第六話
下一篇
資料型別轉轉轉,Ruby 30 天刷題修行篇第八話
系列文
從真「新」鎮出發!30天的刷題修行篇,讓寫程式成為新必殺技16

尚未有邦友留言

立即登入留言