알고리즘 코딩테스트

프로그래머스 Java Level 1) 모의고사

탄력이 2021. 6. 18. 10:32
  • 모의고사

문제 설명

수포자는 수학을 포기한 사람의 준말입니다. 수포자 삼인방은 모의고사에 수학 문제를 전부 찍으려 합니다. 수포자는 1번 문제부터 마지막 문제까지 다음과 같이 찍습니다.

1번 수포자가 찍는 방식: 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, ...
2번 수포자가 찍는 방식: 2, 1, 2, 3, 2, 4, 2, 5, 2, 1, 2, 3, 2, 4, 2, 5, ...
3번 수포자가 찍는 방식: 3, 3, 1, 1, 2, 2, 4, 4, 5, 5, 3, 3, 1, 1, 2, 2, 4, 4, 5, 5, ...

1번 문제부터 마지막 문제까지의 정답이 순서대로 들은 배열 answers가 주어졌을 때, 가장 많은 문제를 맞힌 사람이 누구인지 배열에 담아 return 하도록 solution 함수를 작성해주세요.

제한 조건

  • 시험은 최대 10,000 문제로 구성되어있습니다.
  • 문제의 정답은 1, 2, 3, 4, 5중 하나입니다.
  • 가장 높은 점수를 받은 사람이 여럿일 경우, return하는 값을 오름차순 정렬해주세요.

입출력 예

answersreturn

[1,2,3,4,5] [1]
[1,3,2,4,2] [1,2,3]

입출력 예 설명

입출력 예 #1

  • 수포자 1은 모든 문제를 맞혔습니다.
  • 수포자 2는 모든 문제를 틀렸습니다.
  • 수포자 3은 모든 문제를 틀렸습니다.

따라서 가장 문제를 많이 맞힌 사람은 수포자 1입니다.

입출력 예 #2

  • 모든 사람이 2문제씩을 맞췄습니다.

문제풀이

조건 몇가지를 살펴보자.

1. 찍는 방식이 수포자1,2,3 각자 정해져있다.

2. 문제 갯수는 매개변수로 정해진다.

3. 찍는 방식과 문제 갯수는 배열의 크기가 다르다.

4. 출력 방식은 몇번 수포자가 1등인지 출력한다. 동점자가 있으면 동점자도 출력한다. (오름차순으로)

class Solution {
    public int[] solution(int[] answers) {
    	 //수포자 1,2,3 이 문제를 찍는 방식
         int[] ex1 = {1, 2, 3, 4, 5};
    	 int[] ex2 = {2, 1, 2, 3, 2, 4, 2, 5};
    	 int[] ex3 = {3, 3, 1, 1, 2, 2, 4, 4, 5, 5};
         
         // 출제 문제 갯수에 맞는 수포자들의 답안지(배열) 생성
    	 int[] supo1 = new int[answers.length];
    	 int[] supo2 = new int[answers.length];
    	 int[] supo3 = new int[answers.length];
    	 int k = 0;
         
         // 수포자들의 답안지에 각자의 문제 찍는 방식으로 답안지 내용을 채워준다.
    	 for(int i=0; i<answers.length;i++) {
    		 k = i%ex1.length;
    		 supo1[i]=ex1[k];
    	 }
    	 for(int i=0; i<answers.length;i++) {
    		 k = i%ex2.length;
    		 supo2[i]=ex2[k];
    	 }
    	 for(int i=0; i<answers.length;i++) {
    		 k = i%ex3.length;
    		 supo3[i]=ex3[k];
    	 }
         
         //맞은 답의 갯수를 세주는 변수 선언
         int count1 =0;
         int count2 =0;
         int count3 =0;
         
         // 맞은 답 있을 때마다 1씩 추가
         for(int i=0; i<answers.length;i++) {
        	 if(answers[i] == supo1[i]) {
        		 count1++;
        	 }
        	 if(answers[i] == supo2[i]) {
        		 count2++;
        	 }
        	 if(answers[i] == supo3[i]) {
        		 count3++;
        	 }
         }
         
        int[] answer;
        
        // count를 비교해 가장 많이 맞은 사람만 출력되도록 if문 돌림
         if(count1>count2) {
        	 if(count1>count3) {
        		 answer = new int[1];
        		 answer[0] = 1;
        	 } else if(count1==count3) {
        		 answer = new int[2];
        		 answer[0] =1;
        		 answer[1] =3;
        	 } else {
        		 answer = new int[1];
        		 answer[0] = 3;
        	 }
         } else if(count1==count2) {
        	 if(count1>count3) {
        		 answer = new int[2];
        		 answer[0] =1;
        		 answer[1] =2;
        	 } else if(count1==count3) {
        		 answer = new int[3];
        		 answer[0] =1;
        		 answer[1] =2;
        		 answer[2] =3;
        	 } else {
        		 answer = new int[1];
        		 answer[0] = 3;
        	 }
         } else {
        	 if(count2>count3) {
        		 answer = new int[1];
        		 answer[0] = 2;
        	 } else if(count2==count3) {
        		 answer = new int[2];
        		 answer[0] =2;
        		 answer[1] =3;
        	 } else {
        		 answer = new int[1];
        		 answer[0] = 3;
        	 }
         }
        
        return answer;
    }
}

풀이 절차.

1. 문제 갯수에 맞는 수포자들의 답안지를 작성한다.

2. 비교해서 맞은 갯수를 센다.

3. 맞은 갯수를 비교해 1등이 누구인지 , 동점자가 있는지 알아내 출력한다.

 

풀이절차를 이렇게 쓰면 너무도 쉬워보인다. 그런데 그걸 자바언어로 하는게 참으로 어려운 것 같다.

더 깔끔하게 다듬어서 코드를 올릴 수도 있겠지만, 어떻게 알고리즘을 떠올렸는지 보려면 바로 답을 맞춘 코드가 더 좋은 것 같다.

 

필자는 수포자들의 찍는 방식과 문제 갯수가 다르다는 조건이 힘들었다.

찍는 방식을 반복해서 다른 크기의 배열에 넣어야하니까.

계속 고민하다가 나머지를 생각해냈다. 찍는방식의 배열 크기만큼 나누면 반복 되니까.

 

그 이후는 잘 풀렸던 것 같다.

그러나 출력방식에 맞게 정렬, 동점자 출력이 어려웠지만 많은 if문으로 떼웠다.

다음부턴 다른 함수를 써서 저 부분을 줄여볼 수 있겠다.