[프로그래머스] 의상 (Python)

lemonlily·2024년 1월 29일

문제

문제 링크

문제 설명
코니는 매일 다른 옷을 조합하여 입는것을 좋아합니다.

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

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

코니는 각 종류별로 최대 1가지 의상만 착용할 수 있습니다. 예를 들어 위 예시의 경우 동그란 안경과 검정 선글라스를 동시에 착용할 수는 없습니다.
착용한 의상의 일부가 겹치더라도, 다른 의상이 겹치지 않거나, 혹은 의상을 추가로 더 착용한 경우에는 서로 다른 방법으로 옷을 착용한 것으로 계산합니다.
코니는 하루에 최소 한 개의 의상은 입습니다.
코니가 가진 의상들이 담긴 2차원 배열 clothes가 주어질 때 서로 다른 옷의 조합의 수를 return 하도록 solution 함수를 작성해주세요.

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

입출력 예

clothes	return
[["yellow_hat", "headgear"], ["blue_sunglasses", "eyewear"], ["green_turban", "headgear"]]	5
[["crow_mask", "face"], ["blue_sunglasses", "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

문제 해결 접근

  • 해시 알고리즘 문제를 파이썬으로 풀 때는 dict구조를 사용하면 된다.
  • 그래서 옷 종류별로 개수가 얼마 있는지를 확인하고, 그 조합을 계산하려고 했다.

코드 구현

trial 1 (fail)

from collections import defaultdict
from itertools import combinations

def solution(clothes):

    dic = defaultdict(int)
    for _, t in clothes:
        dic[t] += 1

    answer = sum(list(dic.values()))
    types = list(dic.keys())

    for i in range(2, len(types)+1):
        comb = combinations(types, i) 

        for tup in list(comb):
            tmp = 1
            for sub in tup:
                tmp *= dic[sub]
            answer += tmp 

    return answer
  • 기본적으로 머릿속에서 생각해낼 수 있는 것을 알고리즘으로 구현했다.
  • dic에 종류별 개수를 담아놓고,
  • combinations 를 사용해서, 종류별로 2개를 뽑을 때, 3개를 뽑을 때... 의 경우의 수를 곱해주는 방식을 활용했다.
  • 다른 테케는 모두 통과하지만 1번 테케는 통과하지 않았다!!!!
  • 커뮤니티를 살펴보니 1번 테케는 30 종류의 옷이 단 1개씩 있는 케이스라서, 이 경우 2^n-1 의 시간 복잡도가 올 수 있는 걸 생각해야 한다고 했다.
  • 그러나 내 머릿속에서는 도저히 어떻게 풀어야 할 지 모르겠었다...

trial 2 (pass)

from collections import defaultdict

def solution(clothes):
    answer = 1
    dic = defaultdict(int)
    for _, t in clothes:
        dic[t] += 1
    values = list(dic.values())
    
    for v in values:
        answer *= (v+1) 
            
    return answer-1
  • 결국 구글링 한 것을 내 코드에 적용해서 모든 테케에서 통과할 수 있었다.
  • 결국은 수학 공식인 셈인데,,, 이 수학 공식은 아래와 같다고 한다.
(의상종류 별 의상 수 + 1)씩 모두 곱하는 이유는 의상종류 별 의상수에 그 의상을 안 입는 경우의 수도 곱하는 것입니다. 
거기에 추가적으로 -1을 하는 이유는 아무것도 모두 안 입는 경우의 수를 빼는 것입니다.

느낀 점

  • 수학 공식으로 풀어야 하는 문제였다.
  • 그 동안 조합을 풀 때 combinations 로 구현했었는데 시간복잡도가 높다는 것을 알 수 있었다.
  • 전체 조합을 확인해야 할 때 알면 좋은 공식을 겟했다!
profile
NLP 엔지니어,,,,? 가 될 수,,,? 나도,,,,?

0개의 댓글