LoginSignup

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

Pythonでの文字列のランダム並び替えについて

解決したいこと

Pythonで文字列を並び替えるプログラムを作成していますが、解読できないエラーが発生しました

発生している問題・エラー

3C8FBB82-50A7-42A3-A1F1-F525A526E25B.jpeg
半分までは動作しますが、それ以降はこのエラーが発生して動作を停止します
(入力が8文字なら4文字、5文字なら3文字まで)

該当するソースコード

8893BBD2-40CE-480B-AE6C-2FADFA6066F2.png
乱数を生成して、それをnに格納する
n番目の文字を表示して消去する
の繰り返しのつもりです

自分で試したこと

これから検証を重ねます

0

2Answer

コメントを付けてみましたので,原因を考えてみましょう.

import random
a = input('文字列:') # 文字列aを取得
char = [] # 空リストcharを生成
for i in a: # 文字列aから文字iを1つずつ取り出し
    char.append(i) # 文字iをリストcharに追加
else: # 上のfor文においてbreakで抜け出さなかった場合,
    for j in range(len(char)): # リストcharの長さだけループ
        n = random.randint(0, len(char) - j - 1) # 0からlen(char)-j-1までの値の整数乱数nを生成
        b = char[n] # 整数乱数を使ってn番目を取り出し
        char.pop(n) # リストcharのn番目を削除

エラー文ValueError: empty range for randrange() (0, 0, 0)の意味は,乱数の範囲randrange()が空emptyであったことに起因するものです.0から0までの範囲は0でemptyなわけです.

ここで,random.randint()の第二引数len(char) - j - 1のうち- jは不要です.無くせばエラーは生じなくなります.

逆に- jが必要なケースを書いておきますので,違いを考えてみてください.

import random
a = input('文字列:') # 文字列aを取得
char = [] # 空リストcharを生成
for i in a: # 文字列aから文字iを1つずつ取り出し
    char.append(i) # 文字iをリストcharに追加
else: # 上のfor文においてbreakで抜け出さなかった場合,
    clength = len(char) # リストcharの長さを取得
    for j in range(clength): # リストcharの長さだけループ
        n = random.randint(0, clength - j - 1) # 0からclength-j-1までの値の整数乱数nを生成
        b = char[n] # 整数乱数を使ってn番目を取り出し
        char.pop(n) # リストcharのn番目を削除 # Hint: ここでリストcharの長さが1つ減ります.

charの長さをchar.pop()で徐々に減らしていくくループの中でlen(char)も同時に減っていくのに対し,リストから減った量を表現している- jごと扱っているため,random.randint()の第二引数len(char) - j - 1では2倍の勢いで範囲を減らしていることになります.

したがって,半分まで処理したところで範囲が0になり,empty rangeと言われるわけです.

直上のコードで事前にclengthとして長さを固定した場合は減った分を示す- jが必要になりますし,最初のコードでは減った量は既にlen(char)に反映されているので- jを書かないだけで正常に動くようになるということですね.

ちなみにアナグラムを生成するなら次のコードで十分です.

import random
a = input('文字列:')
print(''.join(random.sample(a, len(a))))

余談

タグがPython2.7とついていますが,コードはPython3のものです.Python2.7であればinput()ではなくraw_input()ですからね.

また,コードはスクリーンショットではなく,コードブロック

(空行1行あける)
```python:
コード本文
```

に記述してください.質問のテンプレートにもあるはずです.

2

Comments

  1. @Nature_Nature

    Questioner
    なるほど、丁寧にわかりやすく教えてくださりありがとうございます。
    生成するコードはあったんですね。知識不足でした。
    実行コンソール1行目にPython2.7(trunk,時刻)の表記があったので2.7かと勘違いしていました。3の環境だったのですね、すみません
    また、質問の形式についてもすみませんでした。自分でも探してみたのですが見当たらなかったので質問テンプレートがどこにあるか教えて頂いていいですか?
  2. 上述の通り,input()が正常に使われているのであれば3系のはずです.もし2.7系でinput()を使うと上のコードのままではエラーになります.
    一応,エラーが起きる確認のため,2系環境の実行例を次のリンクに貼っておきます.
    https://paiza.io/projects/u-EUip8EeDUDDj9RJaMebw

    「質問テンプレートがどこにあるか」についてですが,質問作成時にあらかじめ入力されていた文章がいくつかあったはずです(なければ無いです).その文章の中に,コードブロック例も含まれています.
  3. @Nature_Nature

    Questioner
    返信ありがとうございます。
    リンク見させて頂きました、ああいうエラーの出方もしていた気がするので確認進めてみます。
    あれがテンプレートなのですね、分かりました。どこかに作成例のようなページがあるのかとの勘違いでした。次回からはそうします

randint の引数に -1 を指定してしまったのですね。
ちなみに、random.shuffle() という便利な関数があります。

>>> import random
>>> random.randint(0, -1)
/usr/lib/python3/dist-packages/requests/__init__.py:89: RequestsDependencyWarning: urllib3 (1.26.12) or chardet (3.0.4) doesn't match a supported version!
  warnings.warn("urllib3 ({}) or chardet ({}) doesn't match a supported "
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.8/random.py", line 248, in randint
    return self.randrange(a, b+1)
  File "/usr/lib/python3.8/random.py", line 226, in randrange
    raise ValueError("empty range for randrange() (%d, %d, %d)" % (istart, istop, width))
ValueError: empty range for randrange() (0, 0, 0)
1

Comments

  1. @Nature_Nature

    Questioner
    範囲が負になった感じですかね、ありがとうございます
    便利な関数はあるものですね…

Your answer might help someone💌