質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.60%

関数ないでの挙動に関してアドバイスお願いします!

解決済

回答 1

投稿

  • 評価
  • クリップ 1
  • VIEW 468

score 26

2つ文字列が与えられます。1つ目は見本で、2つ目は、見本とは形が少し違うものです。2つ目の文字列を1つ目の文字列と同じにしたいのですが、左から右へしか動かすことはできないというルールがあります。例えば、abcをcabに直したいときは、abc->bca->cabとしなければなりません。そして最後に、最短で何回動かしたかを出力するのが目的となっています。以下のコードは、思考中だった時の失敗コードなのですが、2点だけわからないところがあります。
その内容は、
1.出力結果は4つ出てくると考えるのですが、結果は3つなのはなぜか。
2.出力されるtotalの最後が1と出力されるのは、なぜか。
です。
また、下記に私の考えを図にした写真を添付しました。

r=[5, "APPLE", "LEAPP"] #左から、文字数、見本の文字、修正する文字 です。
num=int(r[0])
total=0![イメージ説明](579b966b29c1558bdca0a87c0486de6c.jpeg)
model=[]
target=[]
for i in range(num):
    model.append(r[1][i])
    target.append(r[2][i])
def sorten(total):
    for i in range(num):
        #print(total)
        #print(target) 
        if model[i]!=target[i]:
            moji=target[0]
            target.pop(0)
            target.append(moji)
            #print(target)
            total+=1
            sorten(total)
    print(total)
sorten(total)
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • tiitoi

    2019/02/09 00:26

    以下の質問が似てる問題な気がします
    https://teratail.com/questions/170500

    キャンセル

回答 1

checkベストアンサー

+2

関数の中で、その関数それ自身を呼び出すことを「再帰」といいます。
そこで、最初の「sorten」の呼出しを「再帰前のsorten」と、その中での「sorten」の呼出しを「再帰1回目のsorten」などと呼んで説明していきます。

① 再帰前のsorten
最初のfor で、i は 0 です。
target['L', 'E', 'A', 'P', 'P'] です。
model[0] はAで、target[0]Lなので、ifのボディの部分が実行されます。
その結果、target['E', 'A', 'P', 'P', 'L']に、total1になって、「再帰1回目のsorten」に突入します。

② 再帰1回目のsorten
i0で、target[0]Eです。Aではないので、ifのボディが実行されます。
その結果、target['A', 'P', 'P', 'L', 'E']に、total2になって、「再起2回目のsorten」に突入です。

③ 再帰2回目のsorten
i0で、target[0]Aなので、ifのボディは実行されず、sortenの最後の行のprint(total)がようやく実行されます。
total2だったので、2が表示され、「再帰2回目のsorten」は終了します。
そして、中断していた「再帰1回目のsorten」の続きを行います。

④ 再帰1回目のsortenの続き
i1になって、forのボディを実行します。
target['A', 'P', 'P', 'L', 'E']なので、target[1]Pです。
model[1]Pなので、ifのボディは実行されず、print(total)が実行されます。
「再帰1回目のsorten」の中で、total2になっていたので、2が表示され、「再帰1回目のsorten」は終了します。
そして、中断していた「再帰前のsorten」を再開します。

⑤ 再帰前のsortenの続き
i1になって、forのボディを実行しますが、target['A', 'P', 'P', 'L', 'E']なので、ifのボディは実行されず、sorten最後の行のprint(total)が実行されます。
「再帰1回目のsorten」に突入するときのtotsl1でしたから、ここでは1が表示され、「再帰前のsorten」も終了します。

sortenの仮引数であるtotalはローカルな変数なので、関数の途中で中断して再起に突入した場合、再帰の中でtotalの数が増えても、中断したところに戻って再開したら、totalの値は、中断前の値で再開されるのです。
グローバルなtargetとの違いです。

⑥ まとめ
以上から、出力の数は3つで、最後の出力は1になります。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/02/09 13:42

    回答ありがとうございます!
    targetがグローバル変数であることを失念していました!
    スッキリしました!

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.60%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る