競技プログラミングで螺旋状(スパイラル状)にデータを読み取るという問題が時々出てきます。その問題の解き方です。
考え方
螺旋状に読み取るべきデータは2次元リストに入っているものとします。具体的には
testdate=
[1, 2, 3],
[8, 9, 4],
[7, 6, 5,]
のような感じです。 これを1→2→3...のように読み取ることを目指します。
案1.ループを使う
result=[]
top_row,bottom_row,left_col,right_col=0,len(testdate),0,len(testdate[0])
while top_row<bottom_row and left_col<right_col:
#上辺(右から左)
for col in range(left_col,right_col):
result.append(testdate[top_row][col])
top_row+=1
#右辺(上から下)
for row in range(top_row,bottom_row):
result.append(testdate[row][right_col-1])
right_col-=1
if not (top_row<bottom_row and left_col<right_col):
break
#下辺(左から右)
for col in range(right_col-1,left_col-1,-1):
result.append(testdate[bottom_row-1][col])
bottom_row-=1
#左辺(下から上)
for row in range(bottom_row-1,top_row-1,-1):
result.append(testdate[row][left_col])
left_col+=1
処理の順は、上端→右端→下端→左端→...です。***_col
を1ずつ変えることで範囲を狭めています。
案2.回しながら消す
これは自分では思いつけませんでした。ChatGPTが教えてくれて、いいなって思ったので紹介します。
result=[]
while testdate:
result+=testdate.pop(0) #上辺を取得して削除
if testdate:#残りがある場合
testdate=list(zip(*grid))[::-1] # 残りを回転(列を行として扱う)
これすごいですよね。さっきのコードを見てからはびっくりするぐらい簡潔です。一番上にある行を削除&取得して、回すという方法です。回すと右端が一番上の行になるし、削除するので範囲の制限もいらないという出来すぎているコードだと思います(もしかしてこれぐらいが社会では普通だったりします?実務をしたことがないのでわかりません)。