I'm trying to figure out a homework solution in Ruby. I want the answer obviously but you feel it defeats the purpose if I post it here and someone tells me 'this is how you do it'
I am trying to translate fixnum into English word pronunciations, up until the trillionth sizes. So it handles everything from 0 to 999_999_999_999_999
At first I thought of stacking the string as a FILO queue and simply .pop my way through it with a position 'count' to indicate what 'hundred' or 'thousand ' I am currently to spell out. The words, and denomination are set to class instance global hash values to call and verify as a key.
I'm not sure if it's a stupid question but I'm looking for a way to help me think to understand this small problem.
here's my spaghetti code. an improvement to the orignal of 95+ lines.
class Fixnum
@@one_to_teen = {0 => "", 1 => 'one', 2 => "two", 3 => 'three', 4 => "four", 5 => 'five', 6 => 'six', 7=> 'seven', 8 => "eight", 9 => 'nine', 10 => 'ten', 11 => "eleven", 12 => 'twelve', 13 => 'thirteen', 14 => "fourteen", 15 => "fifteen", 16 => 'sixteen', 17 => "seventeen", 18 => "eighteen", 19 => "nineteen"}
@@tens = {20 => "twenty", 30 => 'thirty', 40 => 'forty', 50 => 'fifty', 60 => 'sixty', 70 => 'seventy', 80 => 'eighty', 90 => 'ninety'}
@@count_flag = {3 => "hundred", 4 => "thousand", 9 => "million", 12 => "billion", 15 => "trillion"}
def in_words
return "zero" if self == 0
return @@one_to_teen[self] if self < 20
#stack up
num_stack = self.to_s.split('')
count = 0
temp_str = ""
in_words_str = ""
final_str = ""
#loop until empty
#i was trying to see if resetting the temp_str after being handle in the if statements helped get rid of the stack being used. not originally part of the logic.
while !num_stack.empty?
#puts num_stack.inspect
temp_str << (num_stack.pop unless num_stack.empty?)
count+=1
if count%4 == 0
in_words_str = "#{@@one_to_teen["#{temp_str[temp_str.length-1]}".to_i]} #{@@count_flag[count]} "
temp_str = ""
elsif count%3 == 0
if temp_str[temp_str.length-1] != "0"
in_words_str = "#{@@one_to_teen["#{temp_str[temp_str.length-1]}".to_i]} #{@@count_flag[count]} "
#puts temp_str
end
elsif count%2 == 0
in_words_str = "#{@@tens[("#{temp_str[1]}0").to_i]} #{@@one_to_teen[check_teens(temp_str).to_i]}"
temp_str = ""
end
final_str = in_words_str + final_str
end
#somewhere in my logic i needed to do this, i was getting double spaces due to concat somewhere. bandaided it for now...
return final_str.strip.gsub(" "," ")
end
def check_teens(temp_str)
#swapping here to get correct "20" or higher wording.
if temp_str.reverse.to_i < 20
#puts temp_str.reverse
return temp_str.reverse
else
return temp_str[0]
end
end
end
If you look at how you say 346,422,378 it's three hundred and forty six million four hundred and twenty two thousand three hundred and seventy eight.
You already have the right idea of mapping the groups of three to ones, tens and hundreds. Those then just get repeated.
So the algorithm might go something like:
Here's what I would keep: edited to comply with original spec
Try to divide it into steps that make sense as methods that can be chained. Post any changes you make and I'll be happy to critique.