[프로그래머스] 위장

InKi Hong·2021년 9월 23일
0

[프로그래머스] 위장 링크

내가 작성한 코드는 다음과 같다.


from collections import defaultdict
def solution(clothes):
    answer = 0
    p = defaultdict(list)

    for cloth in clothes:
        p[cloth[1]].append(cloth[0])

    if len(p) == 1:
        answer = len(p[clothes[0][1]])

    else:
        temp = 1
        for key in p.keys():
            temp *= len(p[key])+1
        answer += temp - 1

    return answer

✅ 내 코드 풀이

1. Input

def solution(clothes):

스파이가 가진 의상들이 담긴 2차원 배열 clothes,
이때 clothes의 각 행은 [의상의 이름, 의상의 종류]이다.

예를 들어 clothes =
[["yellowhat", "headgear"],
["bluesunglasses", "eyewear"],
["green_turban", "headgear"]]
이면

1. yellow_hat
2. blue_sunglasses
3. green_turban
4. yellow_hat + blue_sunglasses
5. green_turban + blue_sunglasses

즉, 5개의 조합이 가능하다.

2. Process

from collections import defaultdict
def solution(clothes):
    answer = 0
    p = defaultdict(list)

중복을 담지 못하는 dict 구조가 아쉬워 방법을 찾아봤다.
collections 모듈의 defalutdict(list)는 value 값을 list로 생성가능하다. 따라서 (key, [value A, value B, ...]) 같은 형태로 구성할 수 있다.


   for cloth in clothes:
        p[cloth[1]].append(cloth[0])

clothes 배열은 [[의상의 이름, 의상의 종류], ...] 형태이고, cloth[0]는 의상이름, cloth[1]은 의상종류를 의미한다.

p key = 의상의 종류, p value = 의상의 이름들이 저장


    if len(p) == 1:
        answer = len(p[clothes[0][1]])

의상의 종류가 한 가지라면, answer에는 해당 의상 종류를 키로 가지는 의상들의 총 개수가 저장된다.


    else:
        temp = 1
        for key in p.keys():
            temp *= len(p[key])+1
        answer += temp - 1
    return answer        

의상의 종류가 여러 가지라면, (종류마다 해당하는 의상들의 총 갯수+1)을 서로 곱해준다. 그 뒤에 -1 해주는 이유는 아무 의상도 고르지 않았을 때의 경우를 제외하기 위함이다.

코드로 설명하기 어려운 부분이라 잠시 설명하겠다.

p가 다음 표와 같이 구성되있다고 가정해보자.

의상종류의상이름
A[1, 2, 3]
B[4, 5, 6]
C[7, 8, 9]

단순하게 A, B, C 의 조합은 3x3x3 = 27가지다.
그러나 해당 문제에서는 A만 입고, B와 C는 안입는 등의 경우가 존재한다. 이처럼 해당 의상종류를 입지 않는 경우도 생각해야 한다.

의상종류의상이름
A[1, 2, 3, 입지않음]
B[4, 5, 6, 입지않음]
C[7, 8, 9, 입지않음]

따라서 입지않음의 경우까지 생각하여 총 조합은 4x4x4 = 64가지라고 볼 수 있으나 아무것도 입지 않는 경우는 없으니 64-1 = 63가지의 경우가 존재한다.

3.Output

if __name__ == '__main__':
    solution([["yellowhat", "headgear"], ["bluesunglasses", "eyewear"], ["sunglasses", "eyewear"], ["green_turban", "headgear"],["blond","hair"], ["black","hair"]])
    solution([["yellowhat", "headgear"], ["bluesunglasses", "eyewear"], ["green_turban", "headgear"]])
    solution([["crowmask", "face"], ["bluesunglasses", "face"], ["smoky_makeup", "face"]])

입력이 위와 같다면 output은 다음과 같다.

26
5
3

✅ 코드 실행시간 테스트

내 코드 test case 실행시간

테스트 1 〉	통과 (0.02ms, 10.2MB)
테스트 2 〉	통과 (0.01ms, 10.1MB)
테스트 3 〉	통과 (0.01ms, 10.2MB)
테스트 4 〉	통과 (0.02ms, 10.2MB)
테스트 5 〉	통과 (0.01ms, 10.2MB)
테스트 6 〉	통과 (0.01ms, 10.3MB)
테스트 7 〉	통과 (0.02ms, 10.2MB)
테스트 8 〉	통과 (0.01ms, 10.2MB)
테스트 9 〉	통과 (0.01ms, 10.3MB)
테스트 10 〉	통과 (0.01ms, 10.2MB)
테스트 11 〉	통과 (0.01ms, 10.2MB)
테스트 12 〉	통과 (0.02ms, 10.2MB)
테스트 13 〉	통과 (0.02ms, 10.1MB)
테스트 14 〉	통과 (0.01ms, 10.2MB)
테스트 15 〉	통과 (0.01ms, 10.2MB)
테스트 16 〉	통과 (0.01ms, 10.2MB)
테스트 17 〉	통과 (0.01ms, 10.2MB)
테스트 18 〉	통과 (0.02ms, 10.2MB)
테스트 19 〉	통과 (0.01ms, 10.2MB)
테스트 20 〉	통과 (0.01ms, 10.2MB)
테스트 21 〉	통과 (0.01ms, 10.1MB)
테스트 22 〉	통과 (0.01ms, 10.2MB)
테스트 23 〉	통과 (0.01ms, 10.3MB)
테스트 24 〉	통과 (0.01ms, 10.2MB)
테스트 25 〉	통과 (0.02ms, 10.1MB)
테스트 26 〉	통과 (0.02ms, 10.2MB)
테스트 27 〉	통과 (0.01ms, 10.2MB)
테스트 28 〉	통과 (0.02ms, 10.1MB)

[프로그래머스] 다른 코드풀이 링크

def solution(clothes):
    from collections import Counter
    from functools import reduce
    cnt = Counter([kind for name, kind in clothes])
    answer = reduce(lambda x, y: x*(y+1), cnt.values(), 1) - 1
    return answer

해당 코드 test case 실행시간

테스트 1 〉	통과 (0.04ms, 10.1MB)
테스트 2 〉	통과 (0.03ms, 10.1MB)
테스트 3 〉	통과 (0.03ms, 10.1MB)
테스트 4 〉	통과 (0.04ms, 10.1MB)
테스트 5 〉	통과 (0.03ms, 10.1MB)
테스트 6 〉	통과 (0.03ms, 10.3MB)
테스트 7 〉	통과 (0.05ms, 9.96MB)
테스트 8 〉	통과 (0.03ms, 10.2MB)
테스트 9 〉	통과 (0.04ms, 10.1MB)
테스트 10 〉	통과 (0.03ms, 10.3MB)
테스트 11 〉	통과 (0.03ms, 10.3MB)
테스트 12 〉	통과 (0.03ms, 10MB)
테스트 13 〉	통과 (0.04ms, 10.2MB)
테스트 14 〉	통과 (0.04ms, 10.1MB)
테스트 15 〉	통과 (0.03ms, 10.1MB)
테스트 16 〉	통과 (0.03ms, 10.1MB)
테스트 17 〉	통과 (0.05ms, 9.99MB)
테스트 18 〉	통과 (0.05ms, 10.2MB)
테스트 19 〉	통과 (0.03ms, 10.1MB)
테스트 20 〉	통과 (0.03ms, 10.1MB)
테스트 21 〉	통과 (0.06ms, 10.2MB)
테스트 22 〉	통과 (0.05ms, 10.1MB)
테스트 23 〉	통과 (0.04ms, 10MB)
테스트 24 〉	통과 (0.05ms, 10.1MB)
테스트 25 〉	통과 (0.03ms, 10.1MB)
테스트 26 〉	통과 (0.04ms, 10.1MB)
테스트 27 〉	통과 (0.03ms, 10.1MB)
테스트 28 〉	통과 (0.03ms, 10.2MB)

해당 코드의 실행시간은 내 코드보다 느리지만 익숙하지 않은 모듈과 연산을 사용하고 코드 구성이 간략해서 분석
해보기로 했다.


✅ 다른 코드풀이 분석

[프로그래머스] 다른 코드풀이 링크

def solution(clothes):
    from collections import Counter
    from functools import reduce
    cnt = Counter([kind for name, kind in clothes])
    answer = reduce(lambda x, y: x*(y+1), cnt.values(), 1) - 1
    return answer

1. Input

입력 예시는 아래와 같다고 가정하자.

solution([["yellowhat", "headgear"],
["bluesunglasses", "eyewear"],                
["green_turban", "headgear"]])

2. Process

def solution(clothes):
    from collections import Counter
    from functools import reduce

해당 코드는 collections 모듈의 Counter() 연산과 functools의 reduce() 연산을 사용했다.

Counter() 연산 사용법

from collections import Counter
Counter('hello world') 
# Counter({'l': 3, 'o': 2, 'h': 1, 'e': 1, ' ': 1, 'w': 1, 'r': 1, 'd': 1})
참조한 링크: https://www.daleseo.com

reduce() 연산 사용법

from functools import reduce
array = [1, 2, 3, 4, 5]
def sum(a, b):
    return a + b
reduce(sum, array)
# sum(sum(sum(sum(1, 2), 3), 4), 5)
# -> ((((1 + 2) + 3) + 4) +5)
# -> 15
참조한 링크: https://technote.kr/344

cnt = Counter([kind for name, kind in clothes])
#cnt = Counter({'headgear': 2, 'eyewear': 1})

[kind for name, kind in clothes]clothes 배열에서 옷의 종류만 떼서 담은 배열이다.


answer = reduce(lambda x, y: x*(y+1), cnt.values(), 1) - 1
# answer = 1*(2+1)*(1+1)-1
return answer

초기값이 1로 주어 졌기 때문에 연산은 1x(2+1)x(1+1)-1
와 같다. 따라서 해당 예시에 대한 출력은 5

3. Output

내 코드와 동일하다.


이상으로 포스트를 마칩니다. 감사합니다 😊

profile
S.W Developer

0개의 댓글