2016-10-15 4 views
2

次のコードを実行すると、驚くべき出力が得られます。なぜ再帰関数の3番目の呼び出しでwhileループを入力する前後に、変数wordの値が変化しますか?ループ内でなぜ単語の変数が違うのですか?

def get_perms(word) 
    perms = [] 
    get_perm_recursive("",word, perms) 
    perms 
end 

def get_perm_recursive(prefix, word, perms) 
    puts "---------------------" 
    if word.length == 0 
    perms << prefix 
    end 

    i = 0 
    puts "Word outside loop: #{word}" 
    while i < word.length 
    puts "Word inside loop: #{word}" 
    prefix << word[i] 
    new_word = word[0...i] + word[i+1..-1] 
    get_perm_recursive(prefix, new_word, perms) 
    i += 1 
    end 

end 

get_perms("ab") 

出力:

--------------------- 
Word outside loop: ab 
Word inside loop: ab 
--------------------- 
Word outside loop: b 
Word inside loop: b 
--------------------- 
Word outside loop: 
Word inside loop: ab 
--------------------- 
Word outside loop: a 
Word inside loop: a 
--------------------- 
Word outside loop: 
+0

ようこそ!あなたが本当にここで何をしようとしているのか分かりません。ループはスコープゲートではなく、#get_perm_recursiveを呼び出すたびに* word *(したがってループ条件)のサイズを変更しています。実際の目標が何であっても表現するには、おそらくより良い方法があります。予想される結果(問題のコードだけでなく)で質問を更新することは大きな助けになります。 –

答えて

0

あなたはそれでループと再帰関数を持っています。いくつかの追加のログを追加してみてください:

def get_perms(word) 
    perms = [] 
    $level = 0 
    get_perm_recursive("",word, perms) 
    perms 
end 

def get_perm_recursive(prefix, word, perms) 
    $level += 1 
    puts "level: #{$level}" 
    puts "entering get_perm_recursive(#{prefix},#{word},#{perms}" 
    if word.length == 0 
    perms << prefix 
    end 

    i = 0 
    puts "Word outside loop: #{word}" 
    while i < word.length 
    puts "Word inside loop: #{word}, #{i}" 
    prefix << word[i] 
    new_word = word[0...i] + word[i+1..-1] 
    puts "Calling gets_perm_recursive recursively" 
    get_perm_recursive(prefix, new_word, perms) 
    i += 1 
    end 
    puts "done with gets perm recursive #{$level}" 

    $level -= 1 
end 

get_perms("ab") 

出力:

level: 1 
entering get_perm_recursive(,ab,[] 
Word outside loop: ab 
Word inside loop: ab, 0 
Calling gets_perm_recursive recursively 
level: 2 
entering get_perm_recursive(a,b,[] 
Word outside loop: b 
Word inside loop: b, 0 
Calling gets_perm_recursive recursively 
level: 3 
entering get_perm_recursive(ab,,[] 
Word outside loop: 
done with gets perm recursive 3 
done with gets perm recursive 2 
Word inside loop: ab, 1 
Calling gets_perm_recursive recursively 
level: 2 
entering get_perm_recursive(abb,a,["abb"] 
Word outside loop: a 
Word inside loop: a, 0 
Calling gets_perm_recursive recursively 
level: 3 
entering get_perm_recursive(abba,,["abba"] 
Word outside loop: 
done with gets perm recursive 3 
done with gets perm recursive 2 
done with gets perm recursive 1 
1

それはありません。どの出力から出力が生成されているのかを誤解しています。ここで

--------------------- # this is iteration 1 
Word outside loop: ab # this is iteration 1 
Word inside loop: ab # this is iteration 1 
--------------------- # this is iteration 2 
Word outside loop: b # this is iteration 2 
Word inside loop: b # this is iteration 2 
--------------------- # this is iteration 3 
Word outside loop: # this is iteration 3 
# Iteration 3 has NO FURTHER OUTPUT (because i is not less than word.length) 
# we are returned to Iteration 2 
# but... Iteration 2 ALSO has NO FURTHER OUTPUT (because i in that iteration, increased to 1, is not less than word length) 
# we are returned to Iteration 1 
Word inside loop: ab # this is the SECOND while loop in the first iteration, so yes, the word is "ab" 

はあなたが何をしているの繰り返し見るために出力を変更するための簡単な方法です...最初の反復は、そのデフォルト 1iterationの引数を持ち、次の反復をコールするたびにインクリメントされます。

def get_perm_recursive(prefix, word, perms, iteration=1) 
    puts "---------------------" 
    if word.length == 0 
    perms << prefix 
    end 

    i = 0 
    puts "Word outside loop: #{word} in iteration: #{iteration}" 
    while i < word.length 
    puts "Word inside loop: #{word} in iteration: #{iteration}"" 
    prefix << word[i] 
    new_word = word[0...i] + word[i+1..-1] 
    get_perm_recursive(prefix, new_word, perms, iteration + 1) 
    i += 1 
    end 

end 

ちなみに... get_permsはパーマ(permutations?)の配列を返すと思われます。しかし、あなたは順列呼び出しの中で計算されたpermsを返す仕組みがありません。各メソッドがpermsを返すようにし、返されたpermsを変数に代入する必要があります。

変更第1の方法と...

def get_perms(word) 
    perms = [] 
    perms = get_perm_recursive("",word, perms) 
    perms 
end 

... get_perm_recursiveの結果を変数に代入、またはさらに良くなるように、ちょうど最後の実行文としてget_perm_recursiveを持っています。

def get_perms(word) 
    get_perm_recursive("",word, []) 
end 

あなたはまた、トラップにget_perm_recursive WITHIN get_perm_recursiveの出力が必要なので、置き換え、

perms = perms + get_perm_recursive(prefix, new_word, perms) 

get_perm_recursive(prefix, new_word, perms) 

そしてget_perm_recursive方法の非常に最後の文が返す必要がありますpermsアレイ...

i += 1 
    end 
    perms 

end 

私が言及したいもう一つは、構造

i = 0 
while i < limiting_value 
    ... 
    i += 1 
end 

...ルビー風をされていません。より典型的でより良い実装は、

(0...limiting_value) do |i| 
    ... 
end 
+0

ありがとう!非常に役立ちます :) –

関連する問題