프로그래머스 고득점 kit 풀기 #해시
1. 완주하지 못한 선수
: 두 리스트에 중복하여 존재하지 않는 값을 찾는 문제이다.
내 풀이
def solution(participant, completion):
player = {}
for p in participant:
try:
player[p] += 1
except:
player[p] = 1
for c in completion:
player[c] -=1
for i in player:
if player[i]:
return i
베스트 풀이
import collections
def solution(participant, completion):
answer = collections.Counter(participant) - collections.Counter(completion)
return list(answer.keys())[0]
사실, 내가 구현한 함수가 카운터 함수와 유사하다고 할 수 있을 것 같다.
다만 카운터 객체는 뺄셈연산이 가능하다는점..
2. 전화번호 목록
: 처음에 조금 해매서 검색을 했다.. ㅠㅠ
내 풀이
def solution(phone_book):
answer = True
# 문자열로 저장된 숫자를 정렬하면 1,2,3 순서대로 정렬된다.
# -> 접두어 판단에 유리하다.
phone_book = sorted(phone_book)
# 접두어. 머리부분만 비교해야한다.
for i in range(len(phone_book)-1):
if phone_book[i] == phone_book[i+1][:len(phone_book[i])]:
answer = False
return answer
sorted함수의 특징을 충분히 이해하지 못해 벌어진 일이라고 생각한다.
베스트 풀이
def solution(phoneBook):
phoneBook = sorted(phoneBook)
for p1, p2 in zip(phoneBook, phoneBook[1:]):
if p2.startswith(p1):
return False
return True
zip함수와 startwith 메소드를 사용한게 인상적이다. zip 함수는 iterable 자료형을 동일한 갯수로 묶어주는 함수이고, startwith는 접두어를 비교하는 함수인 듯 한다.
즉 zip([a,b,c], [1,2,3) => [ (a,1), (b,2), (c,3) ] 형태가 된다. 위 문제를 풀기에 너무나 완벽한 함수인 것 같다.
3. 위장
: 그냥 못풀었다. 열심히 짜 봤지만 테스트케이스 하나를 틀렸다.
내 풀이 (틀림)
from itertools import combinations
def solution(clothes):
answer = 0
clothes_dict = {}
for v, k in clothes:
try:
clothes_dict[k].append(v)
except:
clothes_dict[k] = [v]
for i in range(1,len(clothes_dict.keys())+1):
for keys in combinations(clothes_dict.keys(), i):
tmp = 1
for k in keys:
tmp *= len(clothes_dict[k])
answer += tmp
return answer
찾은 풀이 (검색)
def solution(clothes):
answer = {}
for i in clothes:
if i[1] in answer:
answer[i[1]] += 1
else:
answer[i[1]] = 1
cnt = 1
for i in answer.values():
cnt *= (i+1)
return cnt -1
알고 보면 굉장히 단순한 문제이다.
옷의 종류 별 경우의 수는 해당 종류의 가짓수 + 1 (그 종류를 입지 않았을 때) 이다.
때문에, 카테고리별 갯수를 세어 준 다음 1을 더한 값들을 곱해주면 된다.
최종 출력시에는 -1 (모든 종류의 옷을 입지 않았을 경우 제외) 해주면 된다.
문제 이해부터 입력값 이해까지 온전히 이해를 하지 못한 상태로 문제를 풀었던 것 같다.
4. 베스트앨범
꽤나 곤혹스러웠던 문제이다.
장르별 합이 가장 큰 순서대로 두 개의 곡을 넣는데, 그 두 곡은 해당 장르의 곡들 중 가장 조회수가 높은 곡이어야한다.
두개의 리스트를 비교하면서 인덱스를 저장해야했기에 나는 세 데이터를 모두 통합한 리스트를 새롭게 만들었다.
그 뒤 장르별 조회수의 합을 딕셔너리로 구하고, 장르 리스트를 만들어 이 리스트를 조회수의 합을 기준으로 역 정렬했다. (이거 고민하는데 한참걸림)
그리고 곡들을 정렬한 뒤 정답을 구했다.
내 코드
def solution(genres, plays):
answer = []
music = []
sum_of_g = dict()
i = 0
for g, p in zip(genres, plays):
music.append([g,p,i])
i+=1
try:
sum_of_g[g] += p
except:
sum_of_g[g] = p
# 우선순위 1. 장르별 합
g = list(sum_of_g.keys())
g = sorted(g, key=lambda g: sum_of_g[g], reverse=True)
# 우선순위 2. 곡 별 조회수
music = sorted(music, key=lambda a: a[1], reverse=True)
for genre in g:
cnt = 0
for m in music:
if cnt > 1:
break
if m[0] == genre:
answer.append(m[2])
cnt += 1
return answer
핵심적인 부분은 sorted(list, key=lambda a: ... ) 이 부분이다. 리스트 내에 있는 데이터를 기반으로 정렬하지 않아도 된다. lambda함수를 사용해주면 딕셔너리에 저장한 값 (다른 변수에 저장된 값)을 기준으로 정렬할 수 있다. (저거 없었으면 못풀었음)
하지만 정석적인 방법이 필요함으로 다른 사람의 코드를 참고해보자.
추천순 1위
def solution(genres, plays):
answer = []
d = {e:[] for e in set(genres)}
for e in zip(genres, plays, range(len(plays))):
d[e[0]].append([e[1] , e[2]])
genreSort =sorted(list(d.keys()), key= lambda x: sum( map(lambda y: y[0],d[x])), reverse = True)
for g in genreSort:
temp = [e[1] for e in sorted(d[g],key= lambda x: (x[0], -x[1]), reverse = True)]
answer += temp[:min(len(temp),2)]
return answer
람다 안에 람다...
파이썬은 정말 경이로운 언어인 것 같다.