코딩테스트 공부/프로그래머스 문제

프로그래머스 해시_위장 (Counter, reduce)

Stat_in_KNU 2020. 5. 3. 16:12

위장

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

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

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

제한사항

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

 

 


 

 

기본적인 경우의 수 순열 문제를 코드로 구현하는 문제이다.

하지만 순열문제임을 눈치채지 못하고 for문을 반복해서 쓰다가 많이 헤맸다..

+ list의 성분을 Count하는 부분을 잘 몰랐기 때문에 구글에서 검색해 collections의 Counter를 import해서 풀이함.

 

from collections import Counter

def solution(clothes):
    answer = 0
    temp = []
    num = 1
    
    for i in range(0, len(clothes)):
        temp.append(clothes[i][1])
    
    result = Counter(temp)
    result = list(result.values())
    
    for i in range(0, len(result)):
        num = num * (list(result)[i] + 1)
    
    answer = num - 1
    
    return answer

내 코드는 뭔가 모르게 조잡하다.

 

다른사람의 풀이법

1.

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

2.

def solution(clothes):
    clothes_type = {}

    for c, t in clothes:
        if t not in clothes_type:
            clothes_type[t] = 2
        else:
            clothes_type[t] += 1

    cnt = 1
    for num in clothes_type.values():
        cnt *= num

    return cnt - 1

3.

import collections
from functools import reduce

def solution(c):
    return reduce(lambda x,y:x*y,[a+1 for a in collections.Counter([x[1] for x in c]).values()])-1

 

순열을 이용했다는 기본원리는 같다. Counter객체와 reduce에 대해서 공부할 필요가 있다.

 

collections 모듈 - Counter

https://excelsior-cjh.tistory.com/94

 

collections 모듈 - Counter

collections.Counter() 컨테이너에 동일한 값의 자료가 몇개인지를 파악하는데 사용하는 객체이다. docs.python.org에서 Counter함수에 대해 자세히 알아볼 수 있다. A Counter is a dict subclass for counting h..

excelsior-cjh.tistory.com

간단히 설명하면 컨테이너에 동일한 값의 자료가 몇개인지를 파악하는데 사용하는 객체이고, 그 출력값은 딕셔너리 형태이다. 

여기서 말하는 컨테이너는 리스트, 딕셔너리, 스트링, 또는 (값=개수) 형태가 될 수 있다.

 

Counter의 사용가능 메소드는

1) Update() : Counter의 값 갱신

2) elements() : 입력된 값의 요소에 해당하는 값을 풀어서 반환

3) most_common(n) : 입력된 값의 요소들 중 빈도스가 높은 순으로 상위 ~개를 list안의 tuple형태로 반환해준다.

4) substract() : 말 그대로 요소를 뺴는 것을 의미한다 다만, 요소가 없는 경우에는 음수 값이 출력된다.

 

Counter의 연산

1) 덧셈(+) : 더한 요소만큼 카운트를 더해서 세어 줌

2) 뺄셈(-) : substarct와 다르게 음수값은 출력하지 않음

3) 교집합(&)과 합집합(|) : 말 그대로 요소간의 교집합, 합집합의 개수를 세어준다 출력은 딕셔너리 형태

 

functools 모듈 - reduce

 

reduce(function, iterable, initializer = None)

reduce는 첫 번째 파라미터로 함수(람다함수, 정의함수) 두 번째 파라미터로 계산 하고자하는 리스트가 들어 갈 수 있다.

 

from functools import reduce

result = reduce(lambda x, y: x+y, [1,2,3,4,5])
# (((1+2)+3)+4)+5)

#15

위와같이 리스트 안의 모든 값을 더 해줄 수도 있고 (for문이 필요없다)

 

 

from functools import reduce

func = lambda a, b: a if (a > b) else b
# a,b 비교해서 더 큰 것만 반환해주는 함수
result = reduce(func, [1, 100, 2, 55])

print(result)

# 100

 

위와 같이 최대값을 구할 수 도 있다!