repeat string n times in Kotlin - kotlin

I want to create a string which would contain a * symbol n times.
I only see this way:
val s = ""
val n = 100
for (j in 0 until n) {
s += "*"
}
But it looks ugly and it has a O(n^2) time complexity. Is there a way in Kotlin to do that without a loop with better time complexity?

The built in CharSequence.repeat extension does this in an efficient way, see the source here.
val str: String = "*".repeat(100)
Of course, this will still require O(n) steps to create the string. However, using this built-in stdlib function has its advantages: it's cross-platform, easy to read, and can be improved in performance over time, if there's a more efficient solution. The loop inside it will probably be optimized by the compiler or the runtime anyway.

You can overload the * operator to map it to the existing repeat extension:
public operator fun CharSequence.times(count: Int): String {
return repeat(count)
}
fun main() {
val s = "*" * 101
println(s)
println("Badger " * 12 + "Mushroom " * 2)
println(s)
}

An alternative to the CharSequence.repeat is a CharArray with an init function:
CharArray(N, {i -> '*'}).joinToString(separator="")
This solution has the advantage that you can define prefix, postfix, and separator.

StringBuilder would improve the memory footprint here:
val sb = StringBuilder()
val n = 100
for (j in 0 until n) {
sb.append("*")
}

If you need a separator, this initializer function from List is helpful:
val str: String = List(100) { "*" }.joinToString(",")

Thanks to Anton Sizikov and https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/repeat.html, we can write:
val sb = StringBuilder().apply{
repeat(100) {
append("*")
}
}
But this is a simple way. Look at a power function. It has O(log n) complexity.
For StringBuilder:
private fun power(sb: StringBuilder, n: Int): StringBuilder =
when {
n == 0 -> StringBuilder("")
n % 2 == 0 -> {
val part = power(sb, n / 2)
part.append(part)
}
else -> {
val part = power(sb, n / 2)
part.append(part).append(sb)
}
}
For String:
private fun pow(s: String, n: Int): String =
when {
n == 0 -> ""
n % 2 == 0 -> pow(s, n / 2).repeat(2)
else -> s + pow(s, n / 2).repeat(2)
}
Then we can invoke them:
// 1.
val sb1 = StringBuilder().apply {
repeat(100) {
append("*")
}
}
// 2.
val sb2 = power(StringBuilder("*"), 100)
// 3.
val s = power("*", 100)
println(sb1.toString())
println(s)
println(sb2.toString())

Related

using val in kotlin lambda

i'm playing around with map in kotlin, and currently I would like to see whether it would be possible to map a list of integers to a list of functions (Int) -> Int, while doing a bunch of operations inside the lambda that would require me to save values to vals
So I have this simple code:
val num = arrayOf(1, 2, 3, 4)
val funcs = num.map <Int, (Int) -> Int > { x -> {
y -> y + x
}}
This is a bit of a condensed example, the thing i'm really trying to do is a bit more convoluted. But I need to quite a bit of operations inside of of the 'inner' lambda, so I need to write codeblocks where I can use val. Like this:
val fs = num.map <Int, (Int) -> Int > { x -> {
y -> {
val tmp = y *2
val tmp1 = x / 2
tmp + tmp1
}
}}
But this part doesnt work, the compiler is confused by return types
How can I do something like this?
The reason your code in particular does not work is because you are adding an extra { after y -> in the second example:
val fs = num.map<Int, (Int) -> Int> { x ->
{ y ->
{ // this is not needed
val tmp = y * 2
val tmp1 = x / 2
tmp + tmp1
}// this is not needed
}
}
So you are creating a "block" of {} which in kotlin means that you are creating a lambda function. The reason block is in quotes is because if you truly want a block in kotlin the syntax is run {}, as opposed to the java {}. But again, you do not need it here.
All you have to do is remove the extra brackets and your code is fine:
val fs = num.map <Int, (Int) -> Int > { x -> {
y ->
val tmp = y *2
val tmp1 = x / 2
tmp + tmp1
}}
There is no difference between single-line and multi-line lambda
val fs = num.map { x ->
{ y: Int ->
val tmp = y * 2
val tmp1 = x / 2
tmp + tmp1
}
}

How to split operators and operands into two arrays?

I want to split this content into two seperate arrays numbers and operators in Kotlin.
The content is "2*5-6+7".
This is my code which doesnt work:
val arrnum = content.split("[-+*/]").toTypedArray()
val operator = content.split("[0123456789]").toTypedArray()
Maybe something like this, using partition:
val OPERATORS = setOf('*', '+', '-', '/')
fun main() {
val (operators, numbers) = "2*5-6+7".toList().partition { it in OPERATORS }
println(operators)
println(numbers)
}
Prints:
[2, 5, 6, 7]
[*, -, +]
If you want to use regular expressions you have to wrap them into Regex("[-+*/]")
The full example would look like this:
val arrnum = content.split(Regex("[-+*/]")).toTypedArray()
val op = content.split(Regex("[0123456789]")).toTypedArray()
Other things to note: "operator" is a keyword in Kotlin. You can simplify [0123456789] to [\d] (with double \ in Kotlin). The operator array will contain empty entries for what's left of of the two and right of the 7. You can filter them out like .filter { it.isNotBlank() }
Solution without regular expressions, but with mutability:
const val OPERATORS = "*+-/"
fun main() {
val s = "2*55-6+7"
val numbers = mutableListOf<Int>()
val operators = mutableListOf<Char>()
var prevIndex = 0
s.withIndex().forEach { (index, c) ->
if (c in OPERATORS) {
operators.add(c)
numbers.add(s.substring(prevIndex until index).toInt())
prevIndex = index + 1
}
}
numbers.add(s.substring(prevIndex).toInt())
println(operators)
println(numbers)
}
Solution without regular expressions in functional style:
const val OPERATORS = "*+-/"
fun main() {
val s = "2*55-6+7"
val operatorsIndexed = s.withIndex().filter { it.value in OPERATORS }
val operators = operatorsIndexed.map { it.value }
val numbers = listOf(-1, *operatorsIndexed.map { it.index }.toTypedArray(), s.length)
.windowed(2)
.map { (from, to) -> s.substring(from + 1 until to).toInt() }
println(operators)
println(numbers)
}

How to repeat a string n times in Kotlin, when n is Long

I know using repeat function we can repeat a string n times but what if the n is bigger than a size of an Int
You can do this, though you are likely to run out of memory with such long strings
fun String.repeat(times: Long): String {
val inner = (times / Integer.MAX_VALUE).toInt()
val remainder = (times % Integer.MAX_VALUE).toInt()
return buildString {
repeat(inner) {
append(this#repeat.repeat(Integer.MAX_VALUE))
}
append(this#repeat.repeat(remainder))
}
}

More idiomatic way to initialize a set in Kotlin?

I have a set of Cells
data class Cell(val i: Int, val j: Int)
that I initialize in my class like this
protected val board = mutableSetOf<Cell>()
init {
for (i in 1..width) {
for (j in 1..width) {
board += Cell(i, j)
}
}
}
Is there a more idiomatic (functional) way to initialize the set?
Ideally I would like the set to be immutable, because after this initialization it should never be changed.
You could define an extension that takes in a transformer to get the combinations as a pair of integers, then map it to a Cell. For instance:
inline fun <R> IntRange.combine(block: (Int, Int) -> R): Set<R> {
return flatMap { x -> map { y -> block(x, y) } }.toSet()
}
And then you can initialize with:
protected val board = (1..width).combine { x, y -> Cell(x, y) }
or simply:
protected val board = (1..width).flatMap { i -> (1..width).map { j -> Cell(i, j) } }
I think the former is more readable, though.
Unfortunately there is no constructor or top-level function to make the creation of a set following a certain logic easy, but if you already have a list you can turn it into a Set using toSet().
In any case I would separate the logic of creating a list of combinations and the creation of the Cell instances.
// extension property on IntRange to create all possible combinations
val IntRange.combinations get() = flatMap { i -> map { j -> i to j }}
val set = (1..5)
.combinations
.map { (i, j) -> Cell(i, j) }
.toSet()
Addition:
If you create a secondary constructor for Cell which takes a Pair like this:
data class Cell(val i: Int, val j: Int) {
constructor(pair: Pair<Int, Int>): this(pair.first, pair.second)
}
you can shorten the code to this:
val set = (1..5).combinations.map(::Cell).toSet()
You can do this
fun initBoard(width: Int): Set<Cell> {
return List<Cell>(width * width) { index ->
val i = index / width
val j = index % width
Cell(i + 1, j + 1)
}.toSet()
}
then in your init block
lateinit var board: Set<Cell>
init {
board = initBoard(width)
}

Reading multiple ints from the same line in Kotlin?

I am doing the 30 Days of Code in Kotlin on Hackerrank and I am stuck at Day 7.
How do you read multiple integers on a single line?
How is it added to an array and displayed in reverse?
I have solved it in Java but lack the syntax needed in Kotlin
Input:
4
1 4 3 2
My Code:
fun main(args: Array<String>) {
val n = readLine()!!.toInt()
var arr = Array(n)
for(i in 0 until n)
{
arr[i] = readLine()!!.toInt() //Not Working? nor does readLine()!!.split(' ').toInt()
}
for(item in arr.size - 1 downTo 0)
{
print("${item} ")
}
}
EDIT: question was updated from the original
The problem is the readLine() will read the entire line from stdin, so each time you call readLine() in the for loop it will result in a separate line being read each time.
One approach to this is to read the line, and then to split and map each value to an Int.
readLine()?.let {
val numOfValues = it.toInt()
println(numOfValues)
readLine()?.let { line ->
line.split(" ").map {
it.toInt()
}.reversed().forEach {
println(it)
}
}
}
If you want to store them in a list then you can follow this method
var items = readLine()!!.trim().split("\\s+".toRegex()).map (String::toInt)
println(items)
You can also store them in different variables like this way
var (a,b) = readLine()!!.trim().split("\\s+".toRegex()).map (String::toInt)
println(a+b)
You can also use the following code to item items splited and stored in array for a beginner approach
fun main(ags :Array<String>)
{
var item = readLine()!!.trim()
println(item[0])
}
Actually, you can refer to the official Kotlin tutorial: https://kotlinlang.org/docs/tutorials/competitive-programming.html
as mentioned in tutorial:
To make reading the input in competitive programming tasks like this more concise, you can have the following list of helper input-reading functions:
private fun readLn() = readLine()!! // string line
private fun readInt() = readLn().toInt() // single int
private fun readStrings() = readLn().split(" ") // list of strings
private fun readInts() = readStrings().map { it.toInt() } // list of ints
for your case, you can try use as below:
fun main() {
val n = readInt()
val x = readInts()
for (j in x.reversed()) {
print(j); print(" ")
}
println()
}
private fun readLn() = readLine()!! // string line
private fun readInt() = readLn().toInt() // single int
private fun readStrings() = readLn().split(" ") // list of strings
private fun readInts() = readStrings().map { it.toInt() } // list of ints