Kotlin의 fold는 컬렉션을 순회하면서 초기값을 설정하고, 이전 연산의 결과를 누적하면서 값을 계산하는 데 사용됩니다. 특히, 누적된 값을 유지하면서 새로운 값을 추가해야 하는 경우 유용합니다.
이번 글에서는 fold를 활용하여 ATM 대기 시간 최소화 문제를 해결하는 예제를 통해 fold의 동작 원리를 알아보겠습니다.
fold의 기본 구조
- initial: 초기값 (연산을 시작할 때 사용할 값)
- operation: 리스트의 각 요소를 순회하며 누적값(acc)과 현재 요소(T)를 사용해 연산을 수행하는 람다 함수
- 결과값(R)이 누적되면서 최종 결과를 반환
기본 예제: 리스트의 합 구하기
val numbers = listOf(1, 2, 3, 4, 5)
val sum = numbers.fold(0) { acc, num -> acc + num }
println(sum) // 출력: 15
동작 과정:
- initial = 0
- acc(0) + 1 = 1
- acc(1) + 2 = 3
- acc(3) + 3 = 6
- acc(6) + 4 = 10
- acc(10) + 5 = 15
- 최종 결과: 15
ATM 대기 시간 최소화 문제
문제 설명
은행에서 여러 사람이 ATM을 사용하려고 할 때, 각 사람이 인출하는 데 걸리는 시간이 다릅니다. 사람들이 줄을 서는 순서를 최적화하여 전체 대기 시간을 최소화하려면 어떻게 해야 할까요?
문제 해결 아이디어
- 사람들이 인출하는 시간을 오름차순으로 정렬합니다.
- 각 사람의 인출 시간이 누적되어 전체 대기 시간에 영향을 주므로, 이전까지의 합을 누적하면서 총 대기 시간을 계산해야 합니다.
- fold를 사용하여 totalTime(총 대기 시간)과 accumulatedTime(현재까지의 누적 대기 시간)을 함께 관리합니다.
fold를 사용한 구현 코드
fun main() {
val br = System.`in`.bufferedReader()
val bw = System.out.bufferedWriter()
br.readLine().toInt()
val times = br.readLine().split(" ").map { it.toInt() }
val sortedTimes = times.sorted()
val (totalTime, _) = sortedTimes.fold(0 to 0) { (total, accumulated), time ->
val newAccumulated = accumulated + time // 새로운 누적 대기 시간
total + newAccumulated to newAccumulated // (총 대기 시간, 현재 누적 대기 시간)
}
bw.write("$totalTime")
bw.flush()
bw.close()
}
코드 설명
- sortedTimes 리스트를 오름차순 정렬하여 최소한의 대기 시간을 만들 준비를 합니다.
- fold(0 to 0) { (total, accumulated), time -> ... }
- total: 현재까지의 총 대기 시간
- accumulated: 현재까지 누적된 대기 시간
- time: 현재 사람이 인출하는 시간
- 각 단계에서:
- newAccumulated = accumulated + time (이전까지의 누적합 + 현재 값)
- total + newAccumulated to newAccumulated을 반환하여 다음 반복에서 사용
실행 과정 예제
입력:
5
3 1 4 3 2
정렬된 리스트:
1 2 3 3 4
사람 | 인출 시간 | 누적 대기 시간 | 총 대기 시간 |
1 | 1 | 1 | 1 |
2 | 2 | 1 + 2 = 3 | 1 + 3 = 4 |
3 | 3 | 3 + 3 = 6 | 4 + 6 = 10 |
4 | 3 | 6 + 3 = 9 | 10 + 9 = 19 |
5 | 4 | 9 + 4 = 13 | 19 + 13 = 32 |
최종 출력:
32
fold에서 Pair를 사용하는 이유
fold(0 to 0) { (total, accumulated), time -> ... }
- Pair(0, 0)을 초기값으로 설정하여 두 개의 값을 동시에 관리
- total과 accumulated를 구조 분해(destructuring)로 편리하게 사용 가능
- Pair를 반환하면서 totalTime을 누적하고 accumulatedTime을 유지
reduce와 비교하면?
- reduce는 초기값을 설정할 수 없고, 하나의 값만 반환 가능하여 누적값을 유지하는 데 불리함.
- fold는 초기값을 지정하고, 여러 상태를 함께 관리할 수 있어 더 적합함.
결론
- fold는 초기값을 설정하고, 상태를 유지하면서 리스트를 순회하는 데 적합합니다.
- Pair를 활용하면 여러 개의 값을 동시에 누적할 수 있어 계산이 편리합니다.
- fold를 활용하면 누적 대기 시간과 총 대기 시간을 효과적으로 계산할 수 있습니다.
반응형
'Android > Kotlin' 카테고리의 다른 글
[Android/Kotlin] lateinit 이해하기: nullable과의 차이와 지연 초기화 이해하기 (0) | 2025.02.25 |
---|---|
[Android/Kotlin] mutableMapOf vs hashMapOf 차이점 및 성능 비교 (0) | 2025.02.06 |
[Android/Kotlin] 코틀린의 mutableMapOf()는 왜 LinkedHashMap을 사용할까? (0) | 2025.02.04 |
[Android/Kotlin] 코틀린 컬렉션 함수: any와 all (0) | 2025.01.21 |
[Android/Kotlin] removeAt: 요소 제거와 반환 동작 이해 (1) | 2025.01.17 |