Ruby代码说明:使用递归的数字到字符串

时间:2017-01-16 10:11:10

标签: ruby recursion

有人分享了一些关于他们如何完成挑战的Ruby代码,您必须将数字转换为单词。这个解决方案是迄今为止最简单的解决方案,但我并不完全理解它的递归方面。具体来说,在下面的行中......

elsif int.to_s.length == 1 && int/num > 0
  return str + "#{name}" 

如果一个return语句将代码从循环中分解出来,为什么这个代码不会执行并在一旦为真时中断循环?例如,当int = 4且num = 1时,这将被证明是真的并触发return语句,但代码一直持续到num = 4。

对代码的这一方面的任何澄清,以及理解此解决方案的任何一般性建议都会有所帮助。仍在努力理解递归。感谢

def in_words(int)
  numbers_to_name = {
      1000000 => "million",
      1000 => "thousand",
      100 => "hundred",
      90 => "ninety",
      80 => "eighty",
      70 => "seventy",
      60 => "sixty",
      50 => "fifty",
      40 => "forty",
      30 => "thirty",
      20 => "twenty",
      19=>"nineteen",
      18=>"eighteen",
      17=>"seventeen", 
      16=>"sixteen",
      15=>"fifteen",
      14=>"fourteen",
      13=>"thirteen",              
      12=>"twelve",
      11 => "eleven",
      10 => "ten",
      9 => "nine",
      8 => "eight",
      7 => "seven",
      6 => "six",
      5 => "five",
      4 => "four",
      3 => "three",
      2 => "two",
      1 => "one"
    }

  str = ""
  numbers_to_name.each do |num, name|
    if int == 0
      return str
    elsif int.to_s.length == 1 && int/num > 0
      return str + "#{name}"      
    elsif int < 100 && int/num > 0
      return str + "#{name}" if int%num == 0
      return str + "#{name} " + in_words(int%num)
    elsif int/num > 0
      return str + in_words(int/num) + " #{name} " + in_words(int%num)
    end
  end
end

puts in_words(4) == "four"
puts in_words(27) == "twenty seven"
puts in_words(102) == "one hundred two"
puts in_words(38_079) == "thirty eight thousand seventy nine"
puts in_words(82102713) == "eighty two million one hundred two thousand seven hundred thirteen"

1 个答案:

答案 0 :(得分:1)

调试代码

这是一个修改版本,每个分支都有调试行:

def in_words(int, indent="")
  puts "#{indent}in_words(#{int})"
  numbers_to_name = {
      1000000 => "million",
      1000 => "thousand",
      100 => "hundred",
      90 => "ninety",
      80 => "eighty",
      70 => "seventy",
      60 => "sixty",
      50 => "fifty",
      40 => "forty",
      30 => "thirty",
      20 => "twenty",
      19=>"nineteen",
      18=>"eighteen",
      17=>"seventeen", 
      16=>"sixteen",
      15=>"fifteen",
      14=>"fourteen",
      13=>"thirteen",              
      12=>"twelve",
      11 => "eleven",
      10 => "ten",
      9 => "nine",
      8 => "eight",
      7 => "seven",
      6 => "six",
      5 => "five",
      4 => "four",
      3 => "three",
      2 => "two",
      1 => "one"
    }

  str = ""
  numbers_to_name.each do |num, name|
    puts "#{indent}  testing #{num}"
    if int == 0
      puts "#{indent}   Empty string"
      return str
    elsif int.to_s.length == 1 && int/num > 0
      puts "#{indent}  Single digit found (#{name})!"
      return str + "#{name}"      
    elsif int < 100 && int/num > 0
      puts "#{indent}  Double digits found (#{name})!"
      return str + "#{name}" if int%num == 0
      puts "#{indent}  Recursive call with #{int%num} :"
      return str + "#{name} " + in_words(int%num, indent+"  ")
    elsif int/num > 0
      puts "#{indent}  Recursive call with #{int/num} and #{int%num} :"
      indent += "  "
      return str + in_words(int/num, indent) + " #{name} " + in_words(int%num,indent)
    end
  end
end

对于in_words(4),输出:

in_words(4)
  testing 1000000
  testing 1000
  testing 100
  testing 90
  testing 80
  testing 70
  testing 60
  testing 50
  testing 40
  testing 30
  testing 20
  testing 19
  testing 18
  testing 17
  testing 16
  testing 15
  testing 14
  testing 13
  testing 12
  testing 11
  testing 10
  testing 9
  testing 8
  testing 7
  testing 6
  testing 5
  testing 4
  Single digit found (four)!
four

对于27:

in_words(27)
  testing 1000000
  testing 1000
  testing 100
  testing 90
  testing 80
  testing 70
  testing 60
  testing 50
  testing 40
  testing 30
  testing 20
  Double digits found (twenty)!
  Recursive call with 7 :
  in_words(7)
    testing 1000000
    testing 1000
    testing 100
    testing 90
    testing 80
    testing 70
    testing 60
    testing 50
    testing 40
    testing 30
    testing 20
    testing 19
    testing 18
    testing 17
    testing 16
    testing 15
    testing 14
    testing 13
    testing 12
    testing 11
    testing 10
    testing 9
    testing 8
    testing 7
    Single digit found (seven)!
twenty seven

答案

  

例如,当int = 4且num = 1时,这将证明是真的   触发return语句,但代码一直持续到num = 4。

4作为输入,num = 1永远不会发生。 numbers_to_name按递减顺序排列,因此返回语句将发生在num=4,并且该方法将不会执行任何其他代码。