[프로그래머스] [해시] 위장

2021. 3. 11. 18:23Front-end/알고리즘

728x90
반응형

[해시] 위장

문제 출처: 프로그래머스(programmers.co.kr/learn/courses/30/lessons/42578)

 

문제 설명

스파이들은 매일 다른 옷을 조합하여 입어 자신을 위장합니다.

예를 들어 스파이가 가진 옷이 아래와 같고 오늘 스파이가 동그란 안경, 긴 코트, 파란색 티셔츠를 입었다면 다음날은 청바지를 추가로 입거나 동그란 안경 대신 검정 선글라스를 착용하거나 해야 합니다.

 

  종류                                                                                                이름

얼굴 동그란 안경, 검정 선글라스
상의 파란색 티셔츠
하의 청바지
겉옷 긴 코트

스파이가 가진 의상들이 담긴 2차원 배열 clothes가 주어질 때 서로 다른 옷의 조합의 수를 return 하도록 solution 함수를 작성해주세요.

 

제한사항

  • clothes의 각 행은 [의상의 이름, 의상의 종류]로 이루어져 있습니다.
  • 스파이가 가진 의상의 수는 1개 이상 30개 이하입니다.
  • 같은 이름을 가진 의상은 존재하지 않습니다.
  • clothes의 모든 원소는 문자열로 이루어져 있습니다.
  • 모든 문자열의 길이는 1 이상 20 이하인 자연수이고 알파벳 소문자 또는 '_' 로만 이루어져 있습니다.
  • 스파이는 하루에 최소 한 개의 의상은 입습니다.

입출력 예

clothes                                                                                                  return

[["yellowhat", "headgear"], ["bluesunglasses", "eyewear"], ["green_turban", "headgear"]] 5
[["crowmask", "face"], ["bluesunglasses", "face"], ["smoky_makeup", "face"]] 3

 

입출력 예 설명

예제 #1
headgear에 해당하는 의상이 yellow_hat, green_turban이고 eyewear에 해당하는 의상이 blue_sunglasses이므로 아래와 같이 5개의 조합이 가능합니다.

1. yellow_hat

2. blue_sunglasses

3. green_turban

4. yellow_hat + blue_sunglasses

5. green_turban + blue_sunglasses

 

예제 #2
face에 해당하는 의상이 crow_mask, blue_sunglasses, smoky_makeup이므로 아래와 같이 3개의 조합이 가능합니다.

1. crow_mask

2. blue_sunglasses

3. smoky_makeup

 

 

 

📝나의 풀이

전략 세우기

 

현재 옷이

headgear:  [yellowhat], [green_turban]

eyewear: [bluesunglasses]

이렇게 있다면 위의 문제에서 옷을 입는 경우의 수를 따지자면 3 * 2 = 6 에서 1을 뺀 5가 정답이 된다.

 

푸는 방법으로는 우선 각 의상의 카테고리 마다 입지 않는 경우를 하나씩 더해주어야 한다.

그리고 의상의 종류 끼리 곱을 하고 문제에서 하나라도 걸친다고는 했으므로 아무것도 입지 않는 경우의 수(전부다 입지 않음을 선택하게 되는 경우)를 하나 빼준다.

 

결론: 의상 카테고리끼리 곱하고 -1

 

headgear - [yellowhat], [green_turban],[입지 않음]

eyewear - [bluesunglasses], [입지 않음]

 

1. yellow_hat   = 사실상 [headgear - yellow_hat], [eyewear- 입지않음]
2. blue_sunglasses = 사실상 [headgear - 입지 않음], [eyewear- blue_sunglasses]
3. green_turban = 사실상 [headgear - green_turban], [eyewear- 입지않음]
4. yellow_hat + blue_sunglasses = [headgear - yellow_hat], [eyewear- bluesunglasses]5. green_turban + blue_sunglasses = [headgear - green_turban], [eyewear- bluesunglasses]

.아무것도 입지않는 경우 삭제= [headgear - 입지 않음], [eyewear - 입지 않음]

 

작성한 코드

function solution(clothes) {
    return Object.values(clothes.reduce((obj, t)=> {
        obj[t[1]] = obj[t[1]] ? obj[t[1]] + 1 : 1;
        return obj;
    } , {})).reduce((a,b)=> a*(b+1), 1)-1;    
}
console.log(solution([["yellowhat", "headgear"], ["bluesunglasses", "eyewear"], ["green_turban", "headgear"]]));   

reduce 함수는 첫번째 인자로 콜백함수를 가지고 두번째 인자로 초기값을 갖는다.

콜백함수는 4개의 인자를 가질 수 있는데, accumulator, currentvalue, index, array이다.

 

위의 함수에서는 주어진 clothes 배열에 대해서

accumulator로 obj라고 썼으며 초기값으로 {} 빈 객체를 전달했다.

currentValue에 해당하는 값으로 t를 주었는데

clothes 배열 자체가

[["yellowhat", "headgear"], ["bluesunglasses", "eyewear"], ["green_turban","headgear"]]

이것 이므로, t는 이 각각이 t가 된다.

t[1]은 "headgear" "eyewear"와 같은 옷의 종류가 되겠다.

obj[t[1]]이라는 것은, 원래 객체에서 object.property 라고 하는 것처럼 object["property"] 라는 방식으로도 프로퍼티를 검색할 수가 있으므로 obj[t[1]]은 obj["headgear"]와 같은 것이다.

 

그리고 삼항연산자를 사용하였는데,

삼항연산자의 문법은 조건식 ? 참일때 값 : 거짓일때 값  이므로

obj[t[1]] ? 이라는 것은 여기서 값이 존재한다면 true 값이 없으면 false가 되는 것이다.

값이 존재한다면 1을 더해주고 값이 존재하지 않다면 1을 넣는다.

 

1을 더하거나 넣는 이유는, 의상의 카테고리마다 개수만 확인해주면 되므로 그렇다.

 

그렇게 첫번째 reduce 함수를 다 연산하고 나면 { headgear: 2 , eyewear: 1} 이라는 객체가 반환되고 그것을 값만 얻어야 하기 때문에 Object.values(객체) 라는 메소드를 사용한다.

***Object.values(객체) 메소드: 객체안의 값들만 추출해서 배열로 리턴

따라서 [2,1]이라는 배열이 리턴이 된다.

 

2에다가도 1을 더하고 1에다가도 1을 더해서 서로 곱하고 -1을 해주면 되기 때문에

또 reduce 함수를 사용해서 초기 값은 1로 주고, 현재 값에 +1 을 해서 곱한다.

함수가 종료되면 -1을 한 값을 최종적으로 리턴해주면 된다.

 

🌟reduce() 함수

 이 함수는 첫번째 인자로 콜백 함수를 전달받고 두번째 인자로 초기값을 전달받는다.

사용법 : arr.reduce(callback[, initialValue])

 

reduce()는 빈 요소를 제외하고 배열 내에 존재하는 각 요소에 대해 callback 함수를 한 번씩 실행하는데,

콜백 함수는 다음의 네 인수를 받는다.

  • accumulator
  • currentValue
  • currentIndex
  • array

만약 reduce() 함수 호출에서

initialValue를 제공한 경우, accumulator는 initialValue와 같고 currentValue는 배열의 첫 번째 값과 같다.

initialValue를 제공하지 않았다면, accumulator는 배열의 첫 번째 값과 같고 currentValue는 두 번째와 같다.

 

예) const sum = [1,2,3,4];

sum.reduce((accumulator, currentValue, index, array) => accumulator+currentValue, 0);

728x90
반응형