4일차 → 최소 직사각형(forEach([값, 값]), map([값, 값]))
본문 바로가기
항해 중/2주차 알고리즘(프로그래머스)

4일차 → 최소 직사각형(forEach([값, 값]), map([값, 값]))

by 은돌1113 2021. 11. 11.

문제 설명

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

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

가장 긴 가로 길이와 세로 길이가 각각 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 이하인 자연수입니다.

 

문제 자체를 이해를 못하고 있었는 데 어떤 분이 힌트를 주셨다!

 

1. 가로, 세로는 고정된 값이 아니다.

2. 명함을 90도로 돌리면 세로였던 길이가 가로가 된다.

(이 원리를 사용하여 가로를 큰 수로 바꿔준다.)

 

-> 가로와 세로 길이 중에서 더 긴 걸 가로로 옮긴다.

-> 가로에서 제일 긴 길이와 세로에서 제일 긴 길이를 곱해서 넓이를 구한다.

 

이렇게 이해를 하고 나서 문제를 보니까 문제에 답이 다 있었다.

 

내가 푼 문제 풀이

 

첫번째 방법

function solution(sizes) {

    let wMax = 0 // 가로의 최대 길이
    let hMax = 0 // 세로의 최대 길이
    
    // 가로, 세로는 고정된 값이 아니기 때문에
    // 배열함수 map()과 sort()를 사용하여서 더 긴 길이는 가로에 담는다.
    let result = sizes.map((item)=>{return item.sort((a, b)=>b-a)})

    // 가로에서 제일 긴 길이
    let w = result.map(item=>{return item[0]}) // 가로 길이만 배열에 담는다.
    w.forEach(item=>{(wMax < item)? wMax = item : wMax})

    // 세로에서 제일 긴 길이
    let h = result.map(item=>{return item[1]}) // 세로 길이만 배열에 담는다.
    h.forEach(item=>{(hMax < item)? hMax = item : hMax})

    return wMax * hMax;
}

1) map 함수를 사용해서 sizes 배열 안의 요소를 정렬한다. 이때 b-a를 사용해서 큰 값이 앞에 위치 하도록 한다.

2) 제일 긴 가로 길이를 구하기 위해서 가로 길이만 따로 배열에 담는다.

3) forEach 함수를 돌려서 가로 길이 중 가장 큰 값을 wMax에 담는다.

4) 제일 긴 세로 길이을 구하기 위해서 세로 길이만 따로 배열에 담는다.

5) forEach 함수를 돌려서 세로 길이 중 가장 큰 값을 hMax에 담는다.

6) wMax와 hMax를 곱한 넓이를 return 한다.

 

두번째 방법

function solution(sizes) {

    let wMax = 0
    let hMax = 0 
    
    // 가로, 세로는 고정된 값이 아니기 때문에
    // 배열함수 map()을 사용하여서 더 긴 길이는 가로에 담는다.
    // map()에서 인자를 받을 때 배열의 요소는 []를 사용하면 각각 받을 수 있다.
    let result = sizes.map(([w, h])=>{return (w < h)? [h, w] : [w, h]})

    for(let i = 0; i<result.length; i++){

      // 가로에서 제일 긴 길이
      wMax < result[i][0] ? wMax = result[i][0] : wMax

      // 세로에서 제일 긴 길이
      hMax < result[i][1] ? hMax = result[i][1] : hMax
      
    }
    
    return wMax * hMax;
}

1) map()를 사용 할 때 인자에 요소를 받아 올 때 배열 형태의 값을 받아오고 싶었는 데 [w, h]를 사용하면 받아 올 수 있었다. (전까지는 w, h를 써서 받아오지 못했었다.) -> 가로와 세로 길이 중 더 긴 값을 가로에 넣는다.

2) 반복문을 돌려서 가로에서 제일 긴 길이와 세로에서 제일 긴 길이을 변수에 각각 담는다.

3) wMax와 hMax를 곱한 넓이를 return 한다.

 

세번째 방법

function solution(sizes) {

    let wMax = 0
    let hMax = 0 
    
    let result = sizes.map(([w, h])=>{return (w < h)? [h, w] : [w, h]})
    // [ [ 60, 50 ], [ 70, 30 ], [ 60, 30 ], [ 80, 40 ] ]

    result.forEach(([w, h])=>{
    // [ [ 60, 50 ], [ 70, 30 ], [ 60, 30 ], [ 80, 40 ] ]
      wMax < w ? wMax = w : wMax
      hMax < h ? hMax = h : hMax
    })
    
    return wMax * hMax;
}

밑에 다른 분이 푸신 풀이를 보고 for문을 돌리지 않고 forEach를 사용해서 [w, h]를 인자로 받아오면 되겠구나!!를 깨닫고 코드를 수정 해보았다.

 

깨닳은 점

문제를 잘 읽고 이해 한 후 구현 하는 게 좋을 것 같다.

 

다른 사람이 푼 풀이

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];
}

나는 for문을 돌려서 가로, 세로에서 가장 긴 길이를 구했는 데 다른 분은 여기서도 배열에 요소를 인자로 받아와서

비교 하셨다.

https://velog.io/@cjh951114/JavaScriptProgrammers-%EC%B5%9C%EC%86%8C%EC%A7%81%EC%82%AC%EA%B0%81%ED%98%95

 

[JavaScript][Programmers] 최소직사각형

https://programmers.co.kr/learn/courses/30/lessons/86491

velog.io

 

https://programmers.co.kr/learn/courses/30/lessons/86491

 

코딩테스트 연습 - 최소직사각형

[[10, 7], [12, 3], [8, 15], [14, 7], [5, 15]] 120 [[14, 4], [19, 6], [6, 16], [18, 7], [7, 11]] 133

programmers.co.kr

 

댓글