프로그래머스 | LV2 | 행렬의 곱셈

yes·2022년 10월 6일
0

프로그래머스

목록 보기
6/7
post-thumbnail

문제 설명

2차원 행렬 arr1과 arr2를 입력받아, arr1에 arr2를 곱한 결과를 반환하는 함수, solution을 완성해주세요.

제한 조건

  • 행렬 arr1, arr2의 행과 열의 길이는 2 이상 100 이하입니다.
  • 행렬 arr1, arr2의 원소는 -10 이상 20 이하인 자연수입니다.
  • 곱할 수 있는 배열만 주어집니다.

입출력 예

arr1arr2return
[[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]]

행렬을 모르는 문과생은 슬픕니다 ㅠ

행렬


행렬은 일반적인 형태는 위와 같이 몇개의 숫자들을 사각형 모양으로 배치하고 괄호(소괄호나 대괄호를 주로 사용)로 양 옆을 닫아 놓은 모습을 띠고 있습니다. 이 때 가로줄을 '행(行, Row)'이라 하고 세로줄을 '열(列, Column)'이라 부릅니다.
m 개의 행과 n개의 열을 가진 행렬을 'm×n 행렬(m by n matrix)'라고 부릅니다. 즉 m개의 가로줄과 n개의 세로줄로 구성되어 있다는 뜻입니다. 행렬 안에 놓인 숫자들은 행렬의 '성분(component)'라고 부르는데, 그러면 성분의 개수는 총 m×n개가 되겠지요

  • 행: 가로줄
  • 열: 세로줄
  • 행의 개수: 가로줄의 개수
  • 열의 개수: 세로줄의 개수

행렬의 곱

개요

행렬의 곱셈(matrix multiplication)은 여타 행렬의 연산과 같이, '크기가 맞는' 경우에만 할 수 있는데, 행렬의 곱셈에서 '크기가 맞는다'는 것은 앞 행렬의 열의 수와 뒤 행렬의 행의 수가 같다는 것이다. 아래 곱셈의 정의를 보면 명확할 것이다.

곱셈 결과 나오는 행렬의 크기

(앞 행렬의 행의 수) × (뒤 행렬의 열의 수)
(앞 행렬의 가로줄의 개수) x (뒤 행렬의 세로줄의 개수)

가 된다. 즉, 앞 행렬이 m×n 크기이고 뒤 행렬이 n×r 크기인 경우 곱은 m×r 크기의 행렬이 된다.

계산 방법

(× 기호 앞의 행렬의 열의 개수) = (× 뒤에 있는 행렬의 행의 개수)일 때만 곱셈 가능
(×) 기호 앞에 있는 행렬의 제i행과 (×) 기호 뒤에 있는 행렬의 제j열의 성분을 차례대로 곱하여 더한 값이 (i, j)성분

2차원 배열

2차원 배열이란 배열의 요소로 1차원 배열을 가지는 배열입니다.
자바스크립트에서는 다른 언어와는 다르게, 이차원 배열이란 개념이 없습니다. 그러나 이차원 배열 자체를 활용할 수 없는 것은 아닙니다.

2차원 배열 만드는 법

  • 배열에 초깃값을 할당하는 방법
  • 배열을 인자로 전달하는 방법 (array.push())
  • 반복문으로 배열 안에 배열을 생성하는 방법
  • ES6 문법으로 생성하는 방법

2차원 배열 이해하기

3x4 박스

1234
5678
9101112

const box = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]
보기 쉽게
const box = [
[1,2,3,4],
[5,6,7,8],
[9,10,11,12]]

  • 행의 수(가로줄의 수) = box.length (3)
  • 열의 수(세로줄의 수) = box[i].length (4)

7이라는 값을 얻고 싶으면 box[1][2]
원하는 값을 얻고 싶으면 box[몇 번째 행 - 1][몇 번째 열 - 1]

코드

function solution(arr1, arr2) {
    const answer = [];
    for(let i = 0; i < arr1.length; i++) { // arr1의 행의 개수
        const arr = [];
        const arrOneItem = arr1[i];
        for(let l = 0; l < arr2[0].length; l++){ // arr2의 열의 개수
            const sum = arrOneItem.reduce((acc, cur, i) => {
                return acc + (cur * arr2[i][l])
            }, 0);
            arr.push(sum);
        }
        answer.push(arr);
    }
    return answer;
}

풀이

행렬에 대해서 아예 몰라서 검색하고 공부하면서 풀었다.
정답인 2차원 배열을 만드는 방법은 배열을 인자로 전달하는 방법을 사용했다.
=> const answer = [] , answer.push([])

생각한 방법
arr1의 가로줄의 수만큼 반복문을 사용해서 반복할 때마다 나오는 arr1의 가로줄에 속해있는 요소들을 reduce함수를 이용해 더한다.
이렇게 요소들을 더하는 것을 arr2의 새로줄의 수만큼 더해야 한다.
따라서 반복문을 사용해서 arr2의 새로줄의 수만큼 더한다.
더할 때 그냥 더하는 것이 아닌 해당하는 arr2의 요소들을 곱해서 더해주어야 한다.
더해서 나온 값을 arr에 push해 주고
arr2의 새로줄의 수만큼 반복한 것이 완료된 이후 answer배열에 arr를 push해준다.
이러면 행의 곱의 가로줄 하나가 완성되게 된다.
이것을 arr1의 가로줄의 수만큼 반복하면 정답이 된다.

function solution(arr1, arr2) {
    const answer = [];
    arr1.map((arrOneItem, i) => {
        const arr = [];
        for(let l = 0; l < arr2[0].length; l++) {
            const sum = arrOneItem.reduce((acc, cur, i) => {
                return acc + (cur * arr2[i][l]);
            }, 0);
            arr.push(sum);
        }
        answer.push(arr);
    })
    return answer;
}

for문 대신 map을 사용해서 가독성 향상한 풀이


이번 문제 모르는 개념이 있어서 좀 오래 걸렸지만 개념들을 알아보면서 공부하니 재밌었다.
2차원 배열은 언제 어디서나 사용할 수 있으므로 꼭 이해하자.
arr[2][1]
가로줄 3번째에 새로줄 2번째 있는 item

0개의 댓글