-링크
https://school.programmers.co.kr/learn/courses/30/lessons/118666?language=c
-문제 설명
나만의 카카오 성격 유형 검사지를 만들려고 합니다.
성격 유형 검사는 다음과 같은 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
1 매우 비동의 2 비동의 3 약간 비동의 4 모르겠음 5 약간 동의 6 동의 7 매우 동의
-입출력 예
["AN", "CF", "MJ", "RT", "NA"] | [5, 3, 2, 7, 5] | "TCMA" |
["TR", "RT", "TR"] | [7, 1, 3] | "RCJA" |
입출력 예 #2(예외 사항을 설명한 것 같아서 #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 해야 합니다.
-해설
문제가 일단 너무너무 길고 상세히 설명 되어있어서 덜컥 겁부터 나겠지만 차근차근 읽어보면 굉장히 간단한 쉬운 문제이다.
문제설명에서 보여준 "지표 번호성격 유형" 을 보면 4가지 유형 만 존재한다. 이 부분이 굉장히 쉽게 접근할 수 있는 시그널이다.
그냥 하드코딩으로 선언만 해도 풀리는 문제이기 때문이다.
나 같은 경우에는, CASE문과 For문을 사용하여 풀어보았는데 For문이 더 빠르게 작동해서 For문으로 제출했다.
우선 주어진 파라미터 중 survey배열의 길이와 choice 배열의 길이가 같기 때문에 survey의 첫 번째 배열의 응답 점수가 choice첫 번째 배열과 같다는 것을 알 수 있다.
survey배열은 문자열 일차원배열이라고 설명되어있지만 사실 이중배열이다. 근데 주어진 survey의 문자열은 항상 2자리인 것을 제약사항을 통해 알 수 있다.
첫 번째 배열을 예로 들면 배열의 첫 번째 문자는 ex)survey[i][0] 부정적인 응답에 점수를 부여 할 지표이고(매우비동의, 비동의, 약간비동의) 배열의 두 번째 문자는 긍정적인 응답에 점수를 부여 할 지표이다(매우동의, 동의, 약간동의).
이 응답의 기준은 가운데 값인 4를 기준으로 나뉘면서, 값이 4일 경우 어느 쪽에도 점수를 부여하지 않으므로 계산 할 필요가 없다는 것을 알 수 있다.
그래서 choices배열의 값이 4인 경우 그냥 continue를 통해 넘겨버리면 된다.
choices배열의 값은 점수의 지표로 사용할 수 있는데 각 응답에 따른 점수가 항상 고정적이기 때문에 score배열을 { 3 , 2, 1, 0, 1, 2, 3}으로 하드코딩하여 사용하면 된다.
여기서 주의 할 점은 choice의 응답이 곧 점수인데, choices는 1~7까지의 값이고 그 값에 따른 점수 값을 score배열에 저장 해 놓았기 때문에 choice값을 통해 바로 점수로 변환하려면 배열은 0번부터 시작이므로 choices의 값 -1 을 한 위치에 접근하여 점수를 도출 해 내면 된다.
그럼 여기서 어느 지표에 점수를 줘야 하는지만 남았는데, 지표값은 위에서 설명한 것과 같이 항상 2자리이며 배열의 첫 번째 값은 부정적인 응답에 점수를 부여 할 지표이고 배열의 두 번째 문자는 긍정적인 응답에 점수를 부여 할 지표이기 때문에,
이 말의 의미는 choices의 값이 4보다 크면 긍정적인 응답이므로 배열의 두번째 문자를 참조하여 지표 값에 score배열의 choice[i]-1번째 점수를 주면 되고, 4보다 작은 경우 배열의 첫 번째 지표값에 score배열의 choice[i]-1번째 점수를 주면 된다.
이제 점수를 다 환산 했으니 성격 유형을 도출하면 되는데, "지표 번호성격 유형"은 1~4번 지표로 나올 수 있는 값이 항상 동일하다.
때문에 "지표 번호성격 유형"을 1차원 배열에 선언하고, 어떤 지표값의 점수가 더 큰지는 for문을 돌려 지표 번호 성격 유형에 차례로 접근하되, for문의 증가식은 2씩 증가하게 하여 2개씩 차례로 비교하면 된다.
1차원 배열을 2차원 배열처럼 사용하면 더 쉽게 접근할 수 있다.
아래 C 풀이에서는 구조체와 enum을 사용한 방식과 case문을 사용한 방식 두 방법으로 풀어보았으니 참고하여 더 이해가 잘 가는 쪽으로 이해하면 도움이 될 것이다.(사실 구조체도 case문도 안쓰고 Java 풀이처럼 인덱스 참조해서 풀어도 됨 완성까지는 그게 훨씬 더 빠름;;ㅎ)
개인적으로 나는 구조체와 enum을 사용하는 방식이 가독성이 더 좋아서 현업에서 즐겨 사용하는 편이다.
-풀이(Java)
class Solution {
int[] indicatorsScore = {3, 2, 1, 0, 1, 2, 3};
char[] indicators = {'R','T','C','F','J','M','A','N'};
public String solution(String[] survey, int[] choices) {
String answer = "";
int[] myScore = new int[8];
char target;
for(int i = 0; i < survey.length; i++){
if(choices[i] == 4) continue;
target = choices[i] < 4 ? survey[i].charAt(0) : survey[i].charAt(1);
for(int j = 0; j < 8; j++){
if(target == indicators[j]){
myScore[j] += indicatorsScore[choices[i] -1];
break;
}
}
}
for(int i = 0; i < 8; i+=2){
answer += myScore[i] < myScore[i+1] ? indicators[i+1] : indicators[i];
}
return answer;
}
}
-풀이(C 구조체와 Enum사용)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
enum
{
R = 0, T, C, F, J, M, A, N, MAX_INDICATORS_INDEX,
};
typedef struct INDICATORS_CODE_
{
int index;
char code;
} INDICATORS_CODE;
INDICATORS_CODE INDICATORS_CODE_LIST[MAX_INDICATORS_INDEX] =
{
R, 'R',
T, 'T',
C, 'C',
F, 'F',
J, 'J',
M, 'M',
A, 'A',
N, 'N',
};
int indicators_score[7] = {3, 2, 1, 0, 1, 2, 3} ;
char* solution(const char* survey[], size_t survey_len, int choices[], size_t choices_len) {
char* answer = (char*)malloc(4+1);
int my_score[MAX_INDICATORS_INDEX] = {0,};
int choice = 0;
char category = '\0';
int pos = 0;
memset(answer, 0x00, 4+1);
for(int i = 0; i < choices_len; i++)
{
if((choice = choices[i]) == 4) continue;
category = choice < 4 ? survey[i][0] : survey[i][1];
for(int j = 0; j < MAX_INDICATORS_INDEX; j++){
if(INDICATORS_CODE_LIST[j].code == category){
my_score[INDICATORS_CODE_LIST[j].index]+=indicators_score[choice-1];
break;
}
}
}
for(int i = 0; i < 8; i+=2){
answer[pos++] = my_score[i] < my_score[i+1]?
INDICATORS_CODE_LIST[i+1].code : INDICATORS_CODE_LIST[i].code;
}
return answer;
}
-풀이(C Case문 사용)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int indicators_score[7] = {3, 2, 1, 0, 1, 2, 3} ;
char indicators[8] = {'R','T','C','F','J','M','A','N'};
char* solution(const char* survey[], size_t survey_len, int choices[], size_t choices_len) {
char* answer = (char*)malloc(4+1);
int my_score[8] = {0,};
int choice = 0;
char category = '\0';
int pos = 0;
memset(answer, 0x00, 4+1);
for(int i = 0; i < choices_len; i++)
{
if((choice = choices[i]) == 4) continue;
printf("choice[%d]\n",indicators_score[choice-1]);
category = choice < 4 ? survey[i][0] : survey[i][1];
switch(category)
{
case 'R':
my_score[0] += indicators_score[choice-1];
break;
case 'T':
my_score[1] += indicators_score[choice-1];
break;
case 'C':
my_score[2] += indicators_score[choice-1];
break;
case 'F':
my_score[3] += indicators_score[choice-1];
break;
case 'J':
my_score[4] += indicators_score[choice-1];
break;
case 'M':
my_score[5] += indicators_score[choice-1];
break;
case 'A':
my_score[6] += indicators_score[choice-1];
break;
case 'N':
my_score[7] += indicators_score[choice-1];
break;
}
}
for(int i = 0; i < 8; i+=2){
answer[pos++] = my_score[i] < my_score[i+1]?
indicators[i+1] : indicators[i];
}
return answer;
}
'Algorithm > Programmers' 카테고리의 다른 글
[프로그래머스] 코딩테스트 연습 - 숫자 짝궁(C) (1) | 2022.12.10 |
---|---|
[프로그래머스] 코딩테스트 연습 - 가장 가까운 같은 글자(Java ,C) (0) | 2022.12.08 |
[프로그래머스] 코딩테스트 연습 - 문자열 나누기(Java, C) (0) | 2022.12.04 |
[프로그래머스] 코딩테스트 연습 - 큰 수 만들기 (Java, C) (1) | 2022.12.03 |
[프로그래머스] 코딩테스트 연습 - 올바른 괄호 (Java, C) (0) | 2022.12.01 |