Find the Divisors
題目:
My friend John and I are members of the "Fat to Fit Club (FFC)". John is worried because each month a list with the weights of members is published and each month he is the last on the list which means he is the heaviest.
I am the one who establishes the list so I told him: "Don't worry any more, I will modify the order of the list". It was decided to attribute a "weight" to numbers. The weight of a number will be from now on the sum of its digits.
For example 99 will have "weight" 18, 100 will have "weight" 1 so in the list 100 will come before 99. Given a string with the weights of FFC members in normal order can you give this string ordered by "weights" of these numbers?
Example:
"56 65 74 100 99 68 86 180 90" ordered by numbers weights becomes: "100 180 90 56 65 74 68 86 99"
When two numbers have the same "weight", let us class them as if they were strings and not numbers: 100 is before 180 because its "weight" (1) is less than the one of 180 (9) and 180 is before 90 since, having the same "weight" (9) it comes before as a string.
All numbers in the list are positive numbers and the list can be empty.
思路:
輸入是一堆數字組成的字串 輸出也是一堆數字組成的字串 需要將輸入的字串拆開以後在各自字轉成數字排序 最後再把字串組回去後回傳
使用到的語法:
split:把字串拆開 join:把字串連起來
解完後發現優秀的程式碼裏有幾個符號
map(&:to_i)
reduce(:+)
找到說明如下
array.map(&:to_i)
This invokes .map on array, and for each element in the array, returns the result of calling to_i on that element.
reduce(:+)
Combines all elements of enum by applying a binary operation, specified by a block or a symbol that names a method or operator.
If you specify a block, then for each element in enum the block is passed an accumulator value (memo) and the element. If you specify a symbol instead, then each element in the collection will be passed to the named method of memo. In either case, the result becomes the new value for memo. At the end of the iteration, the final value of memo is the return value for the method.
If you do not explicitly specify an initial value for memo, then the first element of collection is used as the initial value of memo.
# Sum some numbers
(5..10).reduce(:+) #=> 45
# Same using a block and inject
(5..10).inject { |sum, n| sum + n } #=> 45
程式碼:
第一次撰寫
def order_weight(string)
string.empty? ? (return string) : false
weight = string.split(" ")
result = []
weight.each_with_index do |w,i|
result[i] = [count_num(w),w]
end
return result.sort!.transpose.last.join(" ")
end
def count_num(num)
r = 0
num.split("").map {|n| r += n.to_i}
return r
end
參考最佳解
def order_weight(string)
string.split.sort_by { |n| [n.chars.map(&:to_i).reduce(:+), n] }.join(" ")
end