diff --git a/lib/src/main/kotlin/de/linkel/aoc/utils/StringMixIn.kt b/lib/src/main/kotlin/de/linkel/aoc/utils/StringMixIn.kt new file mode 100644 index 0000000..84f4f05 --- /dev/null +++ b/lib/src/main/kotlin/de/linkel/aoc/utils/StringMixIn.kt @@ -0,0 +1,14 @@ +package de.linkel.aoc.utils + +fun CharSequence.replaceIndex(idx: Int, char: Char): CharSequence { + if (idx < 0 || idx >= length) + throw IndexOutOfBoundsException("index $idx is out of bounds 0..${length-1}") + val sb = StringBuilder() + sb.appendRange(this, 0, idx) + sb.append(char) + sb.appendRange(this, idx + 1, length) + return sb +} + +fun String.replaceIndex(idx: Int, char: Char): String = + (this as CharSequence).replaceIndex(idx, char).toString() diff --git a/lib/src/main/kotlin/de/linkel/aoc/utils/graph/Graph.kt b/lib/src/main/kotlin/de/linkel/aoc/utils/graph/Graph.kt index 3640fea..9ee6398 100644 --- a/lib/src/main/kotlin/de/linkel/aoc/utils/graph/Graph.kt +++ b/lib/src/main/kotlin/de/linkel/aoc/utils/graph/Graph.kt @@ -6,7 +6,7 @@ data class Node( ) class Graph( - nodes: Set> + val nodes: Set> ) { private val network = nodes.associateBy { it.id } @@ -79,6 +79,28 @@ class Graph( } } + fun subGraphs(): Iterable> { + val results = mutableListOf>>() + val all = network.keys.toMutableSet() + while (all.isNotEmpty()) { + val first = all.first() + val current = mutableSetOf() + val queue = mutableListOf(first) + while (queue.isNotEmpty()) { + val node = queue.removeAt(0) + current.add(node) + queue.addAll( + network[node]!!.edges.keys + .filter { it !in current } + ) + } + results.add(current.map { network[it]!! }.toSet()) + all.removeAll(current) + } + return results + .map { Graph(it) } + } + data class DijkstraNode( val id: K, val distance: Int, diff --git a/lib/src/main/kotlin/de/linkel/aoc/utils/grid/Segment.kt b/lib/src/main/kotlin/de/linkel/aoc/utils/grid/Segment.kt new file mode 100644 index 0000000..22ec729 --- /dev/null +++ b/lib/src/main/kotlin/de/linkel/aoc/utils/grid/Segment.kt @@ -0,0 +1,46 @@ +package de.linkel.aoc.utils.grid + +import kotlin.math.abs +import kotlin.math.sign + +data class Segment( + val x: Int, + val y: Int +) { + operator fun plus(v: Vector): Segment { + return copy( + x = x + v.deltaX, + y = y + v.deltaY + ) + } + operator fun minus(p: Segment): Vector { + return Vector( + deltaX = x - p.x, + deltaY = y - p.y + ) + } + + operator fun rangeTo(p: Segment): List { + if (p == this) { + return listOf(p) + } + val vector = p - this + return if (vector.deltaY == 0) { + (0 .. abs(vector.deltaX)) + .map { i -> this.copy( + x = x + (i) * vector.deltaX.sign + )} + } else if (vector.deltaX == 0) { + (0 .. abs(vector.deltaY)) + .map { i -> this.copy( + y = y + (i) * vector.deltaY.sign + )} + } else { + throw IllegalArgumentException("rangeTo only works in straight lines") + } + } + + override fun toString(): String { + return "$x/$y" + } +} diff --git a/lib/src/main/kotlin/de/linkel/aoc/utils/iterables/CombinationMixIn.kt b/lib/src/main/kotlin/de/linkel/aoc/utils/iterables/CombinationMixIn.kt new file mode 100644 index 0000000..7eac4dc --- /dev/null +++ b/lib/src/main/kotlin/de/linkel/aoc/utils/iterables/CombinationMixIn.kt @@ -0,0 +1,72 @@ +package de.linkel.aoc.utils.iterables + +fun List.combinationPairs( + withSelf: Boolean = false, + withMirrors: Boolean = false +): Sequence> { + val size = this.size + val list = this + return sequence { + (0 until size) + .forEach { i -> + ((if (withMirrors) 0 else i) until size) + .forEach { j -> + if (withSelf || i != j) { + yield(Pair(list[i], list[j])) + } + } + } + } +} + +fun List.combineWith(other: List): Sequence> { + val list = this + return sequence { + list + .forEach { a -> + other.forEach { b -> + yield(Pair(a, b)) + } + } + } +} + +fun List>.combinations(): Sequence> { + val outer = this + return sequence { + val sizes = outer.map { it.size } + val indices = outer.map { 0 }.toMutableList() + while (indices.mapIndexed { i, o -> o < sizes[i] }.all { it }) { + yield( + indices.mapIndexed { i,o -> outer[i][o] } + ) + if (outer.indices + .firstOrNull { i -> + indices[i] = indices[i] + 1 + if (indices[i] >= sizes[i]) { + indices[i] = 0 + false + } else true + } == null) { + break + } + } + } +} + +fun List.permutations(maxSize: Int = -1): Sequence> { + val list = this + return sequence { + if (list.isEmpty() || maxSize == 0) { + yield(emptyList()) + } else { + list.indices.forEach { i -> + val item = list[i] + list.withoutIndex(i).permutations(maxSize - 1) + .forEach { + yield(it + item) + } + } + } + } +} diff --git a/lib/src/main/kotlin/de/linkel/aoc/utils/mixins/ConcatSequence.kt b/lib/src/main/kotlin/de/linkel/aoc/utils/iterables/ConcatSequence.kt similarity index 98% rename from lib/src/main/kotlin/de/linkel/aoc/utils/mixins/ConcatSequence.kt rename to lib/src/main/kotlin/de/linkel/aoc/utils/iterables/ConcatSequence.kt index 3be4aa0..c12c72b 100644 --- a/lib/src/main/kotlin/de/linkel/aoc/utils/mixins/ConcatSequence.kt +++ b/lib/src/main/kotlin/de/linkel/aoc/utils/iterables/ConcatSequence.kt @@ -1,4 +1,4 @@ -package de.linkel.aoc.utils.mixins +package de.linkel.aoc.utils.iterables fun Sequence.prepend(element: T): Sequence { return if (this is ConcatSequence) { diff --git a/lib/src/main/kotlin/de/linkel/aoc/utils/iterables/FilterMixIn.kt b/lib/src/main/kotlin/de/linkel/aoc/utils/iterables/FilterMixIn.kt new file mode 100644 index 0000000..21ef43d --- /dev/null +++ b/lib/src/main/kotlin/de/linkel/aoc/utils/iterables/FilterMixIn.kt @@ -0,0 +1,5 @@ +package de.linkel.aoc.utils.iterables + + +fun List.withoutIndex(blacklist: IntRange) = this.filterIndexed { idx, _ -> idx !in blacklist } +fun List.withoutIndex(index: Int) = this.filterIndexed { idx, _ -> idx != index } diff --git a/lib/src/main/kotlin/de/linkel/aoc/utils/mixins/IntRangeMixIn.kt b/lib/src/main/kotlin/de/linkel/aoc/utils/iterables/IntRangeMixIn.kt similarity index 94% rename from lib/src/main/kotlin/de/linkel/aoc/utils/mixins/IntRangeMixIn.kt rename to lib/src/main/kotlin/de/linkel/aoc/utils/iterables/IntRangeMixIn.kt index c8e70ea..604e143 100644 --- a/lib/src/main/kotlin/de/linkel/aoc/utils/mixins/IntRangeMixIn.kt +++ b/lib/src/main/kotlin/de/linkel/aoc/utils/iterables/IntRangeMixIn.kt @@ -1,4 +1,4 @@ -package de.linkel.aoc.utils.mixins +package de.linkel.aoc.utils.iterables fun IntRange.intersects(other: IntRange): Boolean { return (this.first <= other.first && this.last >= other.first) || (other.first <= this.first && other.last >= this.first) diff --git a/lib/src/main/kotlin/de/linkel/aoc/utils/mixins/LongRangeMixIn.kt b/lib/src/main/kotlin/de/linkel/aoc/utils/iterables/LongRangeMixIn.kt similarity index 93% rename from lib/src/main/kotlin/de/linkel/aoc/utils/mixins/LongRangeMixIn.kt rename to lib/src/main/kotlin/de/linkel/aoc/utils/iterables/LongRangeMixIn.kt index 6625c0e..e5701f2 100644 --- a/lib/src/main/kotlin/de/linkel/aoc/utils/mixins/LongRangeMixIn.kt +++ b/lib/src/main/kotlin/de/linkel/aoc/utils/iterables/LongRangeMixIn.kt @@ -1,4 +1,4 @@ -package de.linkel.aoc.utils.mixins +package de.linkel.aoc.utils.iterables fun LongRange.intersects(other: LongRange): Boolean { return (this.first <= other.first && this.last >= other.first) || (other.first <= this.first && other.last >= this.first) diff --git a/lib/src/main/kotlin/de/linkel/aoc/utils/mixins/NumberIterables.kt b/lib/src/main/kotlin/de/linkel/aoc/utils/iterables/NumberIterables.kt similarity index 95% rename from lib/src/main/kotlin/de/linkel/aoc/utils/mixins/NumberIterables.kt rename to lib/src/main/kotlin/de/linkel/aoc/utils/iterables/NumberIterables.kt index 20c80e4..f46dc3e 100644 --- a/lib/src/main/kotlin/de/linkel/aoc/utils/mixins/NumberIterables.kt +++ b/lib/src/main/kotlin/de/linkel/aoc/utils/iterables/NumberIterables.kt @@ -1,4 +1,4 @@ -package de.linkel.aoc.utils.mixins +package de.linkel.aoc.utils.iterables import de.linkel.aoc.utils.CommonMath import java.math.BigDecimal diff --git a/lib/src/main/kotlin/de/linkel/aoc/utils/iterables/SplitSequenceMixIn.kt b/lib/src/main/kotlin/de/linkel/aoc/utils/iterables/SplitSequenceMixIn.kt new file mode 100644 index 0000000..a5fce2d --- /dev/null +++ b/lib/src/main/kotlin/de/linkel/aoc/utils/iterables/SplitSequenceMixIn.kt @@ -0,0 +1,20 @@ +package de.linkel.aoc.utils.iterables + + +fun Sequence.split(predicate: (T) -> Boolean): Sequence> { + val input = this + return sequence { + val buffer = mutableListOf() + input.forEach { element -> + if (predicate(element)) { + yield(buffer.toList()) + buffer.clear() + } else { + buffer.add(element) + } + } + if (buffer.isNotEmpty()) { + yield(buffer.toList()) + } + } +} diff --git a/lib/src/main/kotlin/de/linkel/aoc/utils/rangeset/AbstractNumberRangeSet.kt b/lib/src/main/kotlin/de/linkel/aoc/utils/rangeset/AbstractNumberRangeSet.kt index 0f09fe0..7c936ff 100644 --- a/lib/src/main/kotlin/de/linkel/aoc/utils/rangeset/AbstractNumberRangeSet.kt +++ b/lib/src/main/kotlin/de/linkel/aoc/utils/rangeset/AbstractNumberRangeSet.kt @@ -1,6 +1,6 @@ package de.linkel.aoc.utils.rangeset -import de.linkel.aoc.utils.mixins.ConcatIterator +import de.linkel.aoc.utils.iterables.ConcatIterator abstract class AbstractNumberRangeSet( ranges: Iterable, @@ -25,7 +25,6 @@ abstract class AbstractNumberRangeSet( cache.add(range) } } - println("$ranges -> $cache") segments = cache.toList() first = segments.firstOrNull()?.start ?: factory.maxValue last = segments.lastOrNull()?.endInclusive ?: factory.minValue diff --git a/lib/src/main/kotlin/de/linkel/aoc/utils/rangeset/IntRangeSet.kt b/lib/src/main/kotlin/de/linkel/aoc/utils/rangeset/IntRangeSet.kt index 8ac7aad..8369eba 100644 --- a/lib/src/main/kotlin/de/linkel/aoc/utils/rangeset/IntRangeSet.kt +++ b/lib/src/main/kotlin/de/linkel/aoc/utils/rangeset/IntRangeSet.kt @@ -1,7 +1,7 @@ package de.linkel.aoc.utils.rangeset -import de.linkel.aoc.utils.mixins.intersect -import de.linkel.aoc.utils.mixins.intersects +import de.linkel.aoc.utils.iterables.intersect +import de.linkel.aoc.utils.iterables.intersects class IntRangeSetFactory: RangeFactory { companion object { diff --git a/lib/src/main/kotlin/de/linkel/aoc/utils/rangeset/LongRangeSet.kt b/lib/src/main/kotlin/de/linkel/aoc/utils/rangeset/LongRangeSet.kt index ff1990a..918fb25 100644 --- a/lib/src/main/kotlin/de/linkel/aoc/utils/rangeset/LongRangeSet.kt +++ b/lib/src/main/kotlin/de/linkel/aoc/utils/rangeset/LongRangeSet.kt @@ -1,7 +1,7 @@ package de.linkel.aoc.utils.rangeset -import de.linkel.aoc.utils.mixins.intersect -import de.linkel.aoc.utils.mixins.intersects +import de.linkel.aoc.utils.iterables.intersect +import de.linkel.aoc.utils.iterables.intersects class LongRangeSetFactory: RangeFactory { companion object { diff --git a/lib/src/test/kotlin/de/linkel/aoc/utils/StringTest.kt b/lib/src/test/kotlin/de/linkel/aoc/utils/StringTest.kt new file mode 100644 index 0000000..78ea058 --- /dev/null +++ b/lib/src/test/kotlin/de/linkel/aoc/utils/StringTest.kt @@ -0,0 +1,11 @@ +package de.linkel.aoc.utils + +import org.assertj.core.api.Assertions +import org.junit.jupiter.api.Test + +class StringTest { + @Test + fun `can replace s single character at a given position`() { + Assertions.assertThat("test".replaceIndex(1, '3')).isEqualTo("t3st") + } +} diff --git a/lib/src/test/kotlin/de/linkel/aoc/utils/iterables/CombinationTest.kt b/lib/src/test/kotlin/de/linkel/aoc/utils/iterables/CombinationTest.kt new file mode 100644 index 0000000..ad12dd4 --- /dev/null +++ b/lib/src/test/kotlin/de/linkel/aoc/utils/iterables/CombinationTest.kt @@ -0,0 +1,255 @@ +package de.linkel.aoc.utils.iterables + +import org.assertj.core.api.Assertions +import org.junit.jupiter.api.Test + +class CombinationTest { + @Test + fun `empty list produces no combinations`() { + Assertions.assertThat(emptyList().combinationPairs(withSelf = false, withMirrors = false).toSet()).isEmpty() + Assertions.assertThat(emptyList().combinationPairs(withSelf = true, withMirrors = false).toSet()).isEmpty() + Assertions.assertThat(emptyList().combinationPairs(withSelf = false, withMirrors = true).toSet()).isEmpty() + Assertions.assertThat(emptyList().combinationPairs(withSelf = true, withMirrors = true).toSet()).isEmpty() + } + + @Test + fun `1,2,3 without self and without mirrors is produces 3 pairs`() { + Assertions.assertThat( + listOf(1, 2, 3) + .combinationPairs(withSelf = false, withMirrors = false) + .toSet() + ).isEqualTo( + setOf( + 1 to 2, + 1 to 3, + 2 to 3 + ) + ) + } + + @Test + fun `1,2,3 with self and without mirrors is produces 6 pairs`() { + Assertions.assertThat( + listOf(1, 2, 3) + .combinationPairs(withSelf = true, withMirrors = false) + .toSet() + ).isEqualTo( + setOf( + 1 to 1, + 1 to 2, + 1 to 3, + 2 to 2, + 2 to 3, + 3 to 3 + ) + ) + } + + @Test + fun `1,2,3 without self and with mirrors is produces 6 pairs`() { + Assertions.assertThat( + listOf(1, 2, 3) + .combinationPairs(withSelf = false, withMirrors = true) + .toSet() + ).isEqualTo( + setOf( + 1 to 2, + 1 to 3, + 2 to 1, + 2 to 3, + 3 to 1, + 3 to 2 + ) + ) + } + + @Test + fun `1,2,3 with self and with mirrors is produces 9 pairs`() { + Assertions.assertThat( + listOf(1, 2, 3) + .combinationPairs(withSelf = true, withMirrors = true) + .toSet() + ).isEqualTo( + setOf( + 1 to 1, + 1 to 2, + 1 to 3, + 2 to 1, + 2 to 2, + 2 to 3, + 3 to 1, + 3 to 2, + 3 to 3 + ) + ) + } + + @Test + fun `1,2,3 combined with a,b produces 6 elements`() { + Assertions.assertThat( + listOf('1','2','3') + .combineWith( + listOf('a','b') + ) + .toSet() + ).isEqualTo( + setOf( + '1' to 'a', + '1' to 'b', + '2' to 'a', + '2' to 'b', + '3' to 'a', + '3' to 'b' + ) + ) + } + + @Test + fun `1,2,3 combined with empty list is empty`() { + Assertions.assertThat( + listOf('1','2','3') + .combineWith( + emptyList() + ) + .toSet() + ).isEmpty() + } + + @Test + fun `combinations of 3 * 1,2,3 are 27`() { + Assertions.assertThat( + List(3) { listOf(1,2,3) } + .combinations() + .toSet() + ).isEqualTo( + setOf( + listOf(1, 1, 1), + listOf(1, 1, 2), + listOf(1, 1, 3), + listOf(1, 2, 1), + listOf(1, 2, 2), + listOf(1, 2, 3), + listOf(1, 3, 1), + listOf(1, 3, 2), + listOf(1, 3, 3), + + listOf(2, 1, 1), + listOf(2, 1, 2), + listOf(2, 1, 3), + listOf(2, 2, 1), + listOf(2, 2, 2), + listOf(2, 2, 3), + listOf(2, 3, 1), + listOf(2, 3, 2), + listOf(2, 3, 3), + + listOf(3, 1, 1), + listOf(3, 1, 2), + listOf(3, 1, 3), + listOf(3, 2, 1), + listOf(3, 2, 2), + listOf(3, 2, 3), + listOf(3, 3, 1), + listOf(3, 3, 2), + listOf(3, 3, 3), + ) + ) + } + + @Test + fun `permutations of 1 is 1`() { + Assertions.assertThat( + listOf(1) + .permutations() + .toSet() + ).isEqualTo( + setOf( + listOf(1), + ) + ) + } + @Test + fun `permutations of emptyList is list of emptyList`() { + Assertions.assertThat( + emptyList() + .permutations() + .toSet() + ).isEqualTo( + setOf( + emptyList(), + ) + ) + } + + @Test + fun `permutations of 1,2,3`() { + Assertions.assertThat( + listOf(1,2,3) + .permutations() + .toSet() + ).isEqualTo( + setOf( + listOf(1, 2, 3), + listOf(1, 3, 2), + listOf(2, 1, 3), + listOf(2, 3, 1), + listOf(3, 1, 2), + listOf(3, 2, 1), + ) + ) + } + + @Test + fun `permutations of 1,1,2,3`() { + Assertions.assertThat( + listOf(1,1,2,3) + .permutations() + .toSet() + ).isEqualTo( + setOf( + listOf(1, 1, 2, 3), + listOf(1, 1, 3, 2), + listOf(1, 2, 1, 3), + listOf(1, 2, 3, 1), + listOf(1, 3, 1, 2), + listOf(1, 3, 2, 1), + listOf(1, 1, 2, 3), + listOf(1, 1, 3, 2), + listOf(2, 1, 1, 3), + listOf(2, 1, 3, 1), + listOf(3, 1, 1, 2), + listOf(3, 1, 2, 1), + listOf(1, 2, 1, 3), + listOf(1, 3, 1, 2), + listOf(2, 1, 1, 3), + listOf(2, 3, 1, 1), + listOf(3, 1, 1, 2), + listOf(3, 2, 1, 1), + listOf(1, 2, 3, 1), + listOf(1, 3, 2, 1), + listOf(2, 1, 3, 1), + listOf(2, 3, 1, 1), + listOf(3, 1, 2, 1), + listOf(3, 2, 1, 1), + ) + ) + } + + @Test + fun `permutations of 2 elements of 1,2,3`() { + Assertions.assertThat( + listOf(1,2,3) + .permutations(2) + .toSet() + ).isEqualTo( + setOf( + listOf(1, 2), + listOf(1, 3), + listOf(2, 1), + listOf(2, 3), + listOf(3, 1), + listOf(3, 2), + ) + ) + } +} diff --git a/lib/src/test/kotlin/de/linkel/aoc/utils/iterables/FilterTest.kt b/lib/src/test/kotlin/de/linkel/aoc/utils/iterables/FilterTest.kt new file mode 100644 index 0000000..63a3043 --- /dev/null +++ b/lib/src/test/kotlin/de/linkel/aoc/utils/iterables/FilterTest.kt @@ -0,0 +1,83 @@ +package de.linkel.aoc.utils.iterables + +import org.assertj.core.api.Assertions +import org.junit.jupiter.api.Test + +class FilterTest { + @Test + fun `withoutIndex with index works on empty list`() { + Assertions.assertThat( + emptyList().withoutIndex(0) + ).isEqualTo( + emptyList() + ) + } + + @Test + fun `withoutIndex works if given index is 0`() { + Assertions.assertThat( + listOf(1, 2, 3).withoutIndex(0) + ).isEqualTo( + listOf(2, 3) + ) + } + + @Test + fun `withoutIndex works if given index is last`() { + Assertions.assertThat( + listOf(1, 2, 3).withoutIndex(2) + ).isEqualTo( + listOf(1, 2) + ) + } + + @Test + fun `withoutIndex works if given index is in the middle`() { + Assertions.assertThat( + listOf(1, 2, 3).withoutIndex(1) + ).isEqualTo( + listOf(1, 3) + ) + } + + @Test + fun `withoutIndex works if given index is out of range`() { + Assertions.assertThat( + listOf(1, 2, 3).withoutIndex(12) + ).isEqualTo( + listOf(1, 2, 3) + ) + Assertions.assertThat( + listOf(1, 2, 3).withoutIndex(-1) + ).isEqualTo( + listOf(1, 2, 3) + ) + } + + @Test + fun `withoutIndexRange works if given range overlaps at the beginning`() { + Assertions.assertThat( + listOf(1, 2, 3, 4).withoutIndex(-1..1) + ).isEqualTo( + listOf(3, 4) + ) + } + + @Test + fun `withoutIndexRange works if given range overlaps at the end`() { + Assertions.assertThat( + listOf(1, 2, 3, 4).withoutIndex(3..5) + ).isEqualTo( + listOf(1, 2, 3) + ) + } + + @Test + fun `withoutIndexRange works if given range overlaps in the middle`() { + Assertions.assertThat( + listOf(1, 2, 3, 4).withoutIndex(1..2) + ).isEqualTo( + listOf(1, 4) + ) + } +} diff --git a/lib/src/test/kotlin/de/linkel/aoc/utils/iterables/IntRangeExtendTest.kt b/lib/src/test/kotlin/de/linkel/aoc/utils/iterables/IntRangeExtendTest.kt index 47cd2d3..d0c5c71 100644 --- a/lib/src/test/kotlin/de/linkel/aoc/utils/iterables/IntRangeExtendTest.kt +++ b/lib/src/test/kotlin/de/linkel/aoc/utils/iterables/IntRangeExtendTest.kt @@ -1,7 +1,5 @@ package de.linkel.aoc.utils.iterables -import de.linkel.aoc.utils.mixins.extend -import de.linkel.aoc.utils.mixins.move import org.assertj.core.api.Assertions import org.junit.jupiter.api.Test diff --git a/lib/src/test/kotlin/de/linkel/aoc/utils/iterables/IntRangeIntersectTest.kt b/lib/src/test/kotlin/de/linkel/aoc/utils/iterables/IntRangeIntersectTest.kt index fc0a2a9..1f797b5 100644 --- a/lib/src/test/kotlin/de/linkel/aoc/utils/iterables/IntRangeIntersectTest.kt +++ b/lib/src/test/kotlin/de/linkel/aoc/utils/iterables/IntRangeIntersectTest.kt @@ -1,7 +1,5 @@ package de.linkel.aoc.utils.iterables -import de.linkel.aoc.utils.mixins.intersect -import de.linkel.aoc.utils.mixins.intersects import org.assertj.core.api.Assertions import org.junit.jupiter.api.Test diff --git a/lib/src/test/kotlin/de/linkel/aoc/utils/iterables/LongRangeExtendTest.kt b/lib/src/test/kotlin/de/linkel/aoc/utils/iterables/LongRangeExtendTest.kt index 0c5d731..4574963 100644 --- a/lib/src/test/kotlin/de/linkel/aoc/utils/iterables/LongRangeExtendTest.kt +++ b/lib/src/test/kotlin/de/linkel/aoc/utils/iterables/LongRangeExtendTest.kt @@ -1,7 +1,5 @@ package de.linkel.aoc.utils.iterables -import de.linkel.aoc.utils.mixins.extend -import de.linkel.aoc.utils.mixins.move import org.assertj.core.api.Assertions import org.junit.jupiter.api.Test diff --git a/lib/src/test/kotlin/de/linkel/aoc/utils/iterables/LongRangeIntersectTest.kt b/lib/src/test/kotlin/de/linkel/aoc/utils/iterables/LongRangeIntersectTest.kt index bb4975b..18a9c50 100644 --- a/lib/src/test/kotlin/de/linkel/aoc/utils/iterables/LongRangeIntersectTest.kt +++ b/lib/src/test/kotlin/de/linkel/aoc/utils/iterables/LongRangeIntersectTest.kt @@ -1,7 +1,5 @@ package de.linkel.aoc.utils.iterables -import de.linkel.aoc.utils.mixins.intersect -import de.linkel.aoc.utils.mixins.intersects import org.assertj.core.api.Assertions import org.junit.jupiter.api.Test diff --git a/lib/src/test/kotlin/de/linkel/aoc/utils/iterables/SequenceConcatTest.kt b/lib/src/test/kotlin/de/linkel/aoc/utils/iterables/SequenceConcatTest.kt index 12c6f78..41c3eff 100644 --- a/lib/src/test/kotlin/de/linkel/aoc/utils/iterables/SequenceConcatTest.kt +++ b/lib/src/test/kotlin/de/linkel/aoc/utils/iterables/SequenceConcatTest.kt @@ -1,8 +1,5 @@ package de.linkel.aoc.utils.iterables -import de.linkel.aoc.utils.mixins.append -import de.linkel.aoc.utils.mixins.plus -import de.linkel.aoc.utils.mixins.prepend import org.assertj.core.api.Assertions import org.junit.jupiter.api.Test diff --git a/lib/src/test/kotlin/de/linkel/aoc/utils/iterables/SequenceSplitTest.kt b/lib/src/test/kotlin/de/linkel/aoc/utils/iterables/SequenceSplitTest.kt new file mode 100644 index 0000000..8a50c7e --- /dev/null +++ b/lib/src/test/kotlin/de/linkel/aoc/utils/iterables/SequenceSplitTest.kt @@ -0,0 +1,38 @@ +package de.linkel.aoc.utils.iterables + +import org.assertj.core.api.Assertions +import org.junit.jupiter.api.Test + +class SequenceSplitTest { + @Test + fun `1-10 can be split on numbers dividable by 3`() { + Assertions.assertThat( + (1..10).asSequence().split { it % 3 == 0 } + .toList() + ).isEqualTo(listOf( + listOf(1, 2), + listOf(4, 5), + listOf(7, 8), + listOf(10) + )) + } + + @Test + fun `sequence of lines can be split on empty line`() { + Assertions.assertThat( + """ + erste zeile + zweite zeile + + dritte zeile + vierte zeile + """.trimIndent() + .lineSequence() + .split(String::isEmpty) + .toList() + ).isEqualTo(listOf( + listOf("erste zeile", "zweite zeile"), + listOf("dritte zeile", "vierte zeile") + )) + } +}