본문 바로가기

PS/프로그래머스

[프로그래머스-해시] 위장_파이썬 ❌⭕

 

programmers.co.kr/learn/courses/30/lessons/42578?language=python3

 

코딩테스트 연습 - 위장

 

programmers.co.kr


from collections import defaultdict
def solution(clothes):
    dic = defaultdict(int)
    for cloth in clothes:
        dic[cloth[1]] += 1
    
    cnt = 1    
    for value in dic.values():
        cnt *= (value + 1)
    
    return cnt - 1

 

이 문제를 풀기 위해선 일단 경우의 수를 어떻게 구해야 하는지 알고 있어야 한다.

결론부터 말하자면 의상의 종류만큼 (의상의 개수 + 1)을 곱한 뒤 1을 빼줘야 한다.

(예를 들어 모자가 2개, 신발이 1개 있다면, 3 * 2 - 1)

여기서 왜 의상의 개수에 1을 더해주는지 의문을 가질 수 있는데, 안 입는 경우의 수를 추가해줘야 하기 때문이다. 그리고 마지막에 1을 빼주는 이유는 아무것도 안 입는 경우의 수는 없기 때문이다.

추가로 딕셔너리 구조에서 value를 하나씩 사용하려면 그냥 for문을 사용하면 된다는 것을 알고 있어야 한다.


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

다음은 reduce를 이용한 풀이이다.

Counter 클래스를 이용해 의상의 종류의 개수 정보를 담은 배열을 만들고, reduce를 이용해 연산을 해주면 된다.

reduce는 reduce(function, iterable, initializer = None) 구조로 되어있는데,

iterable을 function에 누적해서 넣어주는 일을 수행한다. 알기 쉽게 코드를 보자.

e1 = reduce(lambda x, y : x * (y + 1), [2, 2, 3])
print(e1)
>> 24

e2 = reduce(lambda x, y : x * (y + 1), [2, 2, 3], 1)
print(e2)
>> 36

예시를 보면 initializer에 의해서 값이 달라지는 것을 알 수 있는데,

initializer가 없다면 iterable[0]이 처음 x에 들어가게 된다.


from functools import reduce
from collections import Counter
def solution(clothes):
    return reduce(lambda x, y: x * y, [value + 1 for value in Counter([cloth[1] for cloth in clothes]).values()]) - 1

추가로 이렇게 한 줄로 처리할 수 도 있다. 가독성이 떨어지긴 하지만, 위의 코드랑 같은 풀이라고 볼 수 있다.