본문 바로가기

알고리즘/프로그래머스

[파이썬] 프로그래머스 코딩테스트 2024 KAKAO WINTER INTERNSHIP - 가장 많이 받은 선물 완벽해설

문제

 

https://school.programmers.co.kr/learn/courses/30/lessons/258712?language=python3#

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

해설

 

이 문제의 경우 문제에서 요구하는 내용들(테이블 만들기, 테이블 각각의 값 계산 후 집어넣기)을 하나하나 코드로 구현하고, 마지막에 조건대로 코드를 작성하면 쉽게 풀 수 있다.

 

 

    table_1 = [[0 for _ in range(len(friends))] for _ in range(len(friends))]
    table_2 = [[0 for _ in range(3)] for _ in range(len(friends))]

 

이를 위해 가장 먼저 주고 받은 선물 갯수를 기록하는 첫번째 테이블과, 주고 받은 선물의 갯수 및 선물 지수를 기록하는 두번째 테이블을 만들어준다. 첫번째 테이블의 경우 "친구의 수* 친구의 수"의 크기로 구성된 테이블이며, 두번째 테이블의 경우 "친구의 수*3"의 크기로 구성된 테이블이다.

 

 

present_cnts = [0 for _ in range(len(friends))]

테이블을 만들어주었으니, 이제 각각의 친구들이 다음 달에 받을 선물을 기록할 리스트도 하나 만들어준다.

 

for i in range(len(gifts)):
        giver, taker = gifts[i].split()
        table_1[friends.index(giver)][friends.index(taker)] += 1
        
    for i in range(len(table_1)):
        table_2[i][0] = sum(table_1[i])
        for j in range(len(table_1[0])):
            table_2[i][1] += table_1[j][i]
        table_2[i][2] = table_2[i][0] - table_2[i][1]

이제 필요한 변수들은 모두 준비가 되었으니, 첫번째 테이블과 두번째 테이블에 해당되는 값들을 하나하나 넣어준다.  선물을 주고 받은 목록(gifts)에서 주는 사람과 받는 사람의 이름을 따로따로 받아들이고, 주는 사람과 받은 사람의 인덱스를 찾은 후 선물을 준 갯수를 하나하나 계산해주어 첫번째 테이블에 저장해준다.

 

그리고 나서 첫번째 테이블을 기반으로 두번째 테이블을 계산해준다. 여기서 주목할 점은 첫번째 테이블의 i번째 행 값의 총합은 결국 i번째 사람이 준 선물의 총 갯수이고, i번째 열 값의 총합은 i번째 사람이 받은 선물의 총 갯수가 된다.

 

이를 토대로 table_2에서 준 갯수, 받은 갯수를 각각 기입해주고, 준 갯수와 받은 갯수의 차로 선물지수를 계산해준다.

 

 

    for i in range(len(friends)):
        for j in range(i+1,len(friends)):
            # i가 더 많이 줌
            if (table_1[i][j]>table_1[j][i]):
                present_cnts[i] += 1
            # i가 더 많이 받음
            elif (table_1[i][j]<table_1[j][i]):
                present_cnts[j] += 1
            # 똑같음 - 선물지수 비교
            elif ((table_1[i][j]==table_1[j][i])):
                if (table_2[i][2]>table_2[j][2]):
                    present_cnts[i] += 1
                elif (table_2[i][2]<table_2[j][2]):
                    present_cnts[j] += 1
    answer = max(present_cnts)
    return answer

 

마지막으로 i번째 친구와 j번째 친구를 비교하여 주고 받은 선물의 갯수가 더 많고 적은지에 따라 i에게 선물을 주거나 또는 j에게 선물을 주도록 처리한다. 그리고 만약 i와 j가 주고 받은 선물의 갯수가 동일할 경우에는 선물 지수를 비교하는 그 다음 조건문으로 넘어가서, 선물 지수의 크고 적음에 따라 선물을 주도록 처리한다.

 

그리고 마지막으로 가장 선물을 많이 받은 갯수를 answer에 저장해주고 리턴해주면 끝난다.

 

 

코드
def solution(friends, gifts):
    answer = 0
    present_cnts = [0 for _ in range(len(friends))]
    
    # 준사람 받은사람 테이블 만들기 -> table_1
    table_1 = [[0 for _ in range(len(friends))] for _ in range(len(friends))]
    # 선물지수 계산 테이블 만들기 -> table_2
    table_2 = [[0 for _ in range(3)] for _ in range(len(friends))]
    
    # 주고 받은 리스트 처리
    for i in range(len(gifts)):
    	# 받은 사람, 준 사람 저장
        giver, taker = gifts[i].split()
        # 준사람 받은사람 테이블에 선물 주고받은 기록 남기기 
        table_1[friends.index(giver)][friends.index(taker)] += 1
    
    # 준사람 받은사람 테이블 기준으로 선물지수 계산하기
    for i in range(len(table_1)):
    	# i가 준 선물 갯수 계산 및 저장
        table_2[i][0] = sum(table_1[i])
        # i가 받은 선물 갯수 계산 및 저장
        for j in range(len(table_1[0])):
            table_2[i][1] += table_1[j][i]
        # 준 갯수 받은 갯수 토대로 선물지수 계산
        table_2[i][2] = table_2[i][0] - table_2[i][1]

	# 다음달에 받을 선물 예측 시작
    for i in range(len(friends)):
        for j in range(i+1,len(friends)):
            # i가 더 많이 줌 -> i가 선물 받음
            if (table_1[i][j]>table_1[j][i]):
                present_cnts[i] += 1
            # i가 더 많이 받음 -> i가 j에게 선물 줌
            elif (table_1[i][j]<table_1[j][i]):
                present_cnts[j] += 1
            # 똑같음 - 더 나아가 선물지수 비교
            elif ((table_1[i][j]==table_1[j][i])):
            	# i의 선물지수가 j보다 높음
                if (table_2[i][2]>table_2[j][2]):
                	# i가 선물 받음
                    present_cnts[i] += 1
                # j의 선물지수가 i보다 높음
                elif (table_2[i][2]<table_2[j][2]):
                	# j가 선물 받음
                    present_cnts[j] += 1
    # 최대로 받은 선물 갯수 저장 및 출력
    answer = max(present_cnts)
    return answer

 

 

결과