代碼
require 'prime'
def even_nbr_divisors?(n)
return false if n==1
arr = Prime.prime_division(n).map { |v,exp| (0..exp).map { |i| v**i } }
arr.shift.product(*arr).map { |a| a.reduce(:*) }.size.even?
end
closed, open = (1..100).partition { |n| even_nbr_divisors?(n) }
closed #=> [ 2, 3, 5, 6, 7, 8, 10, 11, 12, 13, 14, 15, 17, 18, 19, 20, 21, 22,
# 23, 24, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 37, 38, 39, 40,
# 41, 42, 43, 44, 45, 46, 47, 48, 50, 51, 52, 53, 54, 55, 56, 57,
# 58, 59, 60, 61, 62, 63, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74,
# 75, 76, 77, 78, 79, 80, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91,
# 92, 93, 94, 95, 96, 97, 98, 99],
open #= [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
說明
所有的門都關閉開始。考慮第24門。它下面的次經過時被觸發:
pass 1: opened
pass 2: closed
pass 3: opened
pass 4: closed
pass 6: opened
pass 8: closed
pass 12: opened
pass 24: closed
注意,門對每個24
的除數的切換一次。因此,如果我們有一個方法divisors(n)
是返回n
的除數的數組,我們能夠確定切換的數量如下:
nbr_toggles = divisors(24).size
#=> [1,2,3,4,6,8,12,24].size
#=> 8
由於門被切換爲偶數的時候,我們得出這樣的結論在塵埃落定之後將處於原始狀態(關閉)。同樣,對於n = 9
,
divisors(9).size
#=> [1,3,9].size
#=> 3
因此,我們得出結論:門#9將在年底開放的,因爲3
是奇數。
divisors
可定義如下。
def divisors(n)
arr = Prime.prime_division(n).map { |v,exp| (0..exp).map { |i| v**i } }
arr.first.product(*arr[1..-1]).map { |a| a.reduce(:*) }
end
例如,
divisors 24
#=> [1, 3, 2, 6, 4, 12, 8, 24]
divisors 9
#=> [1, 3, 9]
divisors 1800
#=> [1, 5, 25, 3, 15, 75, 9, 45, 225, 2, 10, 50, 6, 30, 150, 18, 90, 450,
# 4, 20, 100, 12, 60, 300, 36, 180, 900, 8, 40, 200, 24, 120, 600, 72,
# 360, 1800]
由於我們只當有奇數或偶數除數的關心,我們可以改爲寫
def even_nbr_divisors?(n)
return false if n==1
arr = Prime.prime_division(n).map { |v,exp| (0..exp).map { |i| v**i } }
arr.shift.product(*arr).map { |a| a.reduce(:*) }.size.even?
end
爲n = 24
,其操作步驟如下:
n = 24
a = Prime.prime_division(n)
#=> [[2, 3], [3, 1]]
arr = a.map { |v,exp| (0..exp).map { |i| v**i } }
#=> [[1, 2, 4, 8], [1, 3]]
b = arr.shift
#=> [1, 2, 4, 8]
arr
#=> [[1, 3]]
c = b.product(*arr)
#=> [[1, 1], [1, 3], [2, 1], [2, 3], [4, 1], [4, 3], [8, 1], [8, 3]]
d = c.map { |a| a.reduce(:*) }
#=> [1, 3, 2, 6, 4, 12, 8, 24]
e = d.size
#=> 8
e.even?
#=> true
最後,
(1..100).partition { |n| even_nbr_divisors?(n) }
返回上面顯示的結果。
作爲一個說明,在處理打開狀態時,通常最好在內部表示爲'true' /'false'。這比同一事物的字符串表示不那麼混亂。當你想要的時候,你可以用正確的標籤來渲染它們。另外,'open =!open'比這個測試字符串的大'if'更容易理解。此外,'Array.new(100,'closed')'在每個插槽中生成一個具有'關閉'的100元素數組。 – tadman
一般提示,請考慮使用'with_index(1)'。 –
在tadman的評論中捎帶,如果我正在接近這個問題,我會創建一個Door類來跟蹤它是否打開或關閉,並有一個'#toggle!'方法來在內部切換狀態。你正在用Ruby寫這篇文章 - 我建議利用該語言的優勢。 – Matt