본문 바로가기
ALGORITHM/프로그래머스 With JS

[프로그래머스] 위장 / Javascript

by LAY CODER 2021. 4. 29.

문제

 

코딩테스트 연습 - 위장

 

programmers.co.kr

 


 

TRY

const clothes1 = [
    ['yellowhat', 'headgear'],
    ['bluesunglasses', 'eyewear'],
    ['green_turban', 'headgear'],
];
const clothes2 = [
    ['crowmask', 'face'],
    ['bluesunglasses', 'face'],
    ['smoky_makeup', 'face'],
];

function solution(clothes) {
    
    // 옷의 종류와 종류별 갯수를 저장 할 객체
    let obj = {};

    for (let i = 0; i < clothes.length; i++) {
        // 옷의 종류가 정의 되지 않았으면 옷의 종류의 value = 1
        if (obj[clothes[i][1]] === undefined) {
            obj[clothes[i][1]] = 1;
            // 종류가 존재하면 value에 + 1
        } else {
            obj[clothes[i][1]]++;
        }
    }

    // 옷의 종류별 개수를 담을 배열을 초기화
    let clothesKind = [];

    // 옷의 종류별 갯수를 clotherKind 배열에 담아준다.
    for (const key in obj) {
        if (Object.hasOwnProperty.call(obj, key)) {
            clothesKind.push(obj[key]);
        }
    }

    // 경우의 수를 담을 result 변수 초기화
    let result = 0;

    //
    for (let i = 0; i < clothesKind.length; i++) {
        // ex) [1,2]
        // 첫 번째 경우의 수(1) + 두 번째 경우의 수(2) + 둘의 곱(2) = 5
        // ex) [1,2,3]
        // 이전 경우의 수(5) + 자신의 경우의 수(3) + 둘의 곱(5*3) = 23

        // i가 0 이상 일때
        if (i) {
            result += result * clothesKind[i];
        }
        result += clothesKind[i];
    }

    return result;
}

console.log(solution(clothes1));
console.log(solution(clothes2));

 

객체를 만들고 옷의 종류별 개수를 파악하는 건 쉬웠는데 옷을 조합하는 경우의 수를 알아차리는 게 힘들었다.

 

처음에는 옷의 종류가 [1,2,3] 가지 있다고 하면 1*2*3 = 6인 줄 알았는데

 

이건 3가지 옷을 전부 입어야 할 때의 경우의 수 이고

 

문제는 1가지 종류만 입을 수도 있고 2가지 종류만 입을 수도 있다.

 

그래서 처음 내가 생각한 경우의 수 방식은 (이전 경우의 수 + 자신의 경우의 수 + 둘의 곱) 방식이었다.

 

[1,2,3] 경우를 예를 들면

 

[1] 일때 경우의 수 = 1

 

[1,2] 일때 경우의 수 = 이전 경우의 수(1) + 자신의 경우의수(2) + 둘의 곱(1*2) => 5 

 

[1,2,3] 일 때 경우의 수 = 이전 경우의 수(5) + 자신의 경우의 수(3) + 둘의 곱(5*3) => 23

 

이런 방식으로 답을 구했다.

 

 

 


 

Refactoring

const clothes1 = [
    ['yellowhat', 'headgear'],
    ['bluesunglasses', 'eyewear'],
    ['green_turban', 'headgear'],
];
const clothes2 = [
    ['crowmask', 'face'],
    ['bluesunglasses', 'face'],
    ['smoky_makeup', 'face'],
];

function solution(clothes) {
    
    let obj = {};

    for (let i = 0; i < clothes.length; i++) {
        obj[clothes[i][1]] = (obj[clothes[i][1]] || 1) + 1;
    }

    let result = 1;

    for (const key in obj) {
        if (Object.hasOwnProperty.call(obj, key)) {
            result *= obj[key];
        }
    }

    return result - 1;
}

console.log(solution(clothes1));
console.log(solution(clothes2));

 

다른 풀이를 보다가 알게 된 훨씬 쉬운 방식이

 

(자신의 경우의 수 + 1) 로 다 곱해주고 -1(옷을 한 가지도 안 입을 경우) 이다.

 

다시 [1,2,3] 으로 예를 들면

 

1  X = > 2(자신의 경우의 수(1) + 안 입는 경우의 수(1)

1 1 X = > 3(자신의 경우의 수(2) + 안 입는 경우의 수(1)

1 1 1 X = > 4(자신의 경우의 수(4) + 안 입는 경우의 수(1)

 

를 다 곱한 24에서 XXX(모두 다 안 입는 경우) 인 경우 1만 빼주면 되는 것이다.

 

또 유용하게 알게 된 부분이

 

옷을 객체에 넣어주는 부분에서 사용하게 된 Logical OR(||) 이다.

 

합집합으로만 사용하는 줄 알았던 || 연산자가 이렇게 간편하게 사용할 수 있구나 라는 걸 새삼 느꼈다.

 

&&와 ||의 단축평가에 대해서는 아래 분이 정말 자세하게 설명을 해주셔서 쉽게 이해할 수 있었다.

 

 

[자바스크립트] 논리연산자(&&, ||) 단축평가

# 단축평가란? ||(논리합), &&(논리곱) 연산자는 왼쪽부터 오른쪽으로 평가를 진행하는데, 중간에 평가 결과가 나오면 오른쪽 끝까지 가지 않고 평가 결과를 반환해 버린다. 이를 '단축 평가(short

curryyou.tistory.com

 


 

Refactoring

const clothes1 = [
    ['yellowhat', 'headgear'],
    ['bluesunglasses', 'eyewear'],
    ['green_turban', 'headgear'],
];
const clothes2 = [
    ['crowmask', 'face'],
    ['bluesunglasses', 'face'],
    ['smoky_makeup', 'face'],
];

function solution(clothes) {

    return (
        Object.values(
            clothes.reduce((obj, t) => {
                obj[t[1]] = (obj[t[1]] || 1) + 1;
                return obj;
            }, {}),
        ).reduce((a, b) => a * b, 1) - 1
    );
    
}

console.log(solution(clothes1));
console.log(solution(clothes2));

 

두 번째 방식을 극도로 축약해서 return 한방에 보내버린다.

 

Array.reduce() 를 이용하여 옷의 경우의 수를 종류별 개수 배열로 반환하고 그 배열을 다시 reduce하여 경우의 수를 구한 뒤

 

바로 return 해버리는 방식이다.

댓글