땃쥐네

[Python] 이차원 리스트 초기화는 리스트 컴프리헨션으로 본문

Programming Languages/Python

[Python] 이차원 리스트 초기화는 리스트 컴프리헨션으로

ttasjwi 2023. 1. 29. 21:55

문제 상황

백준의 2775번 문제를 풀고 있었다.

 

이 문제의 상황은 a층 b호에 사는 사람은 a-1층 1호부터 b호까지 사는 사람의 합만큼 사람이 살아야하는 규칙에서

n층 k호에 사는 사람의 수를 순서대로 출력하는 문제였다. (단, 0층 b호에는 b명이 산다.)

 

문제를 해결하기 위해서는 나는 바텀업 방식의 DP 알고리즘을 사용하기로 했다. 

numbers = [[0] * 15] * 15
for r in range(15):
    for c in range(15):
        if r == 0 or c == 0:
            numbers[r][c] = c
        else:
            numbers[r][c] = numbers[r][c-1] + numbers[r-1][c]
        print(f'{r}층 {c}호에는 {numbers[r][c]}명이 살아요.\n')

우선 15*15 배열을 초기화한다. 문제의 입력값 범위가 14층 14호까지이므로 이정도만 초기화해주면 된다.

그리고 2중 for문을 돌면서 r층 c호에 사는 사람의 수를 순서대로 초기화한다.

 

이 문제의 상황에서 0호는 없지만 계산의 편의를 위해 각 층의 0호에는 아무도 안 살게 초기화를 하고, 0층 c호에는 c명만 살게 한다.

 

1층부터는, 왼쪽 집 사람의 수에, 아랫층 사람의 수를 더하는 식으로 순서대로 처리하면 조건에 맞게 사람 수를 채울 수 있을 것이다.

 

실제로 로그를 찍어보면 내가 의도한 대로, 사람수가 잘 찍혀나오는 것처럼 보인다.

answers = []
while t > 0:
    k = int(input())
    n = int(input())
    answers.append(str(numbers[k][n]))
    t -= 1
answers = '\n'.join(answers)
print(answers)

이제 입력을 받아서 k층 n에 사는 사람을 순서대로 질의해서 화면에 출력하면 되는데

아니 무슨 상황인가. 1층 3호와 2층 3호에 사는 사람을 질의했는데 둘다 무려 136명이나 찍히는게 아닌가?

이 상황이 너무 어처구니 없어서, 최종 상황에서 리스트 상태를 로그로 출력해봤다.

[[0, 1, 16, 136, 816, 3876, 15504, 54264, 170544, 490314, 1307504, 3268760, 7726160, 17383860, 37442160], 
[0, 1, 16, 136, 816, 3876, 15504, 54264, 170544, 490314, 1307504, 3268760, 7726160, 17383860, 37442160], 

...

[0, 1, 16, 136, 816, 3876, 15504, 54264, 170544, 490314, 1307504, 3268760, 7726160, 17383860, 37442160]]

모든 층에 사는 사람들이... 전부 14층 기준으로 맞춰져 있었다.

로그를 더 찍어보니, 문제가 구체적으로 보이기 시작한다.

r행 c열만 갱신되는게 아니라 다른 열의 c열 요소도 함께 갱신되고 있다.

 

numbers = [[0] * 15] * 15

뭐가 문제였을까 생각해보니 결국 문제는 배열을 초기화하는 선언문에 있었다.

 

[0] * 15까지는 문제가 없는데 이렇게 초기화된 1차원 리스트를 15개 복사한 이차원 리스트를 선언할 때 해당 배열의 참조까지 통채로 복사되기 때문이였다.


해결책

numbers = [[0 for _ in range(15)] for _ in range(15)]

위에서 선언한 방식의 초기화문을 리스트 컴프리헨션을 통한 선언문으로 변경하자.

이제 의도한 대로 동작하게 된다.

 


결론

  • 이차원 리스트를 초기화 할 때 귀찮더라도 리스트 컴프리헨션을 통해 초기화하자.
  • [[...] *n]*m 방식으로 초기화하면 리스트의 참조가 복사되어 의도치 않은 동작을 하게 된다.

 

'Programming Languages > Python' 카테고리의 다른 글

[Python] 파이썬 시작하기  (0) 2023.01.29
Comments