코딩테스트 연습 - 행렬의 덧셈 | 프로그래머스 스쿨 (programmers.co.kr)
프로그래머스
코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.
programmers.co.kr
문제
행렬의 덧셈은 행과 열의 크기가 같은 두 행렬의 같은 행, 같은 열의 값을 서로 더한 결과가 됩니다. 2개의 행렬 arr1과 arr2를 입력받아, 행렬 덧셈의 결과를 반환하는 함수, solution을 완성해주세요.
제한 조건
행렬 arr1, arr2의 행과 열의 길이는 500을 넘지 않습니다.
입출력 예
arr1 | arr2 | return |
[[1,2],[2,3]] | [[3,4],[5,6]] | [[4,6],[7,9]] |
[[1],[2]] | [[3],[4]] | [[4],[6]] |
풀이
아이디어: 리스트 안의 리스트 요소를 인덱싱을 이용하여 접근해서 각각을 더해준다. (for문 안에 for문 사용)
def solution(arr1, arr2):
answer_1=[]
for i in range(len(arr1)):
answer=[]
for j in range(len(arr1[i])):
answer.append(arr1[i][j]+arr2[i][j])
answer_1.append(answer)
return answer_1
첫번째 for문으로 arr1 리스트의 요소(리스트)에 접근한다.
이후 두번째 for 문으로 내부 리스트 요소에 접근하여 각각을 더해준다. 이때 answer 변수에는 내부 리스트 요소끼리 합한 값을 넣어준다.
이 answer 리스를 두번째 for문이 끝난 이후에 (첫번째 for문 도는중) answer_1 이라는 다른 리스트에 요소로 넣어주어서 반환한다.
다른 풀이 모음
다른 풀이 1
def sumMatrix(A,B):
answer = [[c + d for c, d in zip(a,b)] for a, b in zip(A,B)]
return answer
zip()을 사용한 똑똑한 풀이이다.
for a, b in zip(A,B):
print(a,b)
for c, d in zip(a,b):
print(c,d)
print(c+d)
# 출력 결과
# [1, 2] [3, 4] print(a,b)
# 1 3 print(c,d)
# 4 print(c+d)
# 2 4 print(c,d)
# 6 print(c+d)
# [2, 3] [5, 6] print(a,b)
# 2 5 print(c,d)
# 7 print(c+d)
# 3 6 print(c,d)
# 9 print(c+d)
위의 코드의 내부 과정을 보기 위해서 풀어서 실행해보면 이렇게 된다.
다른 풀이 2
def sumMatrix(A,B):
return [list(map(sum, zip(*x))) for x in zip(A, B)]
이것도 zip 을 이용했는데, 이번엔 언패킹을 사용한 풀이이다.
이때 zip을 이용한 for 루프에서 변수를 어떻게 할당하느냐에 따라 출력이 달라진다.
- zip 함수는 각 iterable에서 동일한 인덱스에 있는 요소들을 묶어 튜플로 반환한다.
- for 루프에서 여러 변수를 사용할 경우, 각 튜플의 요소를 해당 변수에 할당한다.
- for 루프에서 단일 변수를 사용할 경우, 튜플 전체가 그 변수에 할당된다.
따라서, 첫번째 코드에서 for a,b in zip(A,B) 는 a,b에 [1, 2](a) [3, 4](b) 와 [2, 3](a) [5, 6](b) 가 할당된다.
반면, 두번째 for x in zip(A,B)는 x에 ([1, 2], [3, 4]) 와 ([2, 3], [5, 6]) 같이 튜플이 할당되게 된다.
-> 즉 변수가 1개면 튜플이 그대로, 변수가 여러개면 튜플의 요소가 각 변수에 할당된다.
언패킹
1. 튜플과 리스트의 언패킹
# 튜플 언패킹
my_tuple = (1, 2, 3)
a, b, c = my_tuple
print(a) # 1
print(b) # 2
print(c) # 3
# 리스트 언패킹
my_list = [4, 5, 6]
a, b, c = my_list
print(a) # 4
print(b) # 5
print(c) # 6
-> 각각의 요소를 개별 변수에 할당 가능.
# '*' 연산자를 이용한 언패킹
#튜플
my_tuple = (1, 2, 3, 4)
a, *b, c = my_tuple
print(a) # 1
print(b) # [2, 3]
print(c) # 4
# 리스트
my_list = [1, 2, 3, 4, 5]
a, b, *c = my_list
print(a) # 1
print(b) # 2
print(c) # [3, 4, 5]
-> 변수의 개수가 튜플,리스트의 요소보다 적을 때 특정변수 앞에 * 를 붙여주면,
요소를 다른 변수 순서에 맞게 할당 하고 남는 개수만큼을 리스트로 만들어준다.
( * 는 1개의 변수만 가질 수 있다.)
2. zip() 에서의 언패킹
# 두 리스트 생성
arr1 = [1, 2, 3]
arr2 = ['a', 'b', 'c']
# zip 함수를 사용하여 두 리스트를 병렬로 묶음
zipped = list(zip(arr1, arr2))
print(zipped) # [(1, 'a'), (2, 'b'), (3, 'c')]
# * 연산자를 사용하여 zip 결과를 언패킹
unzipped1, unzipped2 = zip(*zipped)
print(unzipped1) # (1, 2, 3)
print(unzipped2) # ('a', 'b', 'c')
여기서 zip(*zipped)는 zipped 리스트의 각 튜플을 분해하여 원래의 두 리스트로 되돌린다.
-> zip에서 * 언패킹 = 병렬로 묶인 요소들을 다시 분해하여 원래의 형태로 되돌림.
A= [[1, 2], [3, 4], [5, 6]]
list(zip(*A)) #출력 : [(1, 3, 5), (2, 4, 6)]
이렇게 굳이 zip으로 묶인게 아니더라도, 병렬로 묶인 요소들을 분해해서 튜플로 돌려준다.
다시 '다른 풀이2 '로 돌아와서 코드를 살펴보자.
def sumMatrix(A,B):
return [list(map(sum, zip(*x))) for x in zip(A, B)]
이것도 내부 과정을 하나하나 실행시켜보자.
for x in zip(A,B):
print(x)
# 출력
#([1, 2], [3, 4])
#([2, 3], [5, 6])
zip(*x)
print(list(zip(*x))) #결과를 눈으로 보기 위해서 list를 씌워줌
# 출력
#[(1, 3), (2, 4)]
#[(2, 5), (3, 6)]
list(zip(*x))[0] #print()는 생략하겠다.
# 값
# (1,3)
# (2,5)
list(zip(*x))[1] #print()는 생략.
# 값
# (2,4)
# (3,6)
sum(list(zip(*x))[0]) #print()는 생략.
# 값
# 4
# 7
sum(list(zip(*x))[1]) #print()는 생략.
# 값
# 6
# 9
# 이 sum 연산을 각 zip(*x) 요소에 대해 수행해 주기 위해서 map 함수를 이용
map(sum, zip(*x)) #zip(*x)의 각각의 요소에 대해 sum 을 수행하게 된다.
print(list(map(sum, zip(*x))))
# 출력
#[4, 6]
#[7, 9]
다른 풀이 3
import numpy as np
def sumMatrix(A,B):
A_np = np.array(A)
B_np = np.array(B)
result = A_np + B_np
return result.tolist()
이건 numpy 모듈을 이용한 풀이.
numpy는 수치 계산 라이브러리인데, 다차원 배열 연산을 수월하게 수행해준다.
문제가 행렬의 덧셈이기 때문에 numpy의 array로 덧셈을 해주는 것과 똑같다.
행렬 문제라서 보자마자 numpy가 생각이 났지만 주어진 값이 array형태가 아닌 리스트라서 넘파이로 푸는건 포기했었다.
근데 저렇게 간단히 그냥 np.array()로 지정해주면 되는 거였구나..
zip 함수와 언패킹에 대한 개념이 명확히 잡혀있지 않아서 글이 길어졌다.
그래도 이제 zip과 언패킹에 대해서 좀 알 것 같다. ╰(*°▽°*)╯
'문제풀이 > 프로그래머스' 카테고리의 다른 글
[프로그래머스 Lv.1] 이상한 문자 만들기 (Python) +split()함수 (1) | 2024.07.16 |
---|---|
[프로그래머스 Lv.1] 명예의 전당(1) (Python) (0) | 2024.07.12 |
[프로그래머스 Lv.1] 문자열 다루기 기본 (Python) (0) | 2024.07.10 |
[프로그래머스 Lv.1] 부족한 금액 계산하기 (Python) (0) | 2024.07.10 |
[프로그래머스 Lv.1] 약수의 개수와 덧셈 (Python) (0) | 2024.07.10 |