프로그래머스(Programmers) 성격 유형 검사하기 - javascript

ppmyor·2022년 8월 26일
0

Programmers-JavaScript

목록 보기
8/16
post-thumbnail

프로그래머스(Programmers) 성격 유형 검사하기

🙋‍♀️ 문제 정보

문제 설명

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

4개의 지표가 있으므로 성격 유형은 총 16(=2 x 2 x 2 x 2)가지가 나올 수 있습니다. 예를 들어, "RFMN"이나 "TCMA"와 같은 성격 유형이 있습니다.
검사지에는 총 n개의 질문이 있고, 각 질문에는 아래와 같은 7개의 선택지가 있습니다.

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

각 질문은 1가지 지표로 성격 유형 점수를 판단합니다.
예를 들어, 어떤 한 질문에서 4번 지표로 아래 표처럼 점수를 매길 수 있습니다.

이때 검사자가 질문에서 약간 동의 선택지를 선택할 경우 어피치형(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

입출력 예

입출력 예 설명

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

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

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

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

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

5번 질문에서 검사자는 약간 동의 선택지를 선택했으므로 어피치형(A) 성격 유형 점수 1점을 얻게 됩니다.
1번부터 5번까지 질문의 성격 유형 점수를 합치면 아래 표와 같습니다.

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

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

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

✨ 풀이

소스 코드

function solution(survey, choices) {
  const types = { R: 0, T: 0, C: 0, F: 0, J: 0, M: 0, A: 0, N: 0 };
  let answer = "";
  for (let i = 0; i < choices.length; i++) {
    const [leftType, rightType] = survey[i].split("");
    const result = Math.abs(choices[i] - 4);
    if (choices[i] < 4) {
      // 비동의 -> 왼쪽 요소
      types[leftType] += result;
    } else if (choices[i] > 4) {
      // 동의 -> 오른쪽 원소
      types[rightType] += result;
    }
  }
  const type = Object.keys(types);
  for (let i = 0; i < type.length; i += 2) {
    const leftType = types[type[i]];
    const rightType = types[type[i + 1]];
    if (leftType >= rightType) {
      // 같거나 클 때는 왼쪽 요소
      answer += type[i];
    } else {
      // 작은 때는 오른쪽 요소
      answer += type[i + 1];
    }
  }
  return answer;
}

결과

  • 성공

해결 방법

우선은 해당 성격 유형의 점수를 카운팅하기 위한 types라는 객체를 만들어줬다. 모든 성격 유형을 넣어서 0으로 초기화해준다.
이제 응답 결과를 토대로 왼쪽 원소에 점수를 더해줄 것인지 오른쪽 원소에 점수를 더해줄 것인지 판별해야한다. 이 문제의 조금 특이한 점은 응답 문항에서는 0점을 기준으로 동의와 비동의가 나뉘지 않고 4점을 기준으로 동의와 비동의가 나뉘기 때문에 4를 기준으로 크냐 작냐를 판별해주어야한다. 그러나 점수는 0점 기준으로 왼쪽에서 1, 2, 3점 오른쪽에서 1, 2, 3점이기 때문에 고민을 하다가 해당 점수에서 4를 빼주고 절대값으로 판별해주기로 했다. 결국 어떤 유형인지 판별한 후 해당 type 객체에 점수를 더해주는거다.
이렇게 객체가 완성되면 최종값을 해당 객체에서 얻어내는 작업을 해주어야한다. value 값은 어느게 점수가 높은지만 판별할 것이고 key 값을 최종적으로 return 해주어야 하기 때문에 반복문 속에서 조건문 처리를 해주는 식의 과정이 필요하다. 두개의 유형별로 4가지의 파트가 있기 때문에 객체의 index는 2씩 더해서 순회해준다.(두개의 유형이기 때문에 i와 i+1을 비교 하기 때문이다.)
참고로 애초에 객체를 정의할 때 사전 순서대로 정의를 하면 "점수의 값이 같을 시 사전 순으로 빠른 성격 유형을 검사자의 성격 유형이라고 판단" 요 문항을 신경쓰지 않아도 된다. 이렇게 정의하면 왼쪽이 무조건 사전순으로 빠르기 때문에 같을 때는 왼쪽입니다! 하고 처리해줄 수 있기 때문.
요렇게 answer에 더 높은 점수의 유형을 더해주어 return 해주면 끝!🔥
지문이 아주 길어서 그렇지 생각보다 어려운 문제는 아니다!

➕ 더 나아가서

객체를 순회하는 방법에는 두가지 방법이 있다.
위의 key 값을 뽑아 새로운 배열로 정의해준 다음 해당 배열로 돌면서 key와 value 값을 뽑아낼 수 있지만 ES6부터는 for...in 문으로도 객체가 순회 가능하다.

for (let key in obj) {
  const value = obj[key];
}

for...in 문으로 리팩토링하여 사용하는 방식이 조금 더 가독성을 올릴 수 있는 방법이기도 하겠다!

profile
유영하는 개발자

0개의 댓글