2017-01-16 3 views
2

数字を単語に変換する必要があるチャレンジをどのように完了したかについて、Rubyコードを共有しました。この解決策ははるかに読みやすいものでしたが、私はそれの再帰的な側面を完全には理解していません。具体的には、下の行にある...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

デバッグコード

ここでは、すべての枝にデバッグ線で修正されたバージョンです:

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:

は、 INT = 4とNUM = 1、これは真であることを証明し、 returnステートメントをトリガする、まだコードはNUM = 4

まで続くであろう
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 

回答例えば

4を入力すると、num = 1は発生しません。 numbers_to_nameは降順であるため、return文はnum=4のために発生し、その後はそのメソッドは他のコードを実行しません。

+0

ああ - ありがとう!私は今、各ループが何百万ドルものトップから始まっていることを認識しています。私の面倒を見落とす私にそれを見せてくれてありがとう! –

関連する問題