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

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))
}
}

Related

What is the best way in kotlin to convert an Int value to a Double in a certain format

I have the following numbers:
val first: Int = 531241180
val second: Int = 653345
What would be the best way to write a function which could get first and second as input and return the following values:
output of the fist to a Double value 53.1241180
output of the second to a Double value 6.53345
If you are allowed to specify, how many numbers you want to see before dot, you can write something like this, avoiding math operations
fun intToDouble(value: Int, integerPlaces: Int): Double {
val raw = value.toString()
val sb = StringBuilder(raw)
if(integerPlaces < sb.length()) {
sb.insert(integerPlaces, ".")
} else {
return 0.0 // return 0 if operation is illegal
}
return sb.toString().toDouble()
}

Taking sequence elements fulfilling a predicate then continuing from there in Kotlin

In Kotlin sequences have a takeWhile function that will let you take items as long as they adhere to a given predicate. What I'd like to do is take items according to that predicate, use them in some way, then alter the predicate and take the next "batch". So far I haven't really found a way of doing this purely with what sequences and iterators offer.
Following snippet of code illustrates the problem. The primeGenerator() function returns a Sequence of prime (Long) numbers. Suppose that I want to make lists with each list having prime numbers with the same number of digits. On creating each list I'd use it for some purpose. If the list conforms to what I was searching the iteration can end, otherwise move onto the next list.
val primeIt = primeGenerator().iterator()
var digits = 1
var next: Long? = null
val currentList = ArrayList<Long>()
while (digits < 4) {
next?.also { currentList.add(it) }
next = primeIt.next()
if (next.toString().length > digits) {
println("Primes with $digits: $currentList")
currentList.clear()
digits++
}
}
In this case it ends once the number of digits exceeds 3. This works fine, but I was wondering if there is some way to achieve the same with operations chained purely on the sequence or an iterator of it. Basically chunking the sequence but based on a predicate rather than a set size. The prime number example above is just for illustration, I'm after the general principle, not something that'd only work for this case.
There are no such functions in standard library for large (or infinite) sequences, but you may write such function by yourself (although it requires some extra code):
class BufferedIterator<T>(private val iterator: Iterator<T>) : Iterator<T> {
var current: T? = null
private set
var reachedEnd: Boolean = false
private set
override fun hasNext(): Boolean = iterator.hasNext().also { reachedEnd = !it }
override fun next(): T = iterator.next().also { current = it }
}
fun <T> Iterator<T>.buffered() = BufferedIterator(this)
fun <T> BufferedIterator<T>.takeWhile(predicate: (T) -> Boolean): List<T> {
val list = ArrayList<T>()
if (reachedEnd) return list
current?.let {
if (predicate(it)) list += it
}
while (hasNext()) {
val next = next()
if (predicate(next)) list += next
else break
}
return list
}
fun main() {
val sequence = sequence {
var next = 0
while (true) {
yield(next++)
}
}
val iter = sequence.iterator().buffered()
for (i in 0..3) {
println(iter.takeWhile { it.toString().length <= i })
}
}
With this approach you can easily work even with infinite sequences.
I believe there is a way to accomplish what you want using the standard library. Limit the sequence first and then groupBy the number of digits.
val Int.numberOfDigits
get() = this.toString().length
sequenceOf(1,22,333).takeWhile{ it.numberOfDigits < 3 }.groupBy{ it.numberOfDigits }.values
If you want to avoid the eager evaluation of groupBy you could use groupingBy instead and then reduce potentially leaving the accumulator blank.
ardenit's answer seems like the best reusable approach. Since taking "chunks" of a sequence requires some state it doesn't seem likely something easily done in a purely functional manner. Delegating the state to a separate class enveloping the sequence makes sense.
Here's a small snippet showing what I ended up using. This assumes the sequence will not be empty and is (technically) infinite or further results aren't requested at some point.
class ChunkedIterator<T>(seq: Sequence<T>) {
private val it = seq.iterator()
var next: T = it.next()
fun next(predicate: (T) -> Boolean): List<T> {
val result = ArrayList<T>();
while (predicate.invoke(next)) {
result.add(next)
next = it.next();
}
return result
}
}
one way you could achieve this is by getting an iterator from your your original sequence and then building a new sequence out of it for each "take" -
val itr = seq.iterator()
val batch1 = itr.asSequence().takeWhile { predicate1(it) }.toList()
val batch2 = itr.asSequence().takeWhile { predicate2(it) }.toList()

repeat string n times in 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())

Idiomatic way to generate a random alphanumeric string in Kotlin

I can generate a random sequence of numbers in a certain range like the following:
fun ClosedRange<Int>.random() = Random().nextInt(endInclusive - start) + start
fun generateRandomNumberList(len: Int, low: Int = 0, high: Int = 255): List<Int> {
(0..len-1).map {
(low..high).random()
}.toList()
}
Then I'll have to extend List with:
fun List<Char>.random() = this[Random().nextInt(this.size)]
Then I can do:
fun generateRandomString(len: Int = 15): String{
val alphanumerics = CharArray(26) { it -> (it + 97).toChar() }.toSet()
.union(CharArray(9) { it -> (it + 48).toChar() }.toSet())
return (0..len-1).map {
alphanumerics.toList().random()
}.joinToString("")
}
But maybe there's a better way?
Since Kotlin 1.3 you can do this:
fun getRandomString(length: Int) : String {
val allowedChars = ('A'..'Z') + ('a'..'z') + ('0'..'9')
return (1..length)
.map { allowedChars.random() }
.joinToString("")
}
Lazy folks would just do
java.util.UUID.randomUUID().toString()
You can not restrict the character range here, but I guess it's fine in many situations anyway.
Assuming you have a specific set of source characters (source in this snippet), you could do this:
val source = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
java.util.Random().ints(outputStrLength, 0, source.length)
.asSequence()
.map(source::get)
.joinToString("")
Which gives strings like "LYANFGNPNI" for outputStrLength = 10.
The two important bits are
Random().ints(length, minValue, maxValue) which produces a stream of length random numbers each from minValue to maxValue-1, and
asSequence() which converts the not-massively-useful IntStream into a much-more-useful Sequence<Int>.
Using Collection.random() from Kotlin 1.3:
// Descriptive alphabet using three CharRange objects, concatenated
val alphabet: List<Char> = ('a'..'z') + ('A'..'Z') + ('0'..'9')
// Build list from 20 random samples from the alphabet,
// and convert it to a string using "" as element separator
val randomString: String = List(20) { alphabet.random() }.joinToString("")
Without JDK8:
fun ClosedRange<Char>.randomString(length: Int) =
(1..length)
.map { (Random().nextInt(endInclusive.toInt() - start.toInt()) + start.toInt()).toChar() }
.joinToString("")
usage:
('a'..'z').randomString(6)
To define it for a defined length:
val randomString = UUID.randomUUID().toString().substring(0,15)
where 15 is the number of characters
('A'..'z').map { it }.shuffled().subList(0, 4).joinToString("")
Using Kotlin 1.3:
This method uses an input of your desired string length desiredStrLength as an Integer and returns a random alphanumeric String of your desired string length.
fun randomAlphaNumericString(desiredStrLength: Int): String {
val charPool: List<Char> = ('a'..'z') + ('A'..'Z') + ('0'..'9')
return (1..desiredStrLength)
.map{ kotlin.random.Random.nextInt(0, charPool.size) }
.map(charPool::get)
.joinToString("")
}
If you prefer unknown length of alphanumeric (or at least a decently long string length like 36 in my example below), this method can be used:
fun randomAlphanumericString(): String {
val charPool: List<Char> = ('a'..'z') + ('A'..'Z') + ('0'..'9')
val outputStrLength = (1..36).shuffled().first()
return (1..outputStrLength)
.map{ kotlin.random.Random.nextInt(0, charPool.size) }
.map(charPool::get)
.joinToString("")
}
Or use coroutine API for the true Kotlin spirit:
buildSequence { val r = Random(); while(true) yield(r.nextInt(24)) }
.take(10)
.map{(it+ 65).toChar()}
.joinToString("")
Building off the answer from Paul Hicks, I wanted a custom string as input. In my case, upper and lower-case alphanumeric characters. Random().ints(...) also wasn't working for me, as it required an API level of 24 on Android to use it.
This is how I'm doing it with Kotlin's Random abstract class:
import kotlin.random.Random
object IdHelper {
private val ALPHA_NUMERIC = ('0'..'9') + ('A'..'Z') + ('a'..'z')
private const val LENGTH = 20
fun generateId(): String {
return List(LENGTH) { Random.nextInt(0, ALPHA_NUMERIC.size) }
.map { ALPHA_NUMERIC[it] }
.joinToString(separator = "")
}
}
The process and how this works is similar to a lot of the other answers already posted here:
Generate a list of numbers of length LENGTH that correspond to the index values of the source string, which in this case is ALPHA_NUMERIC
Map those numbers to the source string, converting each numeric index to the character value
Convert the resulting list of characters to a string, joining them with the empty string as the separator character.
Return the resulting string.
Usage is easy, just call it like a static function: IdHelper.generateId()
I use the following code to generate random words and sentences.
val alphabet: List<Char> = ('a'..'z') + ('A'..'Z') + ('0'..'9')
val randomWord: String = List((1..10).random()) { alphabet.random() }.joinToString("")
val randomSentence: String = (1..(1..10).random()).joinToString(" ") { List((1..10).random()) { alphabet.random() }.joinToString("") }
the question is old already, but I think another great solution (should work since Kotlin 1.3) would be the following:
// Just a simpler way to create a List of characters, as seen in other answers
// You can achieve the same effect by declaring it as a String "ABCDEFG...56789"
val alphanumeric = ('A'..'Z') + ('a'..'z') + ('0'..'9')
fun generateAlphanumericString(length: Int) : String {
// The buildString function will create a StringBuilder
return buildString {
// We will repeat length times and will append a random character each time
// This roughly matches how you would do it in plain Java
repeat(length) { append(alphanumeric.random()) }
}
}
fun randomAlphaNumericString(#IntRange(from = 1, to = 62) lenght: Int): String {
val alphaNumeric = ('a'..'z') + ('A'..'Z') + ('0'..'9')
return alphaNumeric.shuffled().take(lenght).joinToString("")
}
Building on Fabb111's answer:
fun randomString(length: Int): String =
buildString {
repeat(length) {
append((0 until 36).random().toString(36))
}
}
Numbers can be converted to a different base using the Int.toString(Int).
Base 36 is the numeral system that contains all alphanumeric characters
You can use RandomStringUtils.randomAlphanumeric(min: Int, max: Int) -> String from apache-commons-lang3
Here's a cryptographically secure version of it, or so I believe:
fun randomString(len: Int): String {
val random = SecureRandom()
val chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789".toCharArray()
return (1..len).map { chars[random.nextInt(chars.size)] }.joinToString("")
}
I used the most voted answer, but after using it for a while I discovered a big problem, since the random strings weren't that random.
I had to modify the generation of the random character, since if I only left allowedChars.random() it always generated the same strings, and I couldn't find why. I was reading that because random() was called very quickly, but I don't know how it works when calling it on the list of numbers.
fun getRandomString(): String {
val allowedChars = ('A'..'Z') + ('a'..'z') + ('0'..'9')
var string = ""
for (i in (1..20)) {
string += allowedChars[(Math.random() * (allowedChars.size - 1)).roundToInt()]
}
return string
}
// initialise at top
companion object {
private const val allowedCharacters = "0123456789QWERTYUIOPASDFGHJKLZXCVBNM"
}
//pass size and get Random String Captcha
fun getRandomCaptcha(sizeOfRandomCaptcha: Int): String {
val random = Random()
val sb = StringBuilder(sizeOfRandomCaptcha)
for (i in 0 until sizeOfRandomCaptcha)
sb.append(allowedCharacters[random.nextInt(allowedCharacters.length)])
return sb.toString()
}
Here's a simple function that uses newer Kotlin stdlib functions:
fun randomString(length: Int): String =
CharArray(length) { validChars.random() }.concatToString()
val validChars: List<Char> = ('a'..'z') + ('A'..'Z') + ('0'..'9'),
This uses:
a collection constructor with a initializer function
CharArray(length) { i -> /* provide a value for element i */ }
This is a one-liner for creating a CharArray and initializing each value using a lambda, It accepts a length, so the CharArray will be initialized with the correct size.
The Collection<>.random() extension function, that will pick a random character. This can be seeded if desired.
validChars.random()
The initialized CharArray is converted to a string using concatToString(), which was released in version 1.4.
The best way I think:
fun generateID(size: Int): String {
val source = "A1BCDEF4G0H8IJKLM7NOPQ3RST9UVWX52YZab1cd60ef2ghij3klmn49opq5rst6uvw7xyz8"
return (source).map { it }.shuffled().subList(0, size).joinToString("")
}

How to define Long Long data type in kotlin?

fun main(args: Array<String>) {
try {
var sum: Long = 0
val n: Int = readLine()!!.toInt()
for (i in 0..(n - 1)) {
var input: Long?
input = readLine()!!.toLong()
sum += input
}
println(sum)
} catch (ex: Exception) {
println(ex.message)
}
}
I want to take data Type Long Long replacing at Long . So how can I define Long Long data type?
Kotlin's Long is 64-bit already. No need for ancient long long trickery:
https://kotlinlang.org/docs/reference/basic-types.html
If you're on the JVM, there isn't a long long type, but you could use java.math.BigInteger for arbitrarily large numbers instead.
See more discussion on this topic and some more alternatives at a Java question here.
Kotlin handles long long data type with the BigInteger data type. Replace the long with BigInteger;
fun main(args: Array<String>) {
try {
var sum = 0.toBigInteger()
val n: Int = readLine()!!.toInt()
for (i in 0..(n - 1)) {
var input: BigInteger?
input = readLine()!!.toBigInteger()
sum += input
}
println(sum)
} catch (ex: Exception) {
println(ex.message)
}
}