본문 바로가기

Algorithm/코딩테스트 고득점 Kit

[고득점 Kit / 해시] 의상 (Counter, 리스트 컴프리헨션)

https://school.programmers.co.kr/learn/courses/30/lessons/42578

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

수학적으로 답이 나오는 과정을 이해해야 한다. 

테스트케이스를 보자.

 

clothes return
[["yellow_hat", "headgear"], ["blue_sunglasses", "eyewear"], ["green_turban", "headgear"]] 5
[["crow_mask", "face"], ["blue_sunglasses", "face"], ["smoky_makeup", "face"]] 3

 

첫번째 테스트케이스의 가능한 경우의 수는 다음과 같다.

 

1. yellow_hat -> headgear1
2. blue_sunglasses -> eyewear1
3. green_turban -> headgear2
4. yellow_hat + blue_sunglasses -> headgear1 + eyewear1
5. green_turban + blue_sunglasses -> headgear2 + eyewear1

 

어떻게 5가지가 나온걸까?

 

사용자는 2개의 headgear와 1개의 eyewear중 의상을 선택해서 조합을 이룰 것이다.

사용자가 선택할 수 있는 경우의 수를 구해보자.

headgear: yellow_hat, green_turban, headgear 선택안함 -> 3가지 경우의 수

eyewear: blue_sunglasses, eyewear 선택안함 -> 2가지 경우의 수

 

그리고 3 * 2를 해주면 전체 경우의 수가 나온다. 하지만 아무 의상도 입지 않는 경우는 없으니 1을 빼줘야 한다.

결론적으로, (2 + 1) * (1 + 1) - 1 = 5라는 결과가 나온 것이다. 

 

이러한 공식을 찾게 된다면, 풀이는 쉬워진다.

 

from collections import Counter

def solution(clothes):
    clothes_counter = Counter([kind for _, kind in clothes])
    
    combinations = 1
    for count in clothes_counter.values():
        combinations *= (count + 1)
    
    return combinations - 1

 

코드를 하나하나씩 살펴보자.

 

def solution(clothes):
    clothes_counter = Counter([kind for _, kind in clothes])

 

이 부분에서는 clothes 리스트에서 의상의 종류별로 몇 개의 아이템이 있는지를 세고 있다,

  • clothes는 이차원 배열로, 예를 들어 [['yellow_hat', 'headgear'], ['blue_sunglasses', 'eyewear'], ['green_turban', 'headgear']]와 같은 형태다.
  • 리스트 컴프리헨션 [kind for _, kind in clothes]는 clothes의 각 요소에서 의상의 종류(kind)만을 추출하여 리스트를 만든다.
  • 예를 들어, clothes가 [['yellow_hat', 'headgear'], ['blue_sunglasses', 'eyewear'], ['green_turban', 'headgear']]라면, 리스트 컴프리헨션은 ['headgear', 'eyewear', 'headgear']를 생성한다.
  • 이 리스트를 Counter에 전달하면, Counter({'headgear': 2, 'eyewear': 1})처럼 종류별 의상 개수를 세는 사전이 생성된다.

 

    combinations = 1
    for count in clothes_counter.values():
        combinations *= (count + 1)

 

이 부분에서는 의상 조합의 수를 계산한다.

  • clothes_counter.values()는 Counter에서 각 종류별 의상 개수를 반환한다. 예를 들어 Counter({'headgear': 2, 'eyewear': 1})라면 values()는 [2, 1]을 반환한다,
  • 각 의상 종류별로, (의상 개수 + 1)을 곱한다. 이때 +1을 더하는 이유는 해당 종류의 의상을 착용하지 않는 경우도 포함하기 위함이다.
  • 예를 들어, headgear가 2개라면, headgear를 착용하지 않는 경우를 포함하여 3가지의 선택지가 있는 것이다: yellow_hat, green_turban, 착용하지 않음.
  • 모든 종류에 대해 이러한 계산을 곱해 나가면 가능한 모든 조합의 수가 계산된다.

 

    return combinations - 1

 

마지막으로, combinations에서 1을 뺀다. 이는 모든 종류의 의상을 착용하지 않는 경우를 제외하기 위함이다. 문제의 조건 중 "코니는 하루에 최소 한 개의 의상은 입습니다"라는 조건을 충족하기 위해 아무것도 입지 않는 경우를 제외해야 한다.