1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

IndexError: list index out of rangeを解決できないの巻

Last updated at Posted at 2024-12-13

最近、AtCoderの簡単な問題を解いて遊んでいるが、2問目で早速詰まってしまった。

第一回 アルゴリズム実技検定 過去問 B - 増減管理

A1,A2,A3...ANと整数が渡されるので、その増減を示せ、という問題。

N = int(input())
A = list(map(int, input().split()))


for i in range(1,len(A)+1) :
    if A[i] == A[i-1]:
        print('stay')
    elif A[i] > A[i-1]:
        n = A[i] - A[i-1]
        print('up %d' %n)
    elif A[i] < A[i-1]:
        n = A[i-1] - A[i]
        print('down %d' %n)

こう書くと...

up 1
down 7
up 97
stay
down 10
down 10
down 70
up 20
down 20
Traceback (most recent call last):
  File "c:\Users\konai\.vscode\extensions\ms-python.python-2024.22.0-win32-x64\python_files\python_server.py", line 133, in exec_user_input
    retval = callable_(user_input, user_globals)
  File "<string>", line 2, in <module>
IndexError: list index out of range

こうなる。
出したい出力はでてるのに、エラーが出る。

A[i] == A[i-1]

多分ここの書き方がよくない。一回目のループではまだA[i-1]は存在していないから、リストの範囲の外ですよ~みたいなことを言われるのかなと思ったが...


1~Nまでの数字の中で条幅しているものを見つけろ。なければcorrectと表示しろという問題。

N = int(input())
A = list(map(int, input().split()))

ListP = list(range(1,N+1))

ListA = sorted(A)

for i in range(1,N):
    if ListA[i] == ListP[i]:
        Num = "correct"        
    elif ListA[i] != ListP[i]:
        print(ListA[i] ,ListP[i])

if Num == "correct":
    print("correct")
else:
    pass

VScode上では正しく走ったが、AtCoderのエディタには

IndexError: list index out of range

の文字が...


geminiくんにきいてみた

はい、エラーが出る可能性があります。具体的には、IndexError: list index out of range が発生する可能性があります。
問題箇所は for i in range(1, N): ループ内での ListA[i] と ListP[i]へのアクセスです。
ListP = list(range(1, N+1)) なので、 ListP の長さは N です。ループの範囲は 1 から N-1 までなので、ListP[i]へのアクセスは問題ありません。
しかし、ListA は A をソートしたリストです。A の長さは N ですが、ListA の要素が 1 から N までの連続した整数であるとは限りません。A に重複した値が含まれている場合、ListA の長さは N より短くなります。
例えば、N = 3 で A = [1, 2, 2] の場合、ListA = [1, 2, 2] となり、長さは 3 です。しかし、A = [1, 1, 1] の場合、ListA = [1, 1, 1] となり、sorted(A) によって重複が削除されず、長さは3のままです。
もし、A の要素に重複がなく、かつ 1 から N までのすべての整数が含まれている場合は、ListA の長さは N となり、エラーは発生しません。しかし、そうでない場合は、i が len(ListA) 以上になると IndexError: list index out of range が発生します。
解決策としては、ループの範囲を len(ListA) -1 までにするか、あるいは try-except ブロックを使用して例外を処理する方法が考えられます。

ループ範囲の修正

for i in range(min(len(ListA)-1,len(ListP)-1)):  # 両方のリストの長さを考慮
    if ListA[i] == ListP[i]:
        # ...

try-exceptブロックの使用

for i in range(N-1):
    try:
        if ListA[i] == ListP[i]:
            # ...
    except IndexError:
        print("Error: List index out of range")  # エラー処理を追加
        break # ループを中断

どちらの方法を選ぶかは、プログラムの仕様やエラー処理の方法によって異なります。 try-except を使う場合は、単にエラーメッセージを表示するだけでなく、適切なエラー処理を行う必要があります。 例えば、エラーが発生した場合にプログラムを終了する、デフォルト値を使用する、などです。
また、そもそも ListA を作成する際に set() を使って重複を除去してしまうという方法もあります。ただし、この場合は元の A の要素の順番が失われることに注意してください。
ListA = sorted(list(set(A))) # 重複を除去
この後、ListAとListPの長さが異なる可能性が高いので、ループ範囲をmin(len(ListA), len(ListP))にするなどの対応が必要です。


だそう。(?)

ListAに重複があり、ListPとの長さが変わった時にエラーが出るらしい。が、

例えば、N = 3 で A = [1, 2, 2] の場合、ListA = [1, 2, 2] となり、長さは 3 です。しかし、A = [1, 1, 1] の場合、ListA = [1, 1, 1] となり、sorted(A) によって重複が削除されず、長さは3のままです。

というように重複があっても長さは変わらないのではないか?
???

rangeを使ったfor文を書くと出るので、僕の書き方が悪いのだろう。
しかし、ググれど解決策が見つからないor理解できていないので、ここに記録して未来の僕に任せます...

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?