문제출처
programmers.co.kr/learn/courses/30/lessons/12949
문제설명
2차원 행렬 arr1과 arr2를 입력받아, arr1에 arr2를 곱한 결과를 반환하는 함수, solution을 완성해주세요.
제한 조건
- 행렬 arr1, arr2의 행과 열의 길이는 2 이상 100 이하입니다.
- 행렬 arr1, arr2의 원소는 -10 이상 20 이하인 자연수입니다.
- 곱할 수 있는 배열만 주어집니다.
입출력 예
arr1 | arr2 | return |
[[1, 4], [3, 2], [4, 1]] | [[3, 3], [3, 3]] | [[15, 15], [15, 15], [15, 15]] |
[[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]] |
문제풀이
ㅋㅋㅋ 드디어 for문 3개를 중첩해보는 경험을 했다!
for문 3개를 중첩해본 적이 없어서 코드를 짤때는 죄짓는(??) 기분이 들었으나
다 풀고 다른 사람풀이를 보니 많이들 이렇게 한 것 같아 안심했다ㅋㅋ...
먼저 행렬의 곱셈 계산식부터 알아야 한다. 이것을 모르면 이 문제는 절대 풀 수 없다.
첫번째 입출력 예를 가지고 간단하게 살펴보도록 하자.
행렬의 곱셈은 좌측 행렬의 행과 우측 행렬의 열을 곱해주면 된다.
먼저 arr1의 첫번째 행과 arr2의 첫번째 열을 곱해주면 된다.
arr1의 첫번째 행 | arr2의 두번째 열 |
[1, 4] | [3] [3] |
arr1 arr2 | return |
[1, 4] [3, 3] [3, 2] [3, 3] [4, 1] |
[15, 15] [15, 15] [15, 15] |
-> 1 * 4 + 3 * 3 = 15
arr1 arr2 | return |
[1, 4] [3, 3] [3, 2] [3, 3] [4, 1] |
[15, 15] [15, 15] [15, 15] |
-> 1 * 4 + 3 * 3 = 15
arr1 arr2 | return |
[1, 4] [3, 3] [3, 2] [3, 3] [4, 1] |
[15, 15] [15, 15] [15, 15] |
-> 3 * 3 + 2 * 3 = 15
이런식으로 행렬을 행과 열끼리 곱하게 하는 것이 행렬의 곱셈이다.
이제 이것을 코드로 구현해야 하는데 처음엔 어떻게 해야할 지 아무런 생각이 떠오르지 않아 막막했다.
그래서 계산에 사용되는 배열 index를 일일이 써보고 숫자들이 어떻게 변화하는지 살펴보았다.
arr1[0][0] * arr2[0][0] + arr1[0][1] * arr2[1][0]
arr1[0][0] * arr2[0][1] + arr1[0][1] * arr2[1][1]
---------------------------------------------
arr1[1][0] * arr2[0][0] + arr1[1][1] * arr2[1][0]
arr1[1][0] * arr2[0][1] + arr1[1][1] * arr2[1][1]
---------------------------------------------
arr1[2][0] * arr2[0][0] + arr1[2][1] * arr2[1][0]
arr1[2][0] * arr2[0][1] + arr1[2][1] * arr2[1][1]
수고스럽긴 하지만 이렇게 써놓고 보니 반복되는 부분과 변화하는 부분이 한눈에 보인다.
arr1은 각 행의 0번 인덱스와 1번 인덱스가 번갈아 가며 나타난다.
그리고 그와 함께 arr2는 [00] [10] [01] [11] 순서로 index가 반복된다.
반복문을 통해 위의 인덱스에 해당하는 숫자들을 표현할 수만 있다면 이 문제는 끝이다!
0과 1의 인덱스가 반복되도록 하는 것은 단순하게 for문을 사용하면 되니 따로 설명하지 않겠다.
[00] [10] [01] [11]는 이중 for문을 사용하고 출력 순서를 바꾸면 된다.
아래 코드를 참고하자
j와 i의 순서를 바꾸면 원하는 순서대로 숫자를 출력할 수 있다.
따라서 이 문제는 arr1을 한 행씩 출력하게 하는 반복문 안에 위의 2중 for문을 넣어서 arr2의 index를 출력하게 하면 된다.
1) var result: [[Int]] = []
-> 결과값을 저장할 이중배열을 변수로 생성한다.
2) var temp = 0
-> 반복문을 통해 계산되는 값을 임시로 저장해줄 변수를 생성한다.
3) for index in 0..<arr1.count {
-> arr1의 각 행이 순차적으로 반복되도록 반복문을 만들어준다.
4) result.append([])
-> 각 행이 시작될 때 result에 빈 배열을 초기화 해준다.
5) for i in 0..<arr2[0].count {
for j in 0..<arr2.count {
-> 이중 for문을 만들어 준다. i는 arr2의 열, j는 arr2의 행을 의미한다는 것을 잊지 말아야 한다.
따라서, i는 arr2의 각 행이 가진 값의 개수(arr2[0].count) 만큼 반복되도록 해주고, j는 행의 개수(arr2.count)만큼 반복되도록 해주어야 한다. i와 j를 뒤집어 사용하기 때문에 이 부분이 헷갈릴 수 있는데 이 부분을 정확하게 적어주지 않으면 채점 결과 0점이 나오게 된다...(ㅠㅠ)
6) temp += arr1[index][j] * arr2[j][i]
-> 행렬 곱셈식을 적어준다. 가장 안쪽에 있는 반복문이 전부 돌아야 하나의 식이 완성되므로 temp에 계속 +해주며 계산을 해주면 된다. 이 반복문이 한 바퀴 돌아 식이 완성되면 해당 값을 result에 append해주고 temp는 0으로 초기화 해준다.
'코딩테스트' 카테고리의 다른 글
프로그래머스 - 다음 큰 숫자 (레벨2, swift) (0) | 2020.07.12 |
---|---|
프로그래머스 - 가장 큰 정사각형 찾기 (레벨2, swift) (0) | 2020.07.11 |
프로그래머스 - 최댓값과 최솟값 (레벨2, swift) (0) | 2020.07.07 |
프로그래머스 - 스킬트리 (레벨2, swift) (0) | 2020.07.06 |
프로그래머스 - 피보나치 수 (레벨2, swift) (0) | 2020.07.05 |