Algorithm/programmers.co.kr

프로그래머스 고득점 kit 풀기 #해시

winney916 2022. 3. 12. 18:37
728x90

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

람다 안에 람다... 

파이썬은 정말 경이로운 언어인 것 같다.