프로그래머스 코딩테스트 특강 1번 문제
in Algorithm on Programmers
문제
나만의 성격 유형 검사지를 만들려고 한다. 성격 유형 검사는 다음과 같은 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점을 획득.
- 모르겠음 선택지를 선택하면 점수 획득 X.
검사 결과는 모든 질문의 성격 유형 점수를 더하여 각 지표에서 더 높은 점수를 받은 성격 유형이 검사자의 성격 유형이라고 판단한다. 단, 하나의 지표에서 각 성격 유형 점수가 같으면, 두 성격 유형 중 사전 순으로 빠른 성격 유형을 검사자의 성격 유형이라고 판단한다.
질문마다 판단하는 지표를 담은 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번 질문의 동의 관련 선택지를 선택하면 받는 성격 유형을 의미합니다.
- 예) [“AN”, “CF”, “MJ”, “RT”, “NA”]
- choices의 길이 = survey의 길이
- choices[i]는 검사자가 선택한 i+1번째 질문의 선택지를 의미.
- 1 ≤ choices의 원소 ≤ 7
- 매우 비동의, 비동의, 약간 비동의, 모르겠음, 약간 동의, 동의, 매우 동의 순으로 1 ~ 7
- 예) [5, 3, 2, 7, 5]
출력
검사자의 성격 유형 검사 결과 4자리 문자 (예: “TCMA”)
풀이 전 주저리주저리…
이런 문제, 상당히 혀가 길다. 하지만, 자세히 잘 읽어보면 손쉽게 생각해 볼 수 있는 문제다. 그러나 본인은 이 문제를 실전 코딩 테스트하면서 접해보았고, 설명이 너무 길어서 도저히 문제 1번이라고 납득하기 어려워서 다른 문제 먼저 도전했다가 패가망신을 당한 케이스다. 당시 주어진 시간은 2시간에 이와 같은 문제가 4문제 였다. 다른 문제 먼저 빨리 풀고 보면 된다란 전략을 짰지만, 오판이었다. 왜 오판이었는지 풀이해본다.
풀이
문제는 다음과 같이 요약할 수 있다.
- 우선 아래와 같은 지표가 있다.
- 1번 지표: 라이언형(R), 튜브형(T)
- 2번 지표: 콘형(C), 프로도형(F)
- 3번 지표: 제이지형(J), 무지형(M)
- 4번 지표: 어피치형(A), 네오형(N)
- 설문지엔 지표순서를 보여준다.
- 1번 지표인 RT가 될 수도 있고 TR이 될 수 있다.
- 설문선택은 1에서 7까지 있고, 1~3은 첫번째 지표가 먹고 5~7은 두번째 지표가 먹는다. 중립인 4에서 멀어질 수록 점수가 세다.
- 모든 설문이 완료 후 각 지표별 점수 큰 거, 같으면 맨 앞에 있는 거로 지표가 정해져서 출력된다.
위 요약 대로 입력인 survey와 choices를 받은 후 로직을 처리하면 다음과 같다.
- 지표 점수 저장하는 공간을 마련한다. 그리고 각 지표별 위치에 대한 값을 알아둔다.
{R,T} => {0,1}
{C,F} => {2,3}
{J,M} => {4,5}
{A,N} => {6,7}// 01 // 0RT // 1CF // 2JM // 3AN int[][] scores = new int[4][2]; public int findScorePlace(char type){ return switch (type) { case 'R' -> 0; case 'T' -> 1; case 'C' -> 2; case 'F' -> 3; case 'J' -> 4; case 'M' -> 5; case 'A' -> 6; case 'N' -> 7; default -> -1; }; } public String findTypePlace(int place){ return switch (place) { case 0 -> "R"; case 1 -> "T"; case 2 -> "C"; case 3 -> "F"; case 4 -> "J"; case 5 -> "M"; case 6 -> "A"; case 7 -> "N"; default -> ""; }; }
- 설문과 선택에 따른 점수를 합산한다.
첫번째 지표 a / 두번째 지표 b =>
1 = a3 / 2 = a2 / 3 = a1 / 4 = X / 5 = b1 / 6 = b2 / 7 = b3
(a3는 a에 3을 더한다를 의미)for(int i = 0; i < survey.length; i++){ String types = survey[i]; char firstType = types.toCharArray()[0]; char secondType = types.toCharArray()[1]; int choice = choices[i]; int point = choice - 4; if(point < 0){ point = -point; int placeIndex = findScorePlace(firstType); scores[placeIndex / 2][placeIndex % 2] += point; } else if(point > 0){ int placeIndex = findScorePlace(secondType); scores[placeIndex / 2][placeIndex % 2] += point; }
- 합산 완료 후 각 지표별 점수 비교하여 총 4가지의 지표를 출력한다.
for(int i = 0; i < 4; i++){ if(scores[i][0] < scores[i][1]){ answer.append(findTypePlace(2 * i + 1)); } else{ answer.append(findTypePlace(2 * i)); } } return answer.toString();
결론
결코 어려운 문제는 아니었다. 그러나, 실전에서의 시험을 대하는 전략에 관해선 문제가 길어도 한 번쯔음 진중히 읽고 생각하는 전략을 취하는 것이 좋은 전략이라 할 수 있다.
겁나 많이 긴 지문이라도, 총 2~3시간 내 여러 문제 풀어야 하는 짧은 시간이라도, 최대 3~5분 정도는 문제를 한번 깊숙히 보는 게 적합한 전략이라 할 수 있다.
3~5분 동안 문제를 읽으며 해결할 수 있는 각을 찾는게 최우선이며, 정녕 각이 잘 안보인다 해도, 다음 문제로 넘어가 차분히 머리를 식힌 다음 다시 한번 분석을 해야한다.
=> 단기간 내 철저한 문제 분석 필요!