Practice for coding test

프로그래머스 - Level 2. 행렬의 곱셈 / JavaScript (js)

Gray Park 2023. 2. 22. 11:30
728x90
반응형

 

 

문제설명

문제분석

이 문제는 행렬의 곱을 알면 해결할 수 있는 문제입니다.

출처: 위키피디아

행렬의 곱을 실행하고 난 뒤의 결과물 총 크기는 arr1의 row 갯수, arr2의 col 갯수로 이루어진 2차원 배열(행렬)입니다.

뿐만 아니라 행렬의 곱은 다음과 같은 순서로 이루어져 각 요소별로 곱셈과 덧셈이 이뤄지게 됩니다.

조금더 복잡하지만 명확하게 각 요소별 값을 구하면 다음과 같습니다.

각 요소에 대해 a_ik와 b_kj의 스칼라 곱의 총 합을 구하면 됩니다.

이해하기 쉽게 코드작성하기

function solution(arr1, arr2) {
    const answer = new Array(arr1.length).fill().map(() => new Array(arr2[0].length).fill(0));
    
    for(let r = 0; r < arr1.length; r++) {
        for(let c = 0; c < arr2[0].length; c++) {
            let sum = 0;
            for(let t = 0; t < arr1[0].length; t++) {
                sum += arr1[r][t] * arr2[t][c];
            }
            answer[r][c] = sum;
        }
    }
    return answer;
}

코드 설명

arr1을 서치하며 arr2의 col을 서치합니다. 마지막으로 arr1의 각 요소에 접근하여 곱셈한 결과를 모두 더하고, 그 결괏값을 answer에 저장합니다.

 

다소 복잡해 보이는 게 사실이니 메서드를 이용해 조금 단순하게 변경해보겠습니다.

function solution(arr1, arr2) {
     return arr1
        .map((r) => arr2[0]
             .map((_, cIdx) => r
                  .map((x, i) => x * arr2[i][cIdx])
                  .reduce((a,c)=>a+c)))
}

결과 행렬의 row는 arr1의 row 길이만큼 생성되므로 arr1에서 map을 실행합니다. 각 row는 arr2의 col 길이만큼 생성되므로 arr2[0]에서 map을 실행합니다. 사실 arr2의 각 row마다 map을 실행하면 좋겠지만, 인덱스만으로 접근이 가능하니 이렇게 작성하였습니다.

그리고 내부에서 arr1의 row에 존재하는 각 요소에 접근하기 위해 r에서 map을 실행합니다. 이때 arr2의 각 요소와의 곱으로 리턴합니다. 그 후 리턴한 결과를 reduce로 모두 더해줍니다.

 

막상 이렇게 작성하니 가장 안쪽에 위치한 map-reduce를 하나의 reduce로 변환해줘도 무방해 보입니다.

function solution(arr1, arr2) {
     return arr1
        .map((r) => arr2[0]
             .map((_, cIdx) => r
                  .reduce((a,c,i)=>a + c * arr2[i][cIdx], 0)));
}

이렇게 2차원 행렬의 곱을 완성했습니다.

728x90
반응형