ror dev newb - 1 year ago 58
Ruby Question

# Project Euler Task 17. Find number of all letters from a range of numbers

The problem:

If the numbers 1 to 5 are written out in words: one, two, three, four, five, then there are 3 + 3 + 5 + 4 + 4 = 19 letters used in total.
If all the numbers from 1 to 1000 (one thousand) inclusive were written out in words, how many letters would be used?

My solution:

``````require 'humanize'
arr, total = [], 0
(1..1000).to_a.map(&:humanize).each {|x| arr << x.delete(" ").delete("-")}.map {|y| total += y.length }
p total
``````

Other solution privided, by @Arif in other question, gives the right answer (according to Project Euler):

``````p (1..1000).to_a.map(&:humanize).join.tr(" -", "").size
``````

Why my solution is wrong? From my knowledge, these two implementations should give the same output...

Edit:
Found one more strange thing.
If I change 1000 to any number up to 20 and implementations looks like this:

``````(1..20).to_a.map(&:humanize).each {|x| arr << x.delete(" ").delete("-")}.map {|y| total += y.length }

p (1..20).to_a.map(&:humanize).join.tr(" -", "").size
``````

Your problem is that you are messing `map` with `each`.

``````(1..1000).to_a.map(&:humanize)
.each {|x| arr << x.delete(" ").delete("-") } # ??? each
.map {|y| total += y.length }                 # ??? map
``````

The call to `Enumerable#each` returns the original `Enumerable`, not `arr` or whatever youâ€™ve expected. Yes, you fulfilled `arr`, but the latter `map` is called on the original array, having all these spaces and dashes.

The correct way to implement it your way:

``````(1..1000).to_a.map(&:humanize)
.map { |x| x.delete(" ").delete("-") } # sic!, no need for arr
.each { |y| total += y.length } # no need to map here
``````

Or, more ruby idiomatic:

``````(1..1000).to_a.map(&:humanize)
.map { |x| x.delete(" ").delete("-") }
.reduce(:+) # reduce by summing everything up
``````

Or, even better (`to_a` is redundant here):

``````(1..1000).map(&:humanize)
.reduce(0) { |memo, x| memo + x.delete(" ").delete("-").length }
``````
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download