[js] 최소 직사각형 (lv.1)

sookyoung.k·2024년 5월 28일
post-thumbnail

명함 지갑을 만드는 회사에서 지갑의 크기를 정하려고 합니다. 다양한 모양과 크기의 명함들을 모두 수납할 수 있으면서, 작아서 들고 다니기 편한 지갑을 만들어야 합니다. 이러한 요건을 만족하는 지갑을 만들기 위해 디자인팀은 모든 명함의 가로 길이와 세로 길이를 조사했습니다.

아래 표는 4가지 명함의 가로 길이와 세로 길이를 나타냅니다.

명함 번호가로 길이세로 길이
16050
23070
36030
48040

가장 긴 가로 길이와 세로 길이가 각각 80, 70이기 때문에 80(가로) x 70(세로) 크기의 지갑을 만들면 모든 명함들을 수납할 수 있습니다. 하지만 2번 명함을 가로로 눕혀 수납한다면 80(가로) x 50(세로) 크기의 지갑으로 모든 명함들을 수납할 수 있습니다. 이때의 지갑 크기는 4000(=80 x 50)입니다.

모든 명함의 가로 길이와 세로 길이를 나타내는 2차원 배열 sizes가 매개변수로 주어집니다. 모든 명함을 수납할 수 있는 가장 작은 지갑을 만들 때, 지갑의 크기를 return 하도록 solution 함수를 완성해주세요.

제한사항

  • sizes의 길이는 1 이상 10,000 이하입니다.
    - sizes의 원소는 [w, h] 형식입니다.
    - w는 명함의 가로 길이를 나타냅니다.
    - h는 명함의 세로 길이를 나타냅니다.
    - w와 h는 1 이상 1,000 이하인 자연수입니다.

나의 풀이

function solution(sizes) {
    // 배열 내의 가로, 세로를 [큰 수, 작은수]로 재정렬
    let result = sizes.map((v) => {
        return v.sort((a, b) => b - a);
    });
    
    let findOne = (arr, n) => {
        // 배열의 n번째 숫자만 담을 배열
        let element = [];
        for(let i=0; i<arr.length; i++) {
            element.push(arr[i][n]);
        };
        // 그 중에 가장 큰 숫자를 return
        return Math.max(...element)
    }
    
    return findOne(result, 0) * findOne(result, 1);
}
  • 주어진 각 명함 크기 배열을 [큰 수, 작은 수] 형태로 재정렬한다. (map()과 sort()를 사용함) 이를 통해서 모든 명함의 크기를 일관되게 배치한다.
  • findOne()함수는 재정렬된 배열에서 가로와 세로의 최대값을 찾는다. 가로와 세로의 값을 찾기 위해 총 두 번 호출된다.
  • 최소 면적을 계산한다. → 가로 *세로

다른 풀이 1

function solution(sizes) {
    const [hor, ver] = sizes.reduce(([h, v], [a, b]) => [Math.max(h, Math.max(a, b)), Math.max(v, Math.min(a, b))], [0, 0])
    return hor * ver;
}

reduce()를 사용해서 더욱 간결하고 효율적으로 만들었다!!! ㅠㅠ 부러워

  • reduce() 메서드를 이용해 size 배열을 수노히하며 최대 가로 길이와 최소 가로 길이를 구한다.
    - [h, v]는 현재까지의 최대 가로 길이와 최대 세로 길이를 나타낸다.
    • [a, b]는 순회 중인 배열의 가로 길이와 세로 길이를 나타낸다.
    • Math.max(h, Math.max(a, b))는 현재까지의 최대 가로 길이와 현재 배열 요소 중 더 큰 값을 비교하여 더 큰 값을 선택한다. 반대도 마찬가지.
  • reduce()를 통해 최종적으로 구해진 최대 가로 길이와 최대 세로 길이가 [hor, ver]에 저장된다. 이후 곱해서 최소 면적을 구한다.

reduce()를 배열에 활용하는 것도 잘 적용해봐야겠다.

다른 풀이 2

function solution(sizes) {
    const rotated = sizes.map(([w, h]) => w < h ? [h, w] : [w, h]);

    let maxSize = [0, 0];
    rotated.forEach(([w, h]) => {
        if (w > maxSize[0]) maxSize[0] = w;
        if (h > maxSize[1]) maxSize[1] = h;
    })
    return maxSize[0]*maxSize[1];
}
  • map()을 사용해 명함을 회전시켜 정렬한다. w가 h보다 작으면 큰 값을 가로로, 작은 값을 세로로 만든다.
  • forEach()를 통해 배열을 순회하며 최대 가로 길이와 최대 세로 길이를 찾는다. 각 명함의 가로/세로 값이 현재 최대 가로/세로 값보다 크면 갱신한다.
  • 최종 결과를 계산한다.
profile
영차영차 😎

0개의 댓글