본문 바로가기
Android/Kotlin

[Android/Kotlin] fold 사용법과 예제

by quessr 2025. 2. 5.

 

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

 

동작 과정:

  1. initial = 0
  2. acc(0) + 1 = 1
  3. acc(1) + 2 = 3
  4. acc(3) + 3 = 6
  5. acc(6) + 4 = 10
  6. acc(10) + 5 = 15
  7. 최종 결과: 15

ATM 대기 시간 최소화 문제

문제 설명

은행에서 여러 사람이 ATM을 사용하려고 할 때, 각 사람이 인출하는 데 걸리는 시간이 다릅니다. 사람들이 줄을 서는 순서를 최적화하여 전체 대기 시간을 최소화하려면 어떻게 해야 할까요?

문제 해결 아이디어

  1. 사람들이 인출하는 시간을 오름차순으로 정렬합니다.
  2. 각 사람의 인출 시간이 누적되어 전체 대기 시간에 영향을 주므로, 이전까지의 합을 누적하면서 총 대기 시간을 계산해야 합니다.
  3. 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()
}

코드 설명

  1. sortedTimes 리스트를 오름차순 정렬하여 최소한의 대기 시간을 만들 준비를 합니다.
  2. fold(0 to 0) { (total, accumulated), time -> ... }
    •    total: 현재까지의 총 대기 시간
    •    accumulated: 현재까지 누적된 대기 시간
    •    time: 현재 사람이 인출하는 시간
  3. 각 단계에서:
    •    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는 초기값을 지정하고, 여러 상태를 함께 관리할 수 있어 더 적합함.

결론

  1. fold초기값을 설정하고, 상태를 유지하면서 리스트를 순회하는 데 적합합니다.
  2. Pair를 활용하면 여러 개의 값을 동시에 누적할 수 있어 계산이 편리합니다.
  3. fold를 활용하면 누적 대기 시간과 총 대기 시간을 효과적으로 계산할 수 있습니다.
반응형