🗒 문제




📝 나의 문제풀이
알고리즘 문제는 항상 지문이 길어서 이해하는데 시간이 좀 소요되는 편이다.
그래서 나는 문제를 풀기 전 내가 어떠한 순서로 접근해야 하는지 주석으로 적어두고 시작한다.
일단 이 문제는 주어진 값들이 String으로 주어져서 계산을 위해 Int로 변환한 값이 필요했다.
따라서 Int로 변환하는 함수, 도로 String으로 변환하는 함수를 만들어준다.
다음으로 오프닝 구간 처리 함수를 만들어준다.
마지막으로 사용자의 동작에 따라 값을 처리하고, 결과값을 문제에서 요구하는 String값으로 변환하여 제출한다.
class Solution {
fun solution(
video_len: String,
pos: String,
op_start: String,
op_end: String,
commands: Array<String>
): String {
val videoLength = video_len.toSeconds()
val openingStart = op_start.toSeconds()
val openingEnd = op_end.toSeconds()
var currentPos = pos.toSeconds().skipOpening(openingStart, openingEnd)
commands.forEach { command ->
currentPos = when (command) {
"next" -> (currentPos + 10).coerceAtMost(videoLength)
"prev" -> (currentPos - 10).coerceAtLeast(0)
else -> currentPos
}.skipOpening(openingStart, openingEnd)
}
return currentPos.toTimeString()
}
// 확장 함수들
private fun String.toSeconds(): Int {
val (min, sec) = split(":").map { it.toInt() }
return min * 60 + sec
}
private fun Int.toTimeString(): String {
return "%02d:%02d".format(this / 60, this % 60)
}
private fun Int.skipOpening(openingStart: Int, openingEnd: Int): Int {
return if (this in openingStart..openingEnd) openingEnd else this
}
}
📝 다른 사람의 문제 풀이
다른 사람의 문제 풀이는 좋아요 수가 높거나 많은 사람들이 푼 방법 기준으로 첨부하였습니다.
class Solution {
fun solution(video_len: String, pos: String, op_start: String, op_end: String, commands: Array<String>): String {
val videoLen = video_len.toSec()
var currentPos = pos.toSec()
val opStart = op_start.toSec()
val opEnd = op_end.toSec()
currentPos = openingSkip(currentPos, opStart..opEnd)
for(command in commands) {
when(command) {
"prev" -> {
currentPos = if(currentPos - 10< 0) 0 else currentPos - 10
}
"next" -> {
currentPos = if(currentPos + 10 > videoLen) videoLen else currentPos + 10
}
}
currentPos = openingSkip(currentPos, opStart..opEnd)
}
return currentPos.toTimeString()
}
fun openingSkip(currentPos: Int, opRange : IntRange) : Int {
return if(currentPos in opRange) opRange.last else currentPos
}
fun String.toSec() : Int = this.split(":").let {
it[0].toInt() * 60 + it[1].toInt()
}
fun Int.toTimeString() : String = String.format("%02d:%02d", this/60, this%60)
}
🖊 문제 풀이 시 알면 좋을 것
확장 함수
기존 클래스에 새로운 함수를 추가하는 방법
// String에 toSeconds() 함수 추가
fun String.toSeconds(): Int = ...
// 사용
"13:00".toSeconds() // this = "13:00"
구조 분해
여러 값을 한 번에 변수로 받기
val (min, sec) = "13:00".split(":")
// min = "13", sec = "00"
val (a, b, c) = listOf(1, 2, 3)
// a = 1, b = 2, c = 3
let 함수
객체를 it으로 받아서 처리
"13:00".split(":").let { (min, sec) ->
min.toInt() * 60 + sec.toInt()
}
// split 결과를 바로 구조 분해하여 사용
coerceAtMost / coerceAtLeast
범위를 제한하는 함수
10.coerceAtMost(5) // 5 (최댓값 5로 제한)
(-1).coerceAtLeast(0) // 0 (최솟값 0으로 제한)
// 동일한 의미
if (value > max) max else value // coerceAtMost
if (value < min) min else value // coerceAtLeast
IntRange와 in 연산자
범위를 나타내고 포함 여부 확인
val range = 100..200 // 100부터 200까지
150 in range // true
50 in range // false
range.last // 200 (마지막 값)
forEach
컬렉션의 각 요소를 순회
commands.forEach { command ->
// 각 command 처리
}
// for문과 동일
for (command in commands) {
// 각 command 처리
}
차이: forEach가 더 함수형, for가 더 명령형
String.format()
형식에 맞춰 문자열 생성
"%02d:%02d".format(12, 5) // "12:05"
"%02d:%02d".format(9, 50) // "09:50"
// %02d = 2자리 정수, 빈 자리는 0으로 채움
시간 계산의 핵심
60진법이므로 초 단위로 변환!
// "13:00" → 780초
13 * 60 + 0 = 780
// 780초 - 10초 = 770초
770초 → 12분 50초
// 770초 → "12:50"
770 / 60 = 12 (분)
770 % 60 = 50 (초)
반응형
'코딩테스트' 카테고리의 다른 글
| [프로그래머스] 가장 큰 수 찾기 (0) | 2025.11.13 |
|---|---|
| [프로그래머스] 택배 상자 꺼내기 (0) | 2025.11.11 |
| [프로그래머스] 특별한 이차원 배열 2 (0) | 2025.09.10 |
| [프로그래머스] 그림 확대 (0) | 2025.02.18 |
| [프로그래머스] 커피 심부름 (0) | 2025.02.13 |