-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathUtils.kt
81 lines (55 loc) · 2.68 KB
/
Utils.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
import kotlin.math.pow
// Input reading utilities
private fun inputBufferedReader() = System.`in`.bufferedReader()
fun <T> mapLines(mapper: (String) -> T): MutableList<T> =
inputBufferedReader().useLines { lines -> lines.map(mapper).toMutableList() }
fun lines() = mapLines { it }
fun <T> mapBlocks(mapper: (String) -> T): MutableList<List<T>> =
inputBufferedReader()
.readText()
.trim('\n')
.splitToSequence("\n\n")
.map { it.lineSequence().map(mapper).toList() }
.toMutableList()
fun <T> withBlocks(transformer: (List<String>) -> T): MutableList<T> =
inputBufferedReader()
.readText()
.trim('\n')
.splitToSequence("\n\n")
.map { transformer(it.lines()) }
.toMutableList()
fun String.toInts(vararg delimiters: String = arrayOf(" ", ",")): List<Int> =
splitToSequence(*delimiters).filter { it.isNotEmpty() }.map { it.toInt() }.toList()
// Error handling utilities
fun <T> T?.expect(): T = this ?: error("Invalid input")
fun expect(): Nothing = error("Invalid Input")
// List utilities
val <T> List<List<T>>.innerIndices: Sequence<Pair<Int, Int>>
get() = indices.asSequence().flatMap { i -> this[i].indices.map { j -> i to j } }
operator fun <T> List<List<T>>.get(index: Pair<Int, Int>) = this[index.first][index.second]
operator fun <T> List<MutableList<T>>.set(index: Pair<Int, Int>, value: T) {
this[index.first][index.second] = value
}
fun <T> List<T>.toPair() = component1() to component2()
infix fun <F, S> List<F>.cartesian(second: List<S>): Sequence<Pair<F, S>> =
asSequence().flatMap { f -> second.asSequence().map { s -> f to s } }
infix fun <F, S> Sequence<F>.cartesian(other: Sequence<S>): Sequence<Pair<F, S>> =
flatMap { f -> other.map { s -> f to s } }
infix fun IntRange.cartesian(other: IntRange): Sequence<Pair<Int, Int>> =
asSequence().flatMap { f -> other.asSequence().map { s -> f to s } }
fun cartesian(intRange: IntRange, vararg rest: IntRange): Sequence<List<Int>> =
cartesian(intRange.asSequence(), *rest.map { it.asSequence() }.toTypedArray())
fun <T> cartesian(first: Sequence<T>, vararg rest: Sequence<T>): Sequence<List<T>> =
when (val second = rest.firstOrNull()) {
null -> first.map { listOf(it) }
else -> {
val newRest = rest.drop(1).toTypedArray()
first.flatMap { ir -> cartesian(second, *newRest).map { listOf(ir) + it } }
}
}
typealias Point = Pair<Int, Int>
// Bit vector utilities
fun Boolean.toInt() = if (this) 1 else 0
fun List<Boolean>.toInt() = fold(0) { acc, i -> (acc shl 1) or i.toInt() }
fun Int.pow(other: Int) = toDouble().pow(other).toInt()
fun Long.pow(other: Int) = toDouble().pow(other).toLong()