컴퓨터 & 코딩/Python

[Python] Advent of Code 2022 - Day 5

구로그 2022. 12. 6. 06:29
728x90

Part One

각 숫자 라인에 담겨있는 요소들이 정해진 순서에 따라 정해진 개수가 왔다갔다 해야하는 과제.
최종적으로 가장 윗라인에 있는 알파벳들을 읽어내야 한다. (예: 현재 위의 표에서는, FFQJWWFBW)

file = open("input/day5.txt", "r")
crates_data = file.read().splitlines()

# 1
temp_list = []
crates_list = []

a = 1

for j in range(9):
    for i in range(0, 8):
        if crates_data[i][a] != " ":
            temp_list.append(crates_data[i][a])
    crates_list.append(temp_list)
    a += 4
    temp_list = []

# 2
def move(number, start, end):
    crane = 0
    departure = crates_list[start - 1]
    arrival = crates_list[end - 1]
    for i in range(number):
        crane = departure.pop(0)
        arrival.insert(0, crane)

# 3
move_data = crates_data[10:]
move_list = []

for moving in move_data:
    move_list = [int(s) for s in moving.split() if s.isdigit()]
    move(move_list[0], move_list[1], move_list[2])

# 4
for i in crates_list:
    print(i[0])

# 1 먼저 제시된 input 데이터에서 표 부분만 따온다. 그리고 표를 내가 원하는 모습의 리스트로 바꾸는 과정을 거친다. 숫자 라인 순서대로 1에 담겨져있는 알파벳들은 crates_list[0]에, 2에 담겨져있는 알파벳들은 crates_line[1]에 등등으로 담길 수 있게 한다. 이때 input 원래 데이터 상 숫자가 담겨있는 위치의 인덱스를 따로 구해내어( >> 1, 5, 9, 13 등 1부터 4씩 올라감) 한 줄의 문자열 중 빈 칸(" ")을 제외한 알파벳만 리스트에 담는다.

# 2 input 데이터에 나와있는 '움직임'에 대한 정보는 이렇게 생겼다

move 3 from 5 to 7

다르게 표현하자면,

move <개수> from <시작점> to <종착점>

으로 나타내어져 있다.
이를 활용하여 함수를 만들어냈다.
알파벳이 이동할 때 가장 위에 있는 알파벳 부터 이동을 하는데, 리스트 상으로는 가장 위에 있는 알파벳이 가장 앞에 있다.
(예: 위의 표에서 1같은 경우 crates_list 에서는 [F, L, M, W] 의 모습으로 담겨져 있다)
즉 이동할 때, 가장 앞 부분인 인덱스 0이 이동하는 것이다. 그렇기 때문에 pop(0)을 활용하여 일종의 temp list인 crane에 담아 arrival에 이동시킨다. 원래 append를 써봤는데, 생각해보니 append를 쓰면 시작점 리스트인 departure에 아무런 변화가 없기 때문에 이 과정에 적합하지 않았다.

# 3 이제 move X from Y to Z 데이터를 따로 뽑는다. 이 문장에서 필요한 건 '숫자'이기 때문에 string에서 integer만 뽑는 과정이 필요했다. 이건 스택오버플로우를 참고했다.
https://stackoverflow.com/questions/4289331/how-to-extract-numbers-from-a-string-in-python

How to extract numbers from a string in Python?

I would like to extract all the numbers contained in a string. Which is better suited for the purpose, regular expressions or the isdigit() method? Example: line = "hello 12 hi 89" Resul...

stackoverflow.com

그렇게 숫자만 뽑아 온 다음 만들어놓은 move 함수의 argument로 보내주었다.
여기서 for loop를 돌며 모든 "move X from Y to Z"가 실행되고 # 4에서 part one에서 요구하는 답인 '각 라인별 가장 위에 있는 알파벳'을 읽어낸다.

Part Two

def move(number, start, end):
    crane = []
    departure = crates_list[start - 1]
    arrival = crates_list[end - 1]
    crane = departure[:number]
    del departure[:number]
    for crate in reversed(crane):
        arrival.insert(0, crate)

이번에는 하나씩 옮겨지는 게 아니라 묶음이 통째로 옮겨져야 한다.
다른 건 위와 동일하고 함수 부분만 바꿔주었다.
pop으로 하나씩 빼는 게 아니라 일단 해당 부분을 잘라서 crane에 넣어주고 departure 에서는 지워준다. 그리고 crane에 담아놓았던 걸 arrival에 그대로 담아준다. 이때 reverse()를 활용하여 의도하는 순서대로 담길 수 있데 한다.

반응형