<로직 고민>
- 행렬의 곱셈 방법...까먹었따...수학공부부터 다시 하고 온다
- 일단 numpy 라이브러리를 이용하면 금방 풀 수 있대서 numpy의 함수를 이용해서 풀어봤다
import numpy as np
def solution(arr1, arr2):
answer = [[]]
matrix1 = np.array(arr1)
matrix2 = np.array(arr2)
answer = np.dot(matrix1, matrix2)
return answer.tolist()
print(solution([[1, 4], [3, 2], [4, 1]], [[3, 3], [3, 3]])) # [[15, 15], [15, 15], [15, 15]]
print(solution([[2, 3, 2], [4, 2, 4], [3, 1, 4]],
[[5, 4, 3], [2, 4, 1], [3, 1, 1]])) # [[22, 22, 11], [36, 28, 18], [29, 20, 14]]
- np.array()는 리스트를 행렬화하는 거고 np.dot은 행렬끼리 곱해주는 메서드다
- 그냥 return을 하면 행렬화되어 있어서 뭐 못 읽는댔나 not json serializable 뭐 이런 거 나오는데 행렬화한 걸 tolist() 메서드로 다시 리스트화 해줘야 답이 제대로 나온다
- 이렇게 풀고 나니 뭔가....푼 것 같지 않고 개운하지가 않아서 다시 행렬 곱셈을 공부했다
- 그리고 numpy는 pip install numpy 해서 설치해야 하니까...(근데 위 풀이로 채점했더니 12점 나왔다 ㅋㅋㅋ)
- 여튼!!!
- 다시 풀어보면 일단 행렬은 첫 번째 행렬의 열과 두 번째 행렬의 행의 길이가 2인 경우, 첫 번째 행렬의 1행 1열과 두 번째 행렬의 1행 1열을 곱하고 그 다음엔 첫 번째 행렬의 1행 2열과 두 번째 행렬의 2행 1열을 곱해서 더한다
- 말로 쓰니까 참 그렇네 사진 보면 바로 이해 되는데
- 보면 일단 답이 될 행렬의 크기는 행렬1의 행 개수 x 행렬2의 열 개수
- 행렬1의 행 개수는 len(arr1), 행렬2의 열 개수는 len(arr2[0])
- arr2의 각 행의 길이는 똑같겠지만 행렬의 크기가 입력값에 따라 변하므로 행렬의 크기와 상관없이 0번째 행은 항상 존재할 것이니까 0번째 행의 길이를 답 행렬의 열 크기로 함
- 답 행렬의 행 길이만큼의 for문이 가장 바깥에 돌아야 하고 답 행렬의 크기가 2(l) x 2(n) 일 때,
- 답 행렬의 첫 번째 n행 = {(행렬1의 m1행 l1열 * 행렬2의 n1행 m1열) + (행렬1의 m1행 l1열 * 행렬2의 n2행 m1열)} + {(행렬1의 m1행 l2열 * 행렬2의 n1행 m2열) + (행렬1의 m1행 l2열 * 행렬2의 n2행 m2열}
- 후 그러니까 행렬의 곱셈이 말이지...
- 행렬1의 1행 요소들을 각자 곱한 값과 행렬2의 1열 요소들을 각자 곱한 값의 합
- 더이상의 설명은 naver............
- 완성한 코드에 열심히 주석을 달고 변수명도 고심 끝에 정했는데 미래의 내가 이걸 다시 봐도 무슨 말인지 알아먹을 수 있겠지.....?
<완성된 코드>
def solution(arr1, arr2):
answer = []
# 답 행렬의 크기는 arr1의 행 개수(길이) x arr2의 열 개수(arr2[0] 길이)
answer_row = len(arr1) # 답 행렬의 행이 되는 개수
answer_col = len(arr2[0]) # 답 행렬의 열이 되는 개수
arr1_col_arr2_row = len(arr1[0]) # 답 행렬 요소에 더해지는 곱 개수
# 행렬1의 행 개수만큼 돌리기
for l in range(answer_row):
# 답 행렬의 각 행 리스트 초기화
sum_answer_row = [0 for _ in range(answer_col)]
# 행렬2의 열 개수만큼 돌리기
for n in range(answer_col):
# 답 행렬 각 요소에 더해지는 곱의 개수만큼 돌리기
for m in range(arr1_col_arr2_row):
# 답 행렬 한 행의 n번째 열 += 행렬1 l행 m열 * 행렬2 m행 n열
sum_answer_row[n] += (arr1[l][m] * arr2[m][n])
# 한 행의 각 열이 다 채워지면 답 행렬에 붙이기
answer.append(sum_answer_row)
return answer
print(solution([[1, 4], [3, 2], [4, 1]], [[3, 3], [3, 3]])) # [[15, 15], [15, 15], [15, 15]]
print(solution([[2, 3, 2], [4, 2, 4], [3, 1, 4]],
[[5, 4, 3], [2, 4, 1], [3, 1, 1]])) # [[22, 22, 11], [36, 28, 18], [29, 20, 14]]
<다른 사람 풀이>
- 천재풀이1
def solution(A, B):
return [[sum(a*b for a, b in zip(A_row, B_col)) for B_col in zip(*B)] for A_row in A]
- 아니..대체 이게 무슨.....?
- 풀어서 써보려고 했는데 안 되넹...
- zip 함수에 대해 알아봐야겠꾼
- [Python 문법] 길이가 같은 리스트의 요소를 묶어주는 zip() 함수 — 구민정의 개발일지 (tistory.com)
- 정리해뒀었네...근데 이땐 딕셔너리 만드는 함수인 줄 알았다 for문으로 활용하는 거 내용 방금 추가함 ㅋㅋ
- 파이썬 별표(*), Asterisk의 역할 (velog.io)
- 그리고 또 찾아보니 변수 앞에 *이 붙으면 언패킹 해서 요소 하나하나 분리하는 거라고 한다
- 2번 입출력 예시로 따지면 zip(*B) 해서 B_col에 각각 (5,4,3) (2,4,1) (3,1,1) 가 담긴다
- 근데 쓰는 거랑 안 쓰는 거랑 무슨 차이인지 모르겠다...일단 그냥 B로 하면 1번 입출력만 통과하고 나머지는 다 안 된다
- 뭐지...
- [파이썬] zip 내장함수 - 묶어서 데이터 가져오기 (tistory.com)
- 이걸 보면 전치행렬을 생성한 건데 음.............리스트 형태니까 행렬로 바꾼건가...........하 모르겠다
- 그나저나 zip()이랑 set()은 다른 사람 풀이에서 맨날 봐도 맨날 활용 못 하는 듯.........머리에 잘 안 들어옴