안녕하세요. 회사와 함께 성장하고 싶은 KOSE입니다.

이번 포스팅은 백준 문자열 문제 - 디지털시계 코틀린 풀이를 진행하고자 합니다.

 

문제 출처: https://www.acmicpc.net/problem/1942

 

1942번: 디지털시계

디지털시계는 일반적으로 시각을 “hh:mm:ss”의 형태로 표현한다. hh는 00 이상 23 이하의 값을, mm과 ss는 00 이상 59 이하의 값을 가질 수 있다. 이러한 형태의 시각에서 콜론(“:”)을 제거하면 “hhm

www.acmicpc.net

 

1. 풀이 소스

 

import java.io.*

const val LAST_TIME_SECONDS_OF_DAY: Int = 3600 * 23 + 59 * 60 + 59
const val START_TIME_SECONDS_OF_DAY: Int = 0

fun main() = BufferedReader(InputStreamReader(System.`in`)).use {

    val sb = StringBuilder()
    repeat(3) {
        val (startTimeSeconds, endTimeSeconds) = readlnOrNull()!!.split(" ").map { it.toTimeSeconds() }

        val result = when {
            startTimeSeconds <= endTimeSeconds -> calculateMultipleOfThreeBetween(startTimeSeconds, endTimeSeconds)
            else -> calculateMultipleOfThreeBetween(startTimeSeconds, LAST_TIME_SECONDS_OF_DAY) +
                    calculateMultipleOfThreeBetween(START_TIME_SECONDS_OF_DAY, endTimeSeconds)
        }

        sb.append(result).append("\n")
    }

    println(sb)
}

private fun calculateMultipleOfThreeBetween(startTimeSeconds: Int, endTimeSeconds: Int): Int {
    var targetTimeSeconds = startTimeSeconds
    var result = 0

    while (targetTimeSeconds <= endTimeSeconds) {

        val longOfTime = targetTimeSeconds.transformTimeToLiteralNumber()
        if (longOfTime % 3 == 0) {
            result++
        }

        if (targetTimeSeconds == LAST_TIME_SECONDS_OF_DAY) {
            break
        }

        targetTimeSeconds++
    }

    return result
}

fun Int.transformTimeToLiteralNumber(): Int {
    val hours = this / 3600
    val minutes = (this % 3600) / 60
    val seconds = this % 60
    return hours * 10000 + minutes * 100 + seconds
}

fun String.toTimeSeconds(): Int {
    val (hours, minutes, seconds) = this.split(":").map { it.toInt() }
    return hours * 3600 + minutes * 60 + seconds
}

 

 

2. 풀이 중점사항

 

- 시작 시간과 종료 시간의 대수 비교

시작 시간이 종료 시간보다 클 경우 (ex: 23:59:59, 00:00:01) 시작 시간 ~ 23:59:59, 00:00:00 ~ 종료 시간 으로 구획을 나눠서 진행해야합니다.

만약, 시작 시간보다 종료 시간이 클 경우는 시작 시간 <= 종료 시간이 될 때 까지 순회하면 됩니다.

val result = when {
    startTimeSeconds <= endTimeSeconds -> calculateMultipleOfThreeBetween(startTimeSeconds, endTimeSeconds)
    else -> calculateMultipleOfThreeBetween(startTimeSeconds, LAST_TIME_SECONDS_OF_DAY) +
            calculateMultipleOfThreeBetween(START_TIME_SECONDS_OF_DAY, endTimeSeconds)
}

 

-시작 시간과 종료 시간 사이의 범위구하기

시작 시간과 종료 시간은 초(단위)로 바꿔서 구할 수 있습니다. 

예를 들어 00:00:00 ~ 00:01:03이 있다면 이를 초(단위)로 표현하면 0 ~ 63이 됩니다.

 

fun String.toTimeSeconds(): Int {
    val (hours, minutes, seconds) = this.split(":").map { it.toInt() }
    return hours * 3600 + minutes * 60 + seconds
}

 

0 ~ 63까지 순회하되, 순회한 숫자를 시간 문자 그대로의 숫자로 바꿔주어야 합니다.

0 -> 00:00:00 -> 0

63 -> 00:01:03 -> 103

이를 위해 시간, 분, 초로 바꾼 후 각 단위에 맞게 10의 제곱승을 곱해줄 수 있습니다.

 

fun Int.transformTimeToLiteralNumber(): Int {
    val hours = this / 3600
    val minutes = (this % 3600) / 60
    val seconds = this % 60
    return hours * 10000 + minutes * 100 + seconds
}

 

이렇게 구한 문자 그대로의 시간을 표현하는 정수를 3의 배수인지 파악하고 결과를 리턴하면 결과를 얻을 수 있습니다!

private fun calculateMultipleOfThreeBetween(startTimeSeconds: Int, endTimeSeconds: Int): Int {
    var targetTimeSeconds = startTimeSeconds
    var result = 0

    while (targetTimeSeconds <= endTimeSeconds) {

        val longOfTime = targetTimeSeconds.transformTimeToLiteralNumber()
        if (longOfTime % 3 == 0) {
            result++
        }

        if (targetTimeSeconds == LAST_TIME_SECONDS_OF_DAY) {
            break
        }

        targetTimeSeconds++
    }

    return result
}

 

 

이상으로 백준 디지털시계 문제 풀이를 마치도록 하겠습니다. 감사합니다!

+ Recent posts