ABOUT ME

작은 디테일에 집착하는 개발자

Today
-
Yesterday
-
Total
-
  • [백준 알고리즘/Kotlin] 2839번 설탕 배달
    IT Study/백준 알고리즘 2023. 12. 21. 12:08
    728x90

     

    개념부터 체크하죠.

     

    1. 정수의 값은 깊은 복사를 할 필요가 없다?

    import java.io.BufferedReader
    import java.io.InputStream
    
    fun main() {
        val br = BufferedReader(InputStreamReader(System.`in`))
    
        val n = br.readLine().toInt()
        var remain = n
        
        br.close()
    }

     

    Kotlin에서는 정수를 복사할 경우,

    별도의 깊은 복사를 위한 함수를 사용하지 않고 단순히 다른 변수에 정수 값을 할당하면 깊은 복사가 이루어집니다.

     

     

    2. Kotlin의 나누기/나머지

    Java를 했을 때가 기억이 나는군요...

    정수끼리 나눈다면(나머지를 구한다면) 몫(나머지)은 정수가,

    나누는 값 중 실수가 존재한다면 실수가 그 몫으로 나올 수 있습니다.

     

    문제를 풀어봅시다.

     

     

    3. 문제 풀기

    정말 많이 고민해 봤는데요...

    처음부터 "3과 5라는 숫자로 만들 수 없는 숫자도 있지 않을까?"라는 생각으로 접근하니,

    정말 많이 틀리고 실수가 많았습니다. (생각 고착 금지)

     

    그래서 저는 결국 다음과 같이 풀이하였습니다.

    1 → -1
    2 → -1
    3 → 1
    4 → -1
    5 → 1
    6 → 2
    7 → -1
    8 → 2
    9 → 3
    10 → 2
    11 → 3
    12 → 4
    13 → 3
    14 → 4
    15 → 3
    16 → 4
    ...

     

    네, 규칙을 찾기 위해 23까지의 숫자들을 확인하며, 어떤 결과를 출력할지 들여다보았습니다.

    그러다 보니, 아래와 같은 규칙을 찾을 수 있었습니다.

    5로 나눈 숫자는 나머지가 0 ~ 4 사이의 수뿐이다.

    나머지가
    0일 경우, 나눈 몫 그대로 
    1일 경우, 나눈 몫 + 1
    2일 경우, 나눈 몫 + 2
    3일 경우, 나눈 몫 + 1
    4일 경우, 나눈 몫 + 2

     

     

    4. 최종 코드

    import java.io.BufferedReader
    import java.io.InputStreamReader
    
    fun main() {
        val br = BufferedReader(InputStreamReader(System.`in`))
    
    	val n = br.readLine().toInt()
        
        // bagCnt : 결과, 봉지의 수
        var bagCnt = 0
        var remain = n
        
        if(n == 3) {
            println(1)
            return
        }
        
        if (n == 4 || n == 7) {
            println(-1)
            return
        }
        
        // 5로 나누기
        bagCnt += remain / 5
        remain %= 5
        
        when (remain) {
            0 -> println(bagCnt)
            1 -> println(bagCnt + 1)
            2 -> println(bagCnt + 2)
            3 -> println(bagCnt + 1)
            4 -> println(bagCnt + 2)
            else -> println (-1)
        }
        
        br.close()
    }

     

    약 23까지의 수들을 확인하며, *3 이상의 수 중 3, 4, 7을 제외한 모든 숫자는 위의 조건을 만족하더군요.

    (1) 3은 5로 나누면 나머지가 3이지만, 위 조건을 만족하지 않기에 예외로 1을 반환하도록 설정
    (2) 4, 7은 3과 5로 만들 수 없는 숫자이기에 예외로 -1로 반환하도록 설정
    (3) 나머지 숫자들5 기준 나머지에 따라 규칙을 가지고 있다는 것을 확인 및 when 문 사용

    *문제의 n 조건 : 3 이상의 수

     

     

    5. 다른 풀이

    역시나 다른 사람들의 생각이 궁금합니다.

     

    5-1. 어느 iOS 개발자의 풀이

    import Foundation
    
    var sugar = Int(readLine()!)!
    
    var result = 0
    
    while sugar >= 0 {
        if sugar % 5 == 0 {
            result += sugar / 5
            sugar = 0
            break
        } else if sugar >= 3 {
            sugar -= 3
            result += 1
        } else {
            result = -1
            break
        }
    }
    
    print(result)

    저는 큰 수인 5부터 사용하는 것이 유용한 방법이라고 생각했는데요,

    위 코드를 작성하신 iOS 개발자분은 while문을 통해

    3을 빼며, 5의 배수가 될 수 있는지를 확인하는 방법을 새로운 접근법을 사용해 문제를 풀이하셨네요.

     

    5-2. GPT의 풀이

    fun minBagsOfSugar(N: Int): Int {
        // 5kg 봉지의 최대 사용 가능 개수 계산
        val maxBags5kg = N / 5
    
        // 5kg 봉지 개수를 최대부터 0까지 줄여가며 반복
        for (bags5kg in maxBags5kg downTo 0) {
            // 남은 무게 계산
            val remainingWeight = N - (bags5kg * 5)
            // 남은 무게가 3kg 봉지로 나누어 떨어지는 경우
            if (remainingWeight % 3 == 0) {
                val bags3kg = remainingWeight / 3
                // 5kg 봉지 개수와 3kg 봉지 개수의 합 반환
                return bags5kg + bags3kg
            }
        }
    
        // 정확한 무게를 맞출 수 없는 경우 -1 반환
        return -1
    }

    제가(사람이) 머릿속으로 생각하는 문제 풀이의 로직을 코드로 정리한 듯 보입니다.

    역시 사람이 접근하는 방법이 가장 최적화하는 방법인 것 같습니다. (생각을 코드로 정리하는 연습을 해봐야겠습니다.)

     

     

    제 힘으로 문제를 풀어내는 것만큼 다른 풀이의 코드들을 보는 것 또한 매우 중요하다고 느껴집니다.

    Kotlin... 부셔보겠습니다 화이팅 🔥

Designed by Tistory.