본문 바로가기
알고리즘 문제 풀이/완전탐색

프로그래머스 - 모의고사

by 가나무마 2021. 8. 24.
728x90

본 알고리즘 풀이는 Routine Study에서 진행하고 있습니다.
저를 포함한 구성원이 대부분 초보이므로, 원하시는분은 언제라도 들어오셔도 좋습니다.

문의는 댓글 바람.

팀 알고리즘 레포지토리 주소

 

GitHub - ROUTINE-STUDY/Algorithm: 초보 알고리즘 스터디 / 누구나 참여 가능

초보 알고리즘 스터디 / 누구나 참여 가능 :runner:. Contribute to ROUTINE-STUDY/Algorithm development by creating an account on GitHub.

github.com

문제 출처

 

코딩테스트 연습 - 모의고사

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

programmers.co.kr

[문제 설명]

문제를 찍는 패턴이 3가지 있을 때, 가장 많은 문제를 맞춘 패턴을 고르시오.

[처음 생각한 접근 방법]

보니까 전에 풀었던 문제다. 그래도 걍 풀기로 했다. 꽤 옛날에 푼 문제라 코드가 어떻게 바꼈나 볼 수도 있으니까.

첫번째 방법

각각의 패턴을 최소한의 길이로 저장한 다음에 마지막 패턴에 도달하면 패턴의 처음으로 돌아가는 방법이다.

근데 이건 전에 풀었던 방법과 비슷해보였고 다른 방법이 생각 나서 관뒀다.

두번째 방법)

각각 패턴을 최소 공배수만큼 저장하기.

물론 패턴의 최소 공배수가 너무 크다면 메모리 낭비가 심하겠지만,

이번 문제의 패턴은 (1,2,3,4,5) 5주기, (2,1,2,3,2,4,2,5) 8주기, (3,3,1,1,2,2,4,4,5,5) 10주기이므로 최소 공배수가 40밖에 안된다.

int형이 차지하는 공간이 4byte이고 40개씩 3개의 배열이 만들어지니까 480byte만 사용하므로 문제가 없다고 생각했다.

이 문제도 첫번째 방법처럼 패턴의 마지막으로 가면 처음 패턴으로 다시 돌아가야 한다.

이게 좀 아쉽긴 하다.

import java.util.ArrayList;
import java.util.List;

class Solution {
    public int[] solution(int[] answers) {
        // 제일 많이 맞은 문제들을 담을 배열
        List<Integer> list = new ArrayList<>();    
        // 각 패턴의 맞은 갯수를 담을 배열
        int[] correctNum = new int[3];        
        // 문제를 풀 패턴
        int[][] pattern = new int[][]{        // 문제를 푸는 패턴
                {1,2,3,4,5,1,2,3,4,5,1,2,3,4,5,1,2,3,4,5,1,2,3,4,5,1,2,3,4,5,1,2,3,4,5,1,2,3,4,5},
                {2,1,2,3,2,4,2,5,2,1,2,3,2,4,2,5,2,1,2,3,2,4,2,5,2,1,2,3,2,4,2,5,2,1,2,3,2,4,2,5},
                {3,3,1,1,2,2,4,4,5,5,3,3,1,1,2,2,4,4,5,5,3,3,1,1,2,2,4,4,5,5,3,3,1,1,2,2,4,4,5,5}
        };

        // 패턴의 인덱스
        int j = 0;    
        // 패턴별로 맞은 갯수를 구하는 반복문
        for (int i = 0; i < answers.length; i++) {
            // 패턴의 끝에 도달하면 처음 인덱스로 돌아감.
            if (j > 39) j = (j%39) - 1;

            if (answers[i] == pattern[0][j]) correctNum[0]++;
            if (answers[i] == pattern[1][j]) correctNum[1]++;
            if (answers[i] == pattern[2][j]) correctNum[2]++;
            j++;
        }

        // 최댓값을 담을 변수 max
        int max = correctNum[0];
        // 패턴별로 맞은 갯수에서 최댓값 구하기
        for (int i = 1; i < correctNum.length; i++) {
            if (correctNum[i] > max) max = correctNum[i];
        }
        // 제일 많이 맞춘 패턴들 list에 담기
        for (int i = 0; i < correctNum.length; i++) {
            if (correctNum[i] == max) list.add(i);
        }

        int[] answer = new int[list.size()];
        // 배열로 변환. (인덱스의 값은 0부터이므로 +1을 해줌)
        for (int i = 0; i < list.size(); i++) answer[i] = list.get(i) + 1;

        return answer;
    }
}

[리팩토링]

import java.util.ArrayList;
import java.util.List;

class Solution {
    public int[] solution(int[] answers) {
        int answer[];
        int[] correctNum = new int[3];
        int[][] pattern = new int[][]{
                {1,2,3,4,5,1,2,3,4,5,1,2,3,4,5,1,2,3,4,5,1,2,3,4,5,1,2,3,4,5,1,2,3,4,5,1,2,3,4,5},
                {2,1,2,3,2,4,2,5,2,1,2,3,2,4,2,5,2,1,2,3,2,4,2,5,2,1,2,3,2,4,2,5,2,1,2,3,2,4,2,5},
                {3,3,1,1,2,2,4,4,5,5,3,3,1,1,2,2,4,4,5,5,3,3,1,1,2,2,4,4,5,5,3,3,1,1,2,2,4,4,5,5}
        };
        List<Integer> list = new ArrayList<>();

        for (int i = 0; i < answers.length; i++) {
            int patternIdx = i%pattern[0].length;
            if (answers[i] == pattern[0][patternIdx]) correctNum[0]++;
            if (answers[i] == pattern[1][patternIdx]) correctNum[1]++;
            if (answers[i] == pattern[2][patternIdx]) correctNum[2]++;
        }

        int max = Math.max(correctNum[0],Math.max(correctNum[1],correctNum[2]));
        for (int i = 0; i < correctNum.length; i++)
            if (correctNum[i] == max) list.add(i);

        answer = new int[list.size()];
        for (int i = 0; i < list.size(); i++)
            answer[i] = list.get(i) + 1;

        return answer;
    }
}

[옛날 내 답안]

class Solution {
    public int[] solution(int[] answers) {
        int[] correctCount = new int[3];
        int max = correctCount[0];
        int maxCount = 0;                //많이 맞춘 회원 수
        int[] answer;
        int[] aAnswers = new int[answers.length];
        int[] bAnswers = new int[answers.length];
        int[] cAnswers = new int[answers.length];

        for(int i=0; i<answers.length; i++) {
            aAnswers[i] = i%5+1;
            if(aAnswers[i]==answers[i]) {
                correctCount[0]++;    
            }
        }

        for(int i=0; i<answers.length; i++) {
            if(i%2==0) {
                bAnswers[i] = 2;
            }else if(i%8==1) {
                bAnswers[i] = 1;
            }else if(i%8==3) {
                bAnswers[i] = 3;
            }else if(i%8==5) {
                bAnswers[i] = 4;
            }else if(i%8==7) {
                bAnswers[i] = 5;
            }

            if(bAnswers[i]==answers[i]) {
                correctCount[1]++;
            }
        }

        for(int i=0; i<answers.length; i++) {
            if(i%10<=1) {
                cAnswers[i] = 3;
            }else if(i%10<=3 && i%10>=2) {
                cAnswers[i] = 1;
            }else if(i%10>=4 && i%10<=5) {
                cAnswers[i] = 2;
            }else if(i%10>=6 && i%10<=7) {
                cAnswers[i] = 4;
            }else if(i%10>=8 && i%10<=9) {
                cAnswers[i] = 5;
            }

            if(cAnswers[i]==answers[i]) {
                correctCount[2]++;
            }

        }
        for(int i=0; i<correctCount.length; i++) {
            if(max<correctCount[i]) {
                max = correctCount[i];
            }
        }

        for(int i=0; i<correctCount.length; i++) {
            if(max==correctCount[i]) {
                maxCount++;
            }
        }

        answer = new int[maxCount];

        int answerIndex = 0;
        for(int i=0; i<correctCount.length; i++) {
            if(max==correctCount[i]) {
                answer[answerIndex++] = i+1; 
            }
        }
        return answer;
    }
}

옛날에 깔끔하게 풀었을 줄 알았는데 아주 코드가 심각하다.

긍정적으로 생각하면 코드가 많이 깔끔해지긴 했다. 2차원배열도 안썼었고, 중복되는 코드도 많고 그냥 말그대로 풀기 위해 작성한 알고리즘 같다.

이번에 문제를 풀 때 풀기 전에 노트에 정리하고 풀었는데 그게 많이 도움이 됐다.

앞으로도 먼저 설계를 하고 코드를 짜는 버릇을 가져야겠다.

728x90
반응형

'알고리즘 문제 풀이 > 완전탐색' 카테고리의 다른 글

백준 - 암호 만들기  (0) 2021.12.12
백준 - 한수  (0) 2021.12.12
프로그래머스 - 소수 만들기  (0) 2021.11.25
프로그래머스 - 모의고사  (0) 2021.11.12
2309번 : 일곱난쟁이  (1) 2021.10.26