我有一系列名字。每个字母的字母表值为1到26。然后将该字母乘以其在列表中的位置。我提出了以下算法:
score = 0
names.each_with_index do |name, index|
temp = 0
letters = name.to_s.scan(/(.)/)
letters.each do |letter|
temp += 1 if letter.to_s.match(/A/)
temp += 2 if letter.to_s.match(/B/)
temp += 3 if letter.to_s.match(/C/)
temp += 4 if letter.to_s.match(/D/)
temp += 5 if letter.to_s.match(/E/)
temp += 6 if letter.to_s.match(/F/)
temp += 7 if letter.to_s.match(/G/)
temp += 8 if letter.to_s.match(/H/)
temp += 9 if letter.to_s.match(/I/)
temp += 10 if letter.to_s.match(/J/)
temp += 11 if letter.to_s.match(/K/)
temp += 12 if letter.to_s.match(/L/)
temp += 13 if letter.to_s.match(/M/)
temp += 14 if letter.to_s.match(/N/)
temp += 15 if letter.to_s.match(/O/)
temp += 16 if letter.to_s.match(/P/)
temp += 17 if letter.to_s.match(/Q/)
temp += 18 if letter.to_s.match(/R/)
temp += 19 if letter.to_s.match(/S/)
temp += 20 if letter.to_s.match(/T/)
temp += 21 if letter.to_s.match(/U/)
temp += 22 if letter.to_s.match(/V/)
temp += 23 if letter.to_s.match(/W/)
temp += 24 if letter.to_s.match(/X/)
temp += 25 if letter.to_s.match(/Y/)
temp += 26 if letter.to_s.match(/Z/)
end
score += (index+1) * temp
end
puts score
这是非常慢的代码。我希望有人可以向我解释一个更好,更快的方法来完成这项任务。
答案 0 :(得分:3)
我就是这样做的。
<强>假设强>
a
的字母偏移求和,然后乘以数组中字的(基数1)位置<强>代码强>
def totals_by_name(names)
names.each.with_index(1).with_object({}) { |(name,i),tots|
tots[name] = i*(name.downcase.each_char.reduce(0) { |tot,c|
tot + c.ord - 'a'.ord + 1 }) }
end
def total(names)
totals_by_name(names).values.reduce(:+)
end
示例强>
names = %w{ Joanne Jackie Joe Jethro Jack Jill }
#=> ["Joanne", "Jackie", "Joe", "Jethro", "Jack", "Jill"]
total(names)
#=> 914
<强>解释强>
对于方法totals_by_name
和上面的数组names
:
e0 = names.each
#=> #<Enumerator: ["Joanne", "Jackie", "Joe", "Jethro", "Jack", "Jill"]:each>
我们可以通过将它转换为数组来查看此枚举器将传递的值:
e0.to_a
#=> ["Joanne", "Jackie", "Joe", "Jethro", "Jack", "Jill"]
继续,
e1 = e0.with_index(1)
#=> #<Enumerator: #<Enumerator: ["Joanne", "Jackie", "Joe", "Jethro",
# "Jack", "Jill"]:each>:with_index(1)>
e1.to_a
#=> [["Joanne", 1], ["Jackie", 2], ["Joe", 3], ["Jethro", 4], ["Jack", 5], ["Jill", 6]]
e2 = e1.with_object({})
#=> #<Enumerator: #<Enumerator: #<Enumerator: ["Joanne", "Jackie", "Joe",
# "Jethro", "Jack", "Jill"]:each>:with_index(1)>:with_object({})>
e2.to_a
#=> [[["Joanne", 1], {}], [["Jackie", 2], {}], [["Joe", 3], {}],
# [["Jethro", 4], {}], [["Jack", 5], {}], [["Jill", 6], {}]]
我们可以将e2
和e3
视为复合枚举数。
Enumerator#每个都将e2
的元素传递给块,并将值赋给块变量。我们可以使用Enumerator#next来查看会发生什么:
(name,i),tots = e2.next
#=> [["Joanne", 1], {}]
name #=> "Joanne"
i #=> 1
tots #=> {}
块计算是:
e3 = name.downcase.each_char
#=> #<Enumerator: "joanne":each_char>
e3.to_a # have a look
#=> ["j", "o", "a", "n", "n", "e"]
e3.reduce(0) { |tot,c| tot + c.ord - 'a'.ord + 1 }
#=> 59
有关
c = "j"
这个块计算是:
tot + c.ord - 'a'.ord + 1
#=> 0 + 106 - 97 + 1
#=> 10
因此:
tots[name] = i*(name.downcase.each_char.reduce(0) { |tot,c|
tot + c.ord - 'a'.ord + 1 })
#=> tots["Joanna"] = 1*(59)
tots
#=> {"Joanne"=>59}
其他名称的值类似地计算。方法tots
很简单。
答案 1 :(得分:2)
我很可能会选择:
class String
def points
each_char.map.with_index do |char, index|
(char.downcase.ord - 96) * (index + 1)
end.inject(0, :+)
end
end
'Hello'.points #=> 177