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

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

新規登録して質問してみよう
ただいま回答率
85.40%
Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

3回答

478閲覧

Python 再帰関数のエラー解決方法

kuiojl

総合スコア1

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

1クリップ

投稿2024/07/12 05:15

実現したいこと

まず、引数として文字列を2個受け取り、文字数の多い方を返す関数longer_stringを書きなさい。文字数が同じ場合は、どちらを返してもかまいません。
次に、引数として文字列のリストを1個受け取り、その中で文字数の一番多い文字列を返す関数longest_stringを次のようにして書きなさい。
リストの先頭の文字列と、残りのリストに対してlongest_stringを再帰的に呼び出した結果を、longer_stringで比較します。

発生している問題・分からないこと

このコードでエラーが発生したが、なぜダメなのかがわからない

#文字数の多い方を返す関数を定義
def longer_string(moji1,moji2):
if len(moji1)>len(moji2):
return moji1
elif len(moji1)==len(moji2):
return moji1
else:
return moji2
#何か引数に代入してみる
longer_string("sakurai","ono")

#リストの中で一番多い文字列を返す関数を定義する
def longest_string(moji_list):
#リストの先頭と残りのリストを定義
first=moji_list[0]
others=moji_list[1:]
#先頭以外の残りのリストの中で一番長いものを判定
others_1st=longest_string(others)
return longer_string(first,others_1st)

#5つの要素からなるリストを生成
moji_list=["sakurai","ono","ninomiya","aiba","matsumoto"]
print(longest_string(moji_list))

エラーメッセージ

error

1list index out of range

該当のソースコード

特になし

試したこと・調べたこと

  • teratailやGoogle等で検索した
  • ソースコードを自分なりに変更した
  • 知人に聞いた
  • その他
上記の詳細・結果

友人もわからないようである

補足

特になし

気になる質問をクリップする

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

meg_

2024/07/12 05:30

・コードはコードの挿入で記入してください。 ・エラーメッセージは省略されると原因が伝わりません。全て掲載してください。
kuiojl

2024/07/12 05:43

申し訳ありません IndexError Traceback (most recent call last) <ipython-input-5-b69de2c243fb> in <cell line: 23>() 21 #5つの要素からなるリストを生成 22 moji_list=["sakurai","ono","ninomiya","aiba","matsumoto"] ---> 23 print(longest_string(moji_list)) 5 frames <ipython-input-5-b69de2c243fb> in longest_string(moji_list) 13 def longest_string(moji_list): 14 #リストの先頭と残りのリストを定義 ---> 15 first=moji_list[0] 16 others=moji_list[1:] 17 #先頭以外の残りのリストの中で一番長いものを判定 IndexError: list index out of range
otn

2024/07/12 06:00

Pythonはインデントが重要な言語です。「該当のソースコード」の部分の```と```の間に書きましょう。 エラーメッセージは、コメント欄に書くのでなく、「エラーメッセージ」の```と```の間に書きましょう。
guest

回答3

0

リスト(moji_list)の先頭2個の文字列を取り出して longer_string() に渡して、その戻り値(より長い文字列)と moji_list の残り(moji_list[2:])をリスト化して longest_string()` に渡します。

python

1def longer_string(moji1,moji2): 2 if len(moji1)>=len(moji2): 3 return moji1 4 else: 5 return moji2 6 7#リストの中で最も長い文字列を返す関数を定義する 8def longest_string(moji_list): 9 match len(moji_list): 10 case 0: return None 11 case 1: return moji_list[0] 12 case _: 13 longer = longer_string(*moji_list[:2]) 14 return longest_string([longer, *moji_list[2:]]) 15 16#5つの要素からなるリストを生成 17moji_list=["sakurai", "ono", "ninomiya", "aiba", "matsumoto"] 18print(longest_string(moji_list)) 19# check result 20print(max(moji_list, key=len)) # moji_list が空(empty)の場合はエラー

リストの先頭の文字列と、残りのリストに対してlongest_stringを再帰的に呼び出した結果を、

題意通りに書くと longest_string() は以下の様になるでしょう。(上記の部分を読み落としていました)

python

1def longest_string(moji_list): 2 match len(moji_list): 3 case 0: return None 4 case 1: return moji_list[0] 5 case 2: return longer_string(*moji_list) 6 case _: return longer_string(moji_list[0], longest_string(moji_list[1:]))

投稿2024/07/12 05:59

編集2024/07/12 06:45
melian

総合スコア20255

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

回答ついてますが、面白そうなので。
(質問は、ついているコメントにしたがって修正いただくのがよいかと)

再帰的な関数の構成のしかたの基本は以下のとおりです。

  1. 最も簡単な場合の答えかたをみつける
  2. 一般的な場合から、最も簡単な場合に近付く方法を考える。

です。

longest_string もこの2つを元に作ることができます。
1の方はどうでしょう? 質問にあるコードには、この観点が抜けています。
考えてみましょう。リストにある文字列の長さを数えなくてもわかるパターンがあります。「文字列のリストに文字列が1つしかない場合」はどうでしょう? その1つしかない文字列そのものが回答ですね。ということで

  1. は 「リストに文字列が1つしかなければ、それを返す」 にしてみます。(よりよいものは後述)

2の方については、より1の状況に近付くようにするのですが、質問にあるとおり「残りのリストに対してlongest_stringを再帰的に呼び出」すことで、リストが短かくなるので、1に近付きますね。なので
2) は 「残りのリストに対してlongest_stringを再帰的に呼び出す」でOKです。

これで構成してみると、

python

1def longest_string(moji_list): 2 # リストに文字列が1つなら、それを返す 3 if len(moji_list) == 1: 4 return moji_list[0] 5 else: 6 #リストの先頭と残りのリストを定義 7 first=moji_list[0] 8 others=moji_list[1:] 9 #先頭以外の残りのリストの中で一番長いものを判定 10 others_1st=longest_string(others) 11 # 長い方を返す 12 return longer_string(first,others_1st)

こんな感じですね。


別の解

問題には書いてありませんが、空のリストを渡したときの動作はどうすればいいでしょうか。
再帰でリストを扱う場合、終端は空のリストにすることが多いです。ロジックもその方がすっきりすることが多いです。
空のリストの場合、空文字列「""」を返すことにすると以下のようになります。

python

1def longest_string(moji_list): 2 # リストが空なら空文字列を返す 3 if not moji_list: 4 return "" 5 else: 6 #リストの先頭と残りのリストを定義 7 first=moji_list[0] 8 others=moji_list[1:] 9 #先頭以外の残りのリストの中で一番長いものを判定 10 others_1st=longest_string(others) 11 # 長い方を返す 12 return longer_string(first,others_1st)

投稿2024/07/12 07:06

編集2024/07/12 09:34
TakaiY

総合スコア13337

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kuiojl

2024/07/12 09:15

ご丁寧にありがとうございます。おかげさまで、解決することができました。
guest

0

python

1def longest_string(moji_list): 2 first=moji_list[0]

エラーが起きているのは moji_list の要素数が0のときですが、moji_listの要素数が1のときにそれ以上再帰しないよう工夫するのがよいでしょう。

投稿2024/07/12 05:46

編集2024/07/12 05:47
int32_t

総合スコア21421

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kuiojl

2024/07/12 05:57

ご回答ありがとうございます。要素が1個しかない時とそうでない場合で場合分けする、ということでしょうか?最後の自分で作ったリストは5つ要素があるので大丈夫かと思ったのですが、該当リストをdefの後に挿入すればよかったのでしょうか?
int32_t

2024/07/12 06:07

> 要素が1個しかない時とそうでない場合で場合分けする それでいいと思います。 > リストは5つ要素があるので大丈夫 短くしたリストで再帰呼び出ししてますよね。
kuiojl

2024/07/12 06:40

短くしたリストというのはmoji_listのことですか?
int32_t

2024/07/12 06:53

いいえ、others のことです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.40%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問