/ CODING

Coding - 코딩테스트 연습(고득점 kit - 해시)

코딩테스트 공부 목록에 대한 내용

코딩 테스트 연습 (고득점 kit - 해시)

프로그래머스 참고링크

1. 포켓몬

def solution(nums):
    # 뽑을 수 있는 포켓몬의 최대 개수를 구한다 (포켓몬을 선택할 때, 총 개수의 절반만큼 뽑을 수 있다).
    sel = len(nums) // 2
    
    # set을 사용해서 중복되는 포켓몬을 제거하고, 각 포켓몬 종류의 개수를 구한다.
    nums = set(nums)
    
    # if문을 사용해서 포켓몬 종류의 개수(nums)와 최대 뽑을 수 있는 개수(sel)를 비교한다.
    
    # 포켓몬 종류의 개수와 최대 뽑을 수 있는 개수가 같다면, 포켓몬 종류의 개수를 반환한다.
    if len(nums) == sel:
        return len(nums)
    
    # 포켓몬 종류의 개수가 최대 뽑을 수 있는 개수보다 많다면, 최대 뽑을 수 있는 개수를 반환한다.
    elif len(nums) > sel:
        return sel
    
    # 포켓몬 종류의 개수가 최대 뽑을 수 있는 개수보다 적다면, 포켓몬 종류의 개수를 반환한다.
    elif len(nums) < sel:
        return len(nums)

2. 완주하지 못한 선수

# participant => 마라톤에 참여한 선수들의 이름
# 참가자 중에는 동명이인이 있을 수 있다.
# completion => 완주한 선수들의 이름이 담긴 배열
# return => 완주하지 못한 선수의 이름
def solution(participant, completion):
    # 완주하지 못한 선수의 이름을 저장할 변수
    answer = ''
    
    # 참가자 이름을 키로 하고, 동명이인 수를 값으로 하는 딕셔너리
    par_dict = {}
    
    # 참가자들의 이름을 딕셔너리에 저장하고, 동명이인 수를 카운트한다.
    for i in participant:
        if i in par_dict:
            par_dict[i] += 1
        else:
            par_dict[i] = 1
    
    # 완주한 선수들의 이름에 해당하는 딕셔너리 키 값을 1씩 감소시킨다.
    for j in completion:
        if j in par_dict:
            par_dict[j] -= 1
    
    # 딕셔너리의 값이 1인 키(완주하지 못한 선수)를 answer에 추가한다.
    for k in par_dict:
        if par_dict[k] >= 1:
            answer += k
    
    # 완주하지 못한 선수의 이름을 반환한다.
    return answer

3. 전화번호 목록

"""
전화번호부에 적힌 전화번호를 담긴 배열: phone_book
result: 어떤 번호가 다른 번호의 접두어인 경우가 있으면 => false 아니라면 ture
처음에 잘못 생각했던 부분은 맨 앞의 첫번째가 두번째 이후의 전화번호의 전두어가 되는지만 
판단하였다. 하지만 다른 사람들의 풀이를 보았을 때, 어떤 번호가 다른 번호의 접두사가 된다고 
판단하면 될 것 같다고 생각하였다. 이렇게 생각하고 풀어보니 정답
"""
def solution(phone_book):
    # 전화번호부를 정렬하여 더 짧은 번호가 앞에 오게 한다.
    phone_book.sort()
    
    # 전화번호부의 전화번호를 순서대로 검사한다.
    for i in range(1, len(phone_book)):
        # 이전 전화번호를 secure 변수에 저장한다.
        secure = phone_book[i-1]
        
        # 이전 전화번호의 길이를 구한다.
        secure_len = len(secure)
        
        # 현재 전화번호의 접두어가 이전 전화번호와 같은지 확인한다.
        if phone_book[i][:secure_len] == secure:
            # 같다면 접두어가 있는 것이므로 False를 반환한다.
            return False
            
    # 전화번호부를 모두 검사했음에도 접두어가 없는 경우 True를 반환한다.
    return True

4.위장

"""
INPUT
스파이가 가진 의상들이 담긴 2차원 배열 clothes
OUPUT
서로 다른 옷의 조합의 수
"""
def solution(clothes):
    # 옷의 종류를 키로, 해당 종류의 옷 목록을 값으로 저장할 딕셔너리 생성
    clothes_dict = {}
    
    # 옷 목록(clothes)를 순회하며 옷 종류별로 딕셔너리에 저장
    for cloth_name, cloth_type in clothes:
        if cloth_type in clothes_dict:
            clothes_dict[cloth_type].append(cloth_name)
        else:
            clothes_dict[cloth_type] = [cloth_name]
    # 예: clothes_dict = {face: [crow_mask, blue_sunglasses, smoky]}
    # 최종 조합의 수를 구하기 위한 변수 초기화
    total_combinations = 1
    
    # 딕셔너리의 키(옷 종류)를 순회하며 각 종류별 옷 개수에 +1 한 값을 곱한다.
    # +1 하는 이유는 해당 옷 종류를 안 입는 경우를 포함하기 위함
    for cloth_type in clothes_dict.keys():
        total_combinations *= (len(clothes_dict[cloth_type]) + 1)
        
    # 아무것도 안 입는 경우를 제외하기 위해 최종 결과에서 1을 뺀 값을 반환한다.
    return total_combinations - 1

5. 베스트앨범

def solution(genres, plays):
    answer = []
    genre_dict = {}

    # 장르별로 노래 정보(재생 횟수, 고유 번호)를 저장
    for i in range(len(genres)):
        if genres[i] in genre_dict:
            genre_dict[genres[i]].append([plays[i], i])
        else:
            genre_dict[genres[i]] = [[plays[i], i]]

    genre_rank = {}

    # 장르별 노래의 총 재생 횟수를 계산
    for genre in genre_dict.keys():
        total_plays = 0
        for song in genre_dict[genre]:
            total_plays += song[0]
        genre_rank[genre] = total_plays

    # 총 재생 횟수를 기준으로 장르 순위 정렬
    genre_rank = sorted(genre_rank.items(), key=lambda x: x[1], reverse=True)

    # 각 장르별로 재생 횟수가 많은 노래 2개씩 선택
    for genre in genre_rank:
        song_rank = sorted(genre_dict[genre[0]], key=lambda x: (-x[0], x[1]))
        best_two = 0
        for song in song_rank:
            answer.append(song[1])
            best_two += 1
            if best_two == 2:
                break

    return answer