[프로그래머스] 모의고사완전탐색

neoneoneo·2024년 3월 11일
0

kotlin

목록 보기
25/49

문제

수포자는 수학을 포기한 사람의 준말입니다. 수포자 삼인방은 모의고사에 수학 문제를 전부 찍으려 합니다. 수포자는 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 함수를 작성해주세요.

나의 풀이

첫 번째 시도

class Solution {
    fun solution(answers: IntArray): IntArray {
        var answer = intArrayOf()
        var supo1 = intArrayOf(1, 2, 3, 4, 5) //5
        var supo2 = intArrayOf(2, 1, 2, 3, 2, 4, 2, 5) //8
        var supo3 = intArrayOf(3, 3, 1, 1, 2, 2, 4, 4, 5, 5) //10
        var supoRank = IntArray(3)
        var duSupo1 = supo1.copyOf()
        var duSupo2 = supo2.copyOf()
        var duSupo3 = supo3.copyOf()           
        //각 수포자 별 배열 크기와 answers 크기 간 싱크 맞추기
        when {
            (answers.size > duSupo1.size) -> {
                val repetition = answers.size / supo1.size + 1
                duSupo1 = IntArray(supo1.size * repetition) {supo1 [it % supo1.size] }
            }
            (answers.size > duSupo2.size) -> {
                val repetition = answers.size / supo2.size + 1
                duSupo2 = IntArray(supo2.size * repetition) {supo2 [it % supo2.size] }
                duSupo2.forEach {
                    println(it)
                }
            }
            (answers.size > duSupo3.size) -> {
                val repetition = answers.size / supo3.size + 1
                duSupo3 = IntArray(supo3.size * repetition) {supo3 [it % supo3.size] }
            }
        }
        //처리가 다 된 duSupo1,2,3을 가지고... answers를 돌면서 답이 맞는지 체크하면서 ++
        for (i in 0 .. answers.size-1) {
            if (duSupo1.size >= i) {
                if (answers[i].equals(duSupo1[i])) { 
                        supoRank[0]++
                        println("duSupo1랑 답 일치! 랭크는 ${supoRank[0]}")
                }
            }
        }
        for (i in 0 .. answers.size-1) {
            if (i <= duSupo2.size-1) {
                if (answers[i].equals(duSupo2[i])) { 
                        supoRank[1]++
                        println("duSupo2랑 답 일치! 랭크는 ${supoRank[1]}")
                }
            }
        }
        for (i in 0 .. answers.size-1) {
            if (i <= duSupo3.size-1) {
                if (answers[i].equals(duSupo3[i])) { 
                        supoRank[2]++
                        println("duSupo3랑 답 일치! 랭크는 ${supoRank[2]}")
                }
            }
        }
        var maxNumber = supoRank.maxOrNull()!!
        var maxIndices = supoRank.indices.filter {supoRank[it] == maxNumber}
        maxIndices.forEach {
            if(it == 0) {
                answer += 1
            }
            else if(it == 1) {
                answer += 2
            }
            else {
                answer += 3
            }
        } 
        return answer
    }
}
  • 코드가 좀 긴데, 파트를 나누자면 아래와 같다.
    • 수포자별 사이즈와 정답 배열의 사이즈를 비교해서 수포자별 답안 배열을 늘리는 작업 파트
    • 정답 체크 파트
    • 가장 큰 점수를 받은 학생들을 선별 파트
    • 최종 결과 변수에 저장 파트
  • 여러 테스트 케이스를 통과하기는 하나.. 최종적으로는 채점을 하면 정답률이 50%가 되지 못했다. 문제점이 무엇인지 고민을 2시간을 한 것 같은데, 결국 내 눈에는 보이지 않아 코드를 초기화하고 다시 짰다.
  • 또한 처음에 문제를 잘 못 읽어서 수포자 3명을 순위별로 리턴해줘야 하는 줄 알고 시간을 버리기도 했다.
  • 무튼간에, 코드를 이렇게 짜니 너무 많은 변수들을 선언해서 사용했고 코드를 작성하면서도 헷갈려서 시간이 더 오래 걸렸다.

두 번째 시도

class Solution {
    fun solution(answers: IntArray): IntArray {
        var answer = intArrayOf()
        val supo1 = intArrayOf(1, 2, 3, 4, 5)
        val supo2 = intArrayOf(2, 1, 2, 3, 2, 4, 2, 5)
        val supo3 = intArrayOf(3, 3, 1, 1, 2, 2, 4, 4, 5, 5)       
        val supoRank = intArrayOf(0, 0, 0)
        for (i in answers.indices) {
            if (answers[i] == supo1[i % supo1.size]) supoRank[0]++
            if (answers[i] == supo2[i % supo2.size]) supoRank[1]++
            if (answers[i] == supo3[i % supo3.size]) supoRank[2]++
        }
        val maxScore = supoRank.maxOrNull()
        var answerList = mutableListOf<Int>()
        for (i in supoRank.indices) {
            if (supoRank[i] == maxScore) answerList.add(i + 1)
        }
        return answerList.toIntArray()
    }
  • 사실 이 코드는 GPT의 도움을 받은 것이다.. 특히 패턴이 반복되는 부분에 대한 도움을 많이 받았다.
  • 첫 번째 for 문이 수포자별 패턴에 따라 일정 주기로 반복되는 값에 대해 정답과 비교하는 파트이다.
    • supo1[i % supo1.size] : % 처리 하여 나머지 값의 인덱스에 접근하는데, 만약 수포자1의 경우 최초 크기가 5이기 때문에 answers에서 6번째 값과 비교하려면 i(6) % 5 하여 1번째 인덱스의 값을 가져올 수 있도록 했다.
  • 두 번째 for문은 수포자들 중에 가장 점수가 큰 수포자를 찾아 결과 리스트에 데이터를 저장하는 파트이다.

배운점

  • 이 문제는 내가 장장 3시간이나 삽질을 하게 만든 문제이다. 문제를 봤을 때 어떻게 풀어야 할 지 감이 안와서 일단 코드를 막 써보자는 마음으로 작성했었는데, 최초에 수포자 패턴을 복제하는 방식부터 좀 힘겹게? 진행이 되었었다. 이 과정에서 자꾸 out of index가 발생하여 그 부분을 처리하는 데에 애를 먹었다. 그 이후 정답과 비교하는 과정에서 아마 오답이 발생하는 것 같은데... 정말 테스트케이스를 한 10개는 넘게 추가해서 테스트를 했지만 다 통과했어서 대체 어느 케이스에서 오답이 발생하는 건지는 찾이 못 했다. 그렇기에 코드의 어떤 부분이 문제인지도 정확하게 파악은 못 했다(그래서 질문하기에다가 고수분들에게 문의글을 써놓았다.)
  • 패턴대로 데이터를 저장하거나 불러와서 쓸 일이 있을 때에 %를 사용할 수 있다는 점에 대해서는 확실히 배운 것 같다.

[TIL-240311]

0개의 댓글