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

[프로그래머스] - 성격 유형 검사하기(C#)

by jyppro 2023. 9. 19.

성격 유형 검사하기

이번에 풀어 볼 문제는 "성격 유형 검사하기" 문제입니다. 이 문제는 2022 KAKAO TECH INTERNSHIP에 출제된 문제로 난이도가 꽤 있고, 상당히 도움이 될 수 있는 문제 중 하나입니다. 정답률은 48%로 매우 낮은 편에 속합니다. 이제 문제를 풀어보도록 하겠습니다.

 

문제 설명

나만의 카카오 성격 유형 검사지를 만들려고 합니다.
성격 유형 검사는 다음과 같은 4개 지표로 성격 유형을 구분합니다. 성격은 각 지표에서 두 유형 중 하나로 결정됩니다.

지표 번호 성격 유형
1번 지표 라이언형(R), 튜브형(T)
2번 지표 콘형(C), 프로도형(F)
3번 지표 제이지형(J), 무지형(M)
4번 지표 어피치형(A), 네오형(N)

4개의 지표가 있으므로 성격 유형은 총 16(=2 x 2 x 2 x 2)가지가 나올 수 있습니다. 예를 들어, "RFMN"이나 "TCMA"와 같은 성격 유형이 있습니다.

검사지에는 총 n개의 질문이 있고, 각 질문에는 아래와 같은 7개의 선택지가 있습니다.

  • 매우 비동의
  • 비동의
  • 약간 비동의
  • 모르겠음
  • 약간 동의
  • 동의
  • 매우 동의

각 질문은 1가지 지표로 성격 유형 점수를 판단합니다.

예를 들어, 어떤 한 질문에서 4번 지표로 아래 표처럼 점수를 매길 수 있습니다.

선택지 성격 유형 점수
매우 비동의 네오형 3점
비동의 네오형 2점
약간 비동의 네오형 1점
모르겠음 어떤 성격유형도 점수를 얻지 않습니다
약간 동의 어피치형 1점
동의 어피치형 2점
매우 동의 어피치형 3점

이때 검사자가 질문에서 약간 동의 선택지를 선택할 경우 어피치형(A) 성격 유형 1점을 받게 됩니다. 만약 검사자가 매우 비동의 선택지를 선택할 경우 네오형(N) 성격 유형 3점을 받게 됩니다.

위 예시처럼 네오형이 비동의, 어피치형이 동의인 경우만 주어지지 않고, 질문에 따라 네오형이 동의, 어피치형이 비동의인 경우도 주어질 수 있습니다.
하지만 각 선택지는 고정적인 크기의 점수를 가지고 있습니다.

  • 매우 동의나 매우 비동의 선택지를 선택하면 3점을 얻습니다.
  • 동의나 비동의 선택지를 선택하면 2점을 얻습니다.
  • 약간 동의나 약간 비동의 선택지를 선택하면 1점을 얻습니다.
  • 모르겠음 선택지를 선택하면 점수를 얻지 않습니다.

검사 결과는 모든 질문의 성격 유형 점수를 더하여 각 지표에서 더 높은 점수를 받은 성격 유형이 검사자의 성격 유형이라고 판단합니다. 단, 하나의 지표에서 각 성격 유형 점수가 같으면, 두 성격 유형 중 사전 순으로 빠른 성격 유형을 검사자의 성격 유형이라고 판단합니다.

질문마다 판단하는 지표를 담은 1차원 문자열 배열 survey와 검사자가 각 질문마다 선택한 선택지를 담은 1차원 정수 배열 choices가 매개변수로 주어집니다. 이때, 검사자의 성격 유형 검사 결과를 지표 번호 순서대로 return 하도록 solution 함수를 완성해주세요.

 

제한사항

  • 1 ≤ survey의 길이 ( = n) ≤ 1,000
  • survey의 원소는 "RT", "TR", "FC", "CF", "MJ", "JM", "AN", "NA" 중 하나입니다.
  • survey[i]의 첫 번째 캐릭터는 i+1번 질문의 비동의 관련 선택지를 선택하면 받는 성격 유형을 의미합니다.
  • survey[i]의 두 번째 캐릭터는 i+1번 질문의 동의 관련 선택지를 선택하면 받는 성격 유형을 의미합니다.
  • choices의 길이 = survey의 길이
  • choices[i]는 검사자가 선택한 i+1번째 질문의 선택지를 의미합니다.
  • 1 ≤ choices의 원소 ≤ 7
choices
1 매우 비동의
2 비동의
3 약간 비동의
4 모르겠음
5 약간 동의
6 동의
7 매우 동의

 

입출력 예

servey choices result
["AN", "CF", "MJ", "RT", "NA"] [5, 3, 2, 7, 5] "TCMA"
["TR", "RT", "TR"] [7, 1, 3] "RCJA"

 

입출력 예 설명

입출력 예 #1
1번 질문의 점수 배치는 아래 표와 같습니다.

선택지 성격 유형 점수
매우 비동의 어피치형 3점
비동의 어피치형 2점
약간 비동의 어피치형 1점
모르겠음 어떤 성격유형도 점수를 얻지 않습니다
약간 동의 네오형 1점
동의 네오형 2점
매우 동의 네오형 3점

1번 질문에서는 지문의 예시와 다르게 비동의 관련 선택지를 선택하면 어피치형(A) 성격 유형의 점수를 얻고, 동의 관련 선택지를 선택하면 네오형(N) 성격 유형의 점수를 얻습니다.
1번 질문에서 검사자는 약간 동의 선택지를 선택했으므로 네오형(N) 성격 유형 점수 1점을 얻게 됩니다.

2번 질문의 점수 배치는 아래 표와 같습니다.

선택지 성격 유형 점수
매우 비동의 콘형 3점
비동의 콘형 2점
약간 비동의 콘형 1점
모르겠음 어떤 성격유형도 점수를 얻지 않습니다
약간 동의 프로도형 1점
동의 프로도형 2점
매우 동의 프로도형 3점

2번 질문에서 검사자는 약간 비동의 선택지를 선택했으므로 콘형(C) 성격 유형 점수 1점을 얻게 됩니다.

3번 질문의 점수 배치는 아래 표와 같습니다.

선택지 성격 유형 점수
매우 비동의 무지형 3점
비동의 무지형 2점
약간 비동의 무지형 1점
모르겠음 어떤 성격유형도 점수를 얻지 않습니다
약간 동의 제이지형 1점
동의 제이지형 2점
매우 동의 제이지형 3점

3번 질문에서 검사자는 비동의 선택지를 선택했으므로 무지형(M) 성격 유형 점수 2점을 얻게 됩니다.

4번 질문의 점수 배치는 아래 표와 같습니다.

선택지 성격 유형 점수
매우 비동의 라이언형 3점
비동의 라이언형 2점
약간 비동의 라이언형 1점
모르겠음 어떤 성격유형도 점수를 얻지 않습니다
약간 동의 튜브형 1점
동의 튜브형 2점
매우 동의 튜브형 3점

4번 질문에서 검사자는 매우 동의 선택지를 선택했으므로 튜브형(T) 성격 유형 점수 3점을 얻게 됩니다.

5번 질문의 점수 배치는 아래 표와 같습니다.

선택지 성격 유형 점수
매우 비동의 네오형 3점
비동의 네오형 2점
약간 비동의 네오형 1점
모르겠음 어떤 성격유형도 점수를 얻지 않습니다
약간 동의 어피치형 1점
동의 어피치형 2점
매우 동의 어피치형 3점

5번 질문에서 검사자는 약간 동의 선택지를 선택했으므로 어피치형(A) 성격 유형 점수 1점을 얻게 됩니다.

1번부터 5번까지 질문의 성격 유형 점수를 합치면 아래 표와 같습니다.

지표 번호 성격 유형 점수 성격 유형 점수
1번 지표 라이언형(R) 0 튜브형(T) 3
2번 지표 콘형(C) 1 프로도형(F) 0
3번 지표 제이지형(J) 0 무지형(M) 2
4번 지표 어피치형(A) 1 네오형(N) 1

각 지표에서 더 점수가 높은 T,C,M이 성격 유형입니다.
하지만, 4번 지표는 1점으로 동일한 점수입니다. 따라서, 4번 지표의 성격 유형은 사전순으로 빠른 A입니다.

따라서 "TCMA"를 return 해야 합니다.

 

입출력 예 #2
1번부터 3번까지 질문의 성격 유형 점수를 합치면 아래 표와 같습니다.

지표 번호 성격 유형 점수 성격 유형 점수
1번 지표 라이언형(R) 6 튜브형(T) 1
2번 지표 콘형(C) 0 프로도형(F) 0
3번 지표 제이지형(J) 0 무지형(M) 0
4번 지표 어피치형(A) 0 네오형(N) 0

1번 지표는 튜브형(T)보다 라이언형(R)의 점수가 더 높습니다. 따라서 첫 번째 지표의 성격 유형은 R입니다.
하지만, 2, 3, 4번 지표는 모두 0점으로 동일한 점수입니다. 따라서 2, 3, 4번 지표의 성격 유형은 사전순으로 빠른 C, J, A입니다. 따라서 "RCJA"를 return 해야 합니다.

 

시작 코드

using System;

public class Solution {
    public string solution(string[] survey, int[] choices) {
        string answer = "";
        return answer;
    }
}

 

나의 풀이

public class Solution
{
    public string solution(string[] survey, int[] choices)
    {
        // mbti 검사
        // 4가지 지표, 각 2개의 유형 존재, 총 16개 성격유형 나올 수 있음
        // 검사 선택지 7개, 1가지 지표 : -(네오)3 ~ (어피치)3
        // 질문에 따라 같은 답변이 네오와 어피치형의 바뀔 수 있다
        // 유형점수가 같으면 사전 순으로 빠른 것
        // survey : 4가지 지표 2개 유형 문자열 배열, choices : 각 질문별 선택한 선택지 정수 배열
        // 검사자의 결과 지표번호 순서대로 리턴
        
        string answer = "";
        string[,] keys = new string[4, 2]
        {
            // 4가지 지표 2가지 유형 초기화
            {"R", "T" }, {"C", "F" }, {"J","M"}, {"A","N"}
        };
        int[,] values = new int[4, 2];

        for (int i = 0; i < survey.Length; i++)
        {
            string sSurvey = "";
            int choice = 0;

            if (choices[i] > 4) // 선택지가 동의쪽이면
            {
                sSurvey = survey[i][1].ToString(); //survey의 두번째 캐릭터를 sServey에 저장
                choice = (-1) * (4 - choices[i]); // choice에 양수(1,2,3 중 하나)를 저장
            }
            else // 비동의 쪽이면
            {
                sSurvey = survey[i][0].ToString(); // survey의 첫번째 캐릭터를 sServey에 저장
                choice = 4 - choices[i]; // choice에 양수(0,1,2,3 중 하나)를 저장
            }
            
            for (int j = 0; j < 4; j++) // 첫번째 인덱스
            {
                for (int k = 0; k < 2; k++) // 두번째 인덱스
                {
                    if (keys[j, k] == sSurvey) // key배열의 요소와 sServey에 들어온 캐릭터가 일치하면
                    {
                        values[j, k] += choice; // 해당 인덱스 value배열 위치에 choice값 추가 
                    }
                }
            }
        }

        for (int i = 0; i < 4; i++) // 주어진 점수를 가지고 mbti 구성하기
        {
            if (values[i, 0] >= values[i, 1]) // value배열의 첫번째 캐릭터의 값이 두번째보다 크면
                answer += keys[i, 0]; // 정답에 키값에 첫번째 캐릭터 추가
            else if (values[i, 0] < values[i, 1]) // 작으면
                answer += keys[i, 1]; // 두번째 캐릭터 추가
        }
        return answer;
    }
}

 

코드 분석

string타입의 배열 survey와 int타입의 배열 choices가 주어지며 코드가 시작됩니다. string타입의 2차원배열 keys를 [4, 2]로 길이를 설정해 만들고, 4가지 지표의 2가지 유형을 초기화 해줍니다. 그리고 int형 2차원 배열 values도 같은 크기로 만들어 줍니다. 이후 구성은 크게 두 개로 나뉩니다. 코드의 양이 많으니 끊어서 이야기 하겠습니다.

 

처음으로 나오는 구성은 큰 for문 안에 if else문과 이중for문 안에 if문입니다.

큰 for문은 i = 0부터 survey의 길이만큼 돌리며 string타입의 sSurvey와 int타입의 choice를 초기화 해줍니다. 이제 if else문에 들어가면 choices[i]가 4보다 크다면 sSurvey에 survey[i][1].ToString()을 넣어주고, choice에는 (-1) * (4 - choices[i])를 넣어줍니다. else문에서는 sSurvey에 survey[i][0]을, choices에는 4 - choices[i]를 넣어줍니다.

 

if else문을 마치고 빠져나오면 이중for문과 그 안에 if문을 만나게 됩니다. 이중for문은 바깥부터 j = 0부터 4까지, k = 0부터 2까지 돌리고 if문의 조건은 keys[j, k] == sSurvey입니다. 조건에 맞다면 values[j, k]에 choice를 더합니다.

 

이제 큰 for문을 빠져나오면 for문과 if else if문이 나옵니다. for문은 i = 0부터 4까지 돌며, if조건은values[i, 0] >= values[i, 1], else if 조건은 values[i, 0] < values[i, 1] 입니다. if가 충족한다면 answer에 keys[i, 0]을 더해주고 else if가 충족한다면 keys[i, 1]을 넣어줍니다.

 

모든 과정이 끝났다면 answer 값을 리턴하면서 코드는 종료됩니다.

 

풀이 설명

이번 문제는 매우 유명한 주제인 MBTI 문제입니다. 하지만, 우리가 흔히 아는 MBTI와 조금 다른데 카카오 캐릭터로 변형되었기 때문입니다. 문제에서 원하는 것은 MBTI검사를 했을 때, survey와 choices에 따른 검사결과를 도출하는 것입니다. survey는 해당 질문의 비동의와 동의 선택지를 순서대로 나타낸 것이고, choices는 말 그대로 고른 숫자를 의미합니다. 이제 코드로 풀이를 살펴보겠습니다.

 

처음에 2차원 배열 keys를 통해 4가지 지표와 2가지 유형을 모두 초기화 해줍니다. 그리고 계산할 때 사용할 2차원 배열 values도 같은 크기로 만들어 줍니다. 처음에 등장하는 큰 for문은 survey의 길이만큼 돌리며 choices의 동의와 비동의를 판단합니다.

survey와 choices의 길이는 같기 때문에 어떤 것으로 돌리던 상관없습니다. 만약 동의라면 survey의 두번째 캐릭터를 따로 저장하고 고른 번호에 따른 점수를 만들어 줍니다. 이후 j와 k로 돌리는 for문에서 keys를 이용해 values의 지정된 위치에 점수를 부여해줍니다.

 

큰 for문을 빠져나와 다시 for문과 if else if문을 만나면 모든 검사가 끝나고 나온 점수를 바탕으로 MBTI를 만들어 줍니다.

values의 배열 인덱스를 순서대로 검색하여 더 큰 수를 지닌 캐릭터를 answer에 부여해줍니다. 그렇게하면 고른 질문에 대한 답의 점수가 높은 것을 기준으로 MBTI가 완성됩니다.

 

<NEXT>

오늘 풀어본 문제는 2022 KAKAO TECH INTERNSHIP에 출제된 "성격 유형 검사하기" 일명, MBTI 문제였습니다. 설명도 상당히 길고, 예시마저 길어서 읽는 기술도 조금 필요해 보입니다. 확실히 카카오 문제이다 보니 이전에 풀었던 다른 문제들보다 복잡한 면이 있었던 것 같습니다. 다음에는 "바탕화면 정리" 문제를 다뤄보도록 하겠습니다. 감사합니다.