본문 바로가기
코딩테스트/프로그래머스

프로그래머스 | Python | Hash | 성격 유형 검사하기 (Lv.1)

by RuntimeSimple 2025. 2. 19.

https://school.programmers.co.kr/learn/courses/30/lessons/118666

 

프로그래머스

SW개발자를 위한 평가, 교육, 채용까지 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프

programmers.co.kr

 

def solution(survey, choices):
    # 성격 유형 점수를 저장할 딕셔너리
    personality_scores = {char: 0 for char in "RTCFJMAN"}

    # 선택지에 따른 점수 매핑
    score_map = {1: 3, 2: 2, 3: 1, 4: 0, 5: 1, 6: 2, 7: 3}

    # 각 질문을 순회하며 점수 부여
    for (first, second), choice in zip(survey, choices):
        if choice < 4:  # 비동의 선택지 (1, 2, 3)
            personality_scores[first] += score_map[choice]
        elif choice > 4:  # 동의 선택지 (5, 6, 7)
            personality_scores[second] += score_map[choice]

    # 성격 유형을 결정하는 4가지 지표 (점수가 같으면 사전순 우선)
    return "".join(
        max(pair, key=lambda x: (personality_scores[x], -ord(x)))
        for pair in [('R', 'T'), ('C', 'F'), ('J', 'M'), ('A', 'N')]
        )   

1. 입력 데이터

survey = ["AN", "CF", "MJ", "RT", "NA"]
choices = [5, 3, 2, 7, 5]
  • survey: 성격 유형을 판단하는 설문 목록
  • choices: 각 질문에 대한 선택지

2. 성격 유형 점수 초기화

personality_scores = {char: 0 for char in "RTCFJMAN"}
  • 각 성격 유형을 딕셔너리로 관리하며, 초기에 모든 점수를 0으로 설정한다.
  • 결과:
{'R': 0, 'T': 0, 'C': 0, 'F': 0, 'J': 0, 'M': 0, 'A': 0, 'N': 0}

3. 선택지에 따른 점수 매핑

score_map = {1: 3, 2: 2, 3: 1, 4: 0, 5: 1, 6: 2, 7: 3}
  • 1~3번 선택지: 비동의 측 점수 증가
  • 4번 선택지: 점수 없음
  • 5~7번 선택지: 동의 측 점수 증가

4. 점수 부여 과정

for (first, second), choice in zip(survey, choices):
    if choice < 4:
        personality_scores[first] += score_map[choice]
    elif choice > 4:
        personality_scores[second] += score_map[choice]

각 설문 항목과 선택지를 순회하며, 선택지에 따라 점수를 부여한다.

점수 부여 과정 상세 분석

1) 첫 번째 질문 (survey[0] = "AN", choices[0] = 5)

  • "A": 비동의 유형, "N": 동의 유형
  • 선택지 5: "N"에 1점 추가
{'R': 0, 'T': 0, 'C': 0, 'F': 0, 'J': 0, 'M': 0, 'A': 0, 'N': 1}

2) 두 번째 질문 (survey[1] = "CF", choices[1] = 3)

  • "C"에 1점 추가
{'R': 0, 'T': 0, 'C': 1, 'F': 0, 'J': 0, 'M': 0, 'A': 0, 'N': 1}

3) 세 번째 질문 (survey[2] = "MJ", choices[2] = 2)

  • "M"에 2점 추가
{'R': 0, 'T': 0, 'C': 1, 'F': 0, 'J': 0, 'M': 2, 'A': 0, 'N': 1}

4) 네 번째 질문 (survey[3] = "RT", choices[3] = 7)

  • "T"에 3점 추가
{'R': 0, 'T': 3, 'C': 1, 'F': 0, 'J': 0, 'M': 2, 'A': 0, 'N': 1}

5) 다섯 번째 질문 (survey[4] = "NA", choices[4] = 5)

  • "A"에 1점 추가
{'R': 0, 'T': 3, 'C': 1, 'F': 0, 'J': 0, 'M': 2, 'A': 1, 'N': 1}

5. 성격 유형 결정

result = "".join(
    max(pair, key=lambda x: (personality_scores[x], -ord(x)))
    for pair in [('R', 'T'), ('C', 'F'), ('J', 'M'), ('A', 'N')]
)
  • 점수가 높은 성격 유형을 선택한다.
  • 점수가 같다면 사전순으로 앞선 성격 유형을 선택한다.

각 지표별 선택 과정

1) 첫 번째 지표 ('R', 'T')

max(('R', 'T'), key=lambda x: (personality_scores[x], -ord(x)))
  • 'R': (0, -82)
  • 'T': (3, -84)✅ 선택: "T"

2) 두 번째 지표 ('C', 'F')

max(('C', 'F'), key=lambda x: (personality_scores[x], -ord(x)))
  • 'C': (1, -67) ✅ 선택: "C"
  • 'F': (0, -70)

3) 세 번째 지표 ('J', 'M')

max(('J', 'M'), key=lambda x: (personality_scores[x], -ord(x)))
  • 'J': (0, -74)
  • 'M': (2, -77)✅ 선택: "M"

4) 네 번째 지표 ('A', 'N')

max(('A', 'N'), key=lambda x: (personality_scores[x], -ord(x))
  • 'A': (1, -65)✅ 선택: "A"
  • 'N': (1, -78)

6. 최종 결과

"TCMA"

7. 실행 흐름 정리

  1. 설문과 선택지를 분석하여 점수를 계산한다.
  2. 각 성격 유형에서 더 높은 점수를 가진 유형을 선택한다.
  3. 점수가 같을 경우 사전순으로 앞선 유형을 선택한다.
  4. 최종 결과를 반환한다.

사용된 문법에 대해 더 알아봅시다.

zip(survey, choices)의 결과

zip() 함수는 여러 개의 리스트를 동시에 묶어주는 함수이다.

즉, survey와 choices를 묶어서 튜플(pair) 형태의 이터레이터(iterator)를 생성한다.


zip(survey, choices)의 실행 과정

survey = ["AN", "CF", "MJ", "RT", "NA"]
choices = [5, 3, 2, 7, 5]

zipped_data = zip(survey, choices)  # zip 객체 생성
print(list(zipped_data))  # 리스트로 변환하여 출력

출력 결과

[('AN', 5), ('CF', 3), ('MJ', 2), ('RT', 7), ('NA', 5)]

for (first, second), choice in zip(survey, choices) 동작 과정

for (first, second), choice in zip(survey, choices):
    print(f"first: {first}, second: {second}, choice: {choice}")

출력 결과

first: A, second: N, choice: 5
first: C, second: F, choice: 3
first: M, second: J, choice: 2
first: R, second: T, choice: 7
first: N, second: A, choice: 5

작동 방식

  • zip(survey, choices)는 ('AN', 5), ('CF', 3), ... 이런 형태의 튜플을 반환한다.
  • first, second = survey[i]는 "AN"을 분해하여 첫 번째 문자 'A', 두 번째 문자 'N'을 추출한다.
  • choice = choices[i]는 해당 질문의 선택지를 저장한다.

즉, 한 줄의 코드로 "AN"을 'A'와 'N'으로 분해하고,

해당 질문의 선택지(choices[i])도 동시에 저장할 수 있다.


max()의 key 활용

return "".join(
    max(pair, key=lambda x: (personality_scores[x], -ord(x)))
    for pair in [('R', 'T'), ('C', 'F'), ('J', 'M'), ('A', 'N')]
)

lambda x: (personality_scores[x], -ord(x))의 의미

  1. personality_scores[x] → 점수가 가장 높은 성격 유형 선택
  2. -ord(x) → 점수가 같을 경우, 사전순으로 앞선 문자 선택
    •   ord('A') = 65, ord('N') = 78
    •   -ord('A') = -65, -ord('N') = -78→ A가 더 크므로 A가 선택됨.