Skip to content

Commit 3d255f8

Browse files
committed
Improve solution 2025-05 (Cafeteria)
Let mergeRange() operate on an immutable list. It makes the code easier to read and has negligible performance impact.
1 parent 9f3d89a commit 3d255f8

File tree

2 files changed

+11
-17
lines changed

2 files changed

+11
-17
lines changed

src/main/kotlin/de/ronny_h/aoc/year2025/day05/Cafeteria.kt

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ class Cafeteria : AdventOfCode<Long>(2025, 5) {
1616
input.parseIngredients()
1717
.freshRanges
1818
.sortedBy { it.first }
19-
.fold(mutableListOf<LongRange>()) { compactRanges, range ->
19+
.fold(listOf<LongRange>()) { compactRanges, range ->
2020
compactRanges.mergeRange(range)
2121
}.sumOf {
2222
it.last - it.first + 1
@@ -27,11 +27,10 @@ data class Ingredients(val freshRanges: List<LongRange>, val available: List<Lon
2727

2828
// invariant: ranges in this MutableList are non-overlapping and sorted
2929
// pre-condition: add operations only occur with ranges sorted by their first value
30-
fun MutableList<LongRange>.mergeRange(toAdd: LongRange): MutableList<LongRange> {
30+
fun List<LongRange>.mergeRange(toAdd: LongRange): List<LongRange> {
3131
if (none { toAdd.first in it || toAdd.last in it }) {
3232
// disjunct -> just add it
33-
add(toAdd)
34-
return this
33+
return this + listOf(toAdd)
3534
}
3635
for ((i, range) in withIndex()) {
3736
if (toAdd.first in range && toAdd.last in range) {
@@ -45,17 +44,12 @@ fun MutableList<LongRange>.mergeRange(toAdd: LongRange): MutableList<LongRange>
4544
val lastOverlappingRangeIndex = indexOfLast { toAdd.last in it }
4645
if (toAdd.first in range && lastOverlappingRangeIndex == -1) {
4746
// the beginning overlaps with this range -> merge
48-
this[i] = range.first..toAdd.last
49-
return this
47+
return this.take(i) + listOf(range.first..toAdd.last) + this.drop(i + 1)
5048
}
5149

5250
// overlaps with several ranges -> squash them
5351
val lastOverlappingRange = this[lastOverlappingRangeIndex]
54-
for (index in lastOverlappingRangeIndex downTo i + 1) {
55-
this.removeAt(index)
56-
}
57-
this[i] = range.first..lastOverlappingRange.last
58-
return this
52+
return this.take(i) + listOf(range.first..lastOverlappingRange.last) + this.drop(lastOverlappingRangeIndex + 1)
5953
}
6054
error("If this line is reached, a case is missing")
6155
}

src/test/kotlin/de/ronny_h/aoc/year2025/day05/CafeteriaTest.kt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,12 @@ class CafeteriaTest : StringSpec({
3636

3737
"mergeRange merges the added range with the existing ones" {
3838
forAll(
39-
row(mutableListOf(2L..5L), 3L..4L, listOf(2L..5L)),
40-
row(mutableListOf(2L..5L), 6L..7L, listOf(2L..5L, 6L..7L)),
41-
row(mutableListOf(2L..5L, 8L..9L), 4L..6L, listOf(2L..6L, 8L..9L)),
42-
row(mutableListOf(2L..5L, 8L..9L), 4L..8L, listOf(2L..9L)),
43-
row(mutableListOf(2L..5L, 8L..9L, 11L..13L), 4L..11L, listOf(2L..13L)),
44-
row(mutableListOf(0L..1L, 4L..5L, 8L..9L, 11L..13L, 15L..20L), 4L..11L, listOf(0L..1L, 4L..13L, 15L..20L)),
39+
row(listOf(2L..5L), 3L..4L, listOf(2L..5L)),
40+
row(listOf(2L..5L), 6L..7L, listOf(2L..5L, 6L..7L)),
41+
row(listOf(2L..5L, 8L..9L), 4L..6L, listOf(2L..6L, 8L..9L)),
42+
row(listOf(2L..5L, 8L..9L), 4L..8L, listOf(2L..9L)),
43+
row(listOf(2L..5L, 8L..9L, 11L..13L), 4L..11L, listOf(2L..13L)),
44+
row(listOf(0L..1L, 4L..5L, 8L..9L, 11L..13L, 15L..20L), 4L..11L, listOf(0L..1L, 4L..13L, 15L..20L)),
4545
) { list, range, expected ->
4646
list.mergeRange(range) shouldBe expected
4747
}

0 commit comments

Comments
 (0)