[프로그래머스] 위장 링크
내가 작성한 코드는 다음과 같다.
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
내 코드와 동일하다.
이상으로 포스트를 마칩니다. 감사합니다 😊