Euler 017 ruby Solution

Number letter counts

Problem

https://projecteuler.net/problem=17

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?

NOTE: Do not count spaces or hyphens. For example, 342 (three hundred and forty-two) contains 23 letters and 115 (one hundred and fifteen) contains 20 letters. The use of “and” when writing out numbers is in compliance with British usage.

Answer: 21124

Solution

euler017.rb

require 'humanize'

def simple_humanize_length(number)
  raise ArgumentError, 'Only supports (1..99999)' unless (1..99_999).cover?(number)

  result = ''
  working = number

  while working.positive?
    case working
    when (1000..99_999)
      how_many = (working / 1000).floor
      working -= 1000 * how_many
      result += "#{simple_humanize_length(how_many)}thousand"
    when (100..999)
      how_many = (working / 100).floor
      working -= 100 * how_many
      result += "#{simple_humanize_length(how_many)}hundred#{'and' unless working.zero?}"
    when (20..99)
      how_many = (working / 10).floor
      working -= 10 * how_many
      result += case how_many
                when 4, 5, 6 # forty, fifty, sixty = 5
                  'aaaaa'
                when 2, 3, 8, 9 # twenty, thirty, eighty, ninety = 6
                  'bbbbbb'
                when 7 # seventy = 7
                  'ccccccc'
                end
    else
      result += case working
                when 1, 2, 6, 10 # one, two, six, ten = 3
                  'ddd'
                when 4, 5, 9 # four, five, nine = 4
                  'eeee'
                when 3, 7, 8 # three, seven, eight = 5
                  'fffff'
                when 11, 12 # eleven, twelve = 6
                  'gggggg'
                when 15, 16 # fifteen, sixteen = 7
                  'hhhhhhh'
                when 13, 14, 18, 19 # thirteen, fourteen, eighteen, nineteen = 8
                  'iiiiiiii'
                when 17
                  'jjjjjjjjj' # seventeen = 9
                end
      working = 0
    end
  end
  result
end

def number_letter_counts(upper)
  (1..upper).reduce(0) do |sum, digit|
    sum + simple_humanize_length(digit).length
  end
end

def number_letter_counts_cheat(upper)
  (1..upper).reduce(0) { |sum, digit| sum + digit.humanize.tr(' -', '').length }
end

puts "Mine: #{number_letter_counts(1000)}" if __FILE__ == $PROGRAM_NAME
puts "Cheat: #{number_letter_counts_cheat(1000)}" if __FILE__ == $PROGRAM_NAME

See Also