replicate(n:Int,x:T):List<T> is a list of length n with x the value of every element.
I wrote a mutable version replicate as below:
fun <T> mutableReplicate(n:Int, x:T) : MutableList<T>{
val xs = mutableListOf<T>()
for (i in 1..n){
xs.add(x)
}
return xs
}
Is there any bulid-in immutable replicate function in Kotlin?
How to write ourselves an immutable replicate function in Kotlin?
You can use List instantiation functions. They accept a function from the Index to the desired element, but you can also use them to create a List of constant values.
fun <T> replicate(n:Int,x:T):List<T> {
return List(n) { x }
}
If you need a read-only list, you can implement replicate the following way:
fun <T> replicate(n: Int, x: T): List<T> = object : AbstractList<T>() {
override val size: Int = n
override fun get(index: Int): T =
if (index in 0..lastIndex) x else throw IndexOutOfBoundsException("$n")
}
It has an advantage that it requires a constant amount of memory no matter how large n is.
Related
I have made an extension functions for BigIntegers, allowing me to add Ints to them.
operator fun BigInteger.plus(other: Int): BigInteger = this + other.toBigInteger()
// Allowing me to do
val c = myBigInt + 3
I have also made a Counter class, holding bigintegers for various keys, for easy counting. Since doing counter["1"] += myBigInt isn't allowed on standard maps (it's nullable), I have added a custom getter that returns a default value, making this possible.
class Counter<K>(val map: MutableMap<K, BigInteger>) : MutableMap<K, BigInteger> by map {
constructor() : this(mutableMapOf())
override operator fun get(key: K): BigInteger {
return map.getOrDefault(key, BigInteger.ZERO)
}
I can then use it like this
val counter = Counter<String>()
c["ones"] += 5.toBigInteger()
Problem is that I cannot use it like this:
c["ones"] += 5 // doesn't work, "Kotlin: No set method providing array access"
but this should be equivalent to this, which works, since it should use my extension operator on the bigint:
c["ones"] = c["ones"] + 5 // works
Why doesn't this work?
I've tried adding a set method for Ints, but then I see a very weird behavior. Kotlin will do the calculation correct, but then convert the BigInteger to an Int before passing it to my class! Example:
inline operator fun BigInteger.plus(other: Int): BigInteger {
val bigInteger = this + other.toBigInteger()
println("calculated bigint to $bigInteger")
return bigInteger
}
class Counter<K>(val map: MutableMap<K, BigInteger>) : MutableMap<K, BigInteger> by map {
constructor() : this(mutableMapOf())
override operator fun get(key: K): BigInteger {
return map.getOrDefault(key, BigInteger.ZERO)
}
operator fun set(key: K, value: Int) {
println("setting int $value")
map[key] = value.toBigInteger()
}
}
val c = Counter<String>()
c["1"] = "2192039569601".toBigInteger()
c["1"] += 5
println("result: ${c["1"]}")
c["1"] = "2192039569601".toBigInteger()
c["1"] = c["1"] + 5
println("result: ${c["1"]}")
Which prints
calculated bigint to 2192039569606
setting int 1606248646 <--- why does it call the int setter here?
result: 1606248646
calculated bigint to 2192039569606
result: 2192039569606
Why does Kotlin do the BigInt summation, but converts it back to an Int before sending to my setter?
Update
Since a comment suggest this is a compiler issue, any other ideas?
My ultimate goal here, was to have a counter of big integers, but to be able to easily add ints to it.
Adding this as a set function, makes it being called for both ints and bigints, so I can do the proper assignment myself. However, it will also then allow someone to add floats that will crash at runtime.
operator fun set(key: K, value: Number) {
map[key] = when (value) {
is BigInteger -> value
is Int -> value.toBigInteger()
else -> throw RuntimeException("only ints")
}
}
Any tips?
Notice that c["ones"] += 5 can be translated into calls in two ways:
c.set("ones", c.get("ones").plus(5))
c.get("ones").plusAssign(5)
The first way is what your code currently translates to, because you don't have a plusAssign operator defined. As I said in the comments, there is a bug in the compiler that prevents the operators from resolved correctly. When resolving c["ones"] += 5, It seems to be trying to find a set operator that takes an Int instead (possibly because 5 is an Int), which is unexpected. If you modify the code in the bug report a little, you can even make it throw an exception when executed!
class Foo {
operator fun get(i: Int) : A = A()
operator fun set(i: Int, a: A) {}
operator fun set(i: Int, a: Int) {}
}
class A {
operator fun plus(b: Int) = A()
}
class B
fun main(args: Array<String>) {
val foo = Foo()
foo[0] = foo[0] + 1
foo[0] += 1 // this compiles now, since there is a set(Int, Int) method
// but A can't be casted to Int, so ClassCastException!
}
It is rather coincidental (and lucky) in your case, that the compiler knows how to convert from BigInteger (or any other Number type actually) to Int, using Number#intValue. Otherwise the program would have crashed too.
A natural alternative way is to define the plusAssign operator, so that the assignment gets translated the second way. However, we can't do it on BigInteger, because plusAssign would need to mutate this, but BigInteger is immutable. This means that we need to create our own mutable wrapper. This does mean that you lose the nice immutability, but this is all I can think of.
fun main() {
val c = Counter<String>()
c.set("1", "2192039569601".toMutableBigInteger())
c.get("1").plusAssign(5)
println("result: ${c["1"]}")
}
data class MutableBigInteger(var bigInt: BigInteger) {
operator fun plusAssign(other: Int) {
bigInt += other.toBigInteger()
}
}
fun String.toMutableBigInteger() = MutableBigInteger(toBigInteger())
class Counter<K>(val map: MutableMap<K, MutableBigInteger>) : MutableMap<K, MutableBigInteger> by map{
constructor() : this(mutableMapOf())
override operator fun get(key: K): MutableBigInteger {
return map.getOrPut(key) { MutableBigInteger(BigInteger.ZERO) }
}
operator fun set(key: K, value: Int) {
println("setting int $value")
map[key] = MutableBigInteger(value.toBigInteger())
}
}
Notably, getOrDefault is changed to getOrPut - when a value is not found, we want to put the zero we return into the map, rather than just returning a zero that is not in the map. Our changes to that instance wouldn't be visible through the map otherwise.
Does Kotlin have something to filter a collection and return the matching indexes?
E.g. like Groovy's findIndexValues:
http://docs.groovy-lang.org/latest/html/groovy-jdk/java/lang/Iterable.html#findIndexValues(groovy.lang.Closure)
Something like:
fun <T> List<T>.findIndexValues(predicate: (T) -> Boolean): List<Int> {
var indexValues = mutableListOf<Int>()
this.forEachIndexed { index, it ->
if (predicate(it)) {
indexValues.add(index)
}
}
return indexValues
}
The simplest way I can think of to do this is to use mapIndexedNotNull:
fun <T> List<T>.findIndexValues(predicate: (T) -> Boolean): List<Int> =
mapIndexedNotNull { i, t -> i.takeIf { predicate(t) } }
I don't believe there's a function for this in the standard library.
There are basically 2 simple ways according to me.
//say there is a List x of Strings
val x = listOf<String>()
//I don't believe you are looking for this.
//string is the required String of x at index.
for ((index, string) in x.withIndex()) {
TODO()
}
//2nd method is using filterIndexed
/**
* Returns a list containing only elements matching the given predicate.
* #Params: predicate - function that takes the index of an element and the element itself and returns the result of predicate evaluation on the element.
*/
x.filterIndexed { index, string ->
TODO()
}
I like #Sam's answer, but I find this implementation to be slightly more readable as it filters explicitly on predicate as opposed to implicitly via null:
fun <T> List<T>.findIndexValues(predicate: (T) -> Boolean): List<Int> =
withIndex().filter { (_, t) -> predicate(t) }.map { it.index }
I made a function which returns all factors of an integer. But the problem is that it gives an error that the return type is Unit instead of mutableListOf. my code:
fun get_factors(num: Int) {
var factors = mutableListOf<Int>()
for (x in 1..num) {
if (x % num == 0) {
factors.add(x)
}
}
return factors
}
fun main() {
print(get_factors(18))
}
I tried doing:
fun get_factors(num: Int): mustableListOf {
var factors = mutableListOf<Int>()
for (x in 1..num) {
if (x % num == 0) {
factors.add(x)
}
}
return factors
}
fun main() {
print(get_factors(18))
}
but it says mutableListOf not defined.
I just started learning Kotlin today so I am a total beginner with Kotlin. Please help me out with this.
You seem to have confused the type MutableList<Int>, with the function mutableListOf.
Since the type name is MutableList<Int>, you should do:
fun get_factors(num: Int) : MutableList<Int> {
...
}
Or, if the caller doesn't need to modify the list, you can just return List<Int> too:
fun get_factors(num: Int) : List<Int> {
...
}
I can see why this is confusing - to create an instance of a type, you normally just add () to the end of the type name, so if mutableListOf() creates a list, you'd think that mutableListOf is the type name. However, this is actually calling the global function called mutableListOf, which returns an instance of MutableList<T>.
One way to distinguish between these is to look at the first letter. Type names usually begin with a capital letter, whereas function names begin with a small letter.
In Kotlin, it is possible to write
class A {
fun B.foo()
}
and then e.g. write with (myA) { myB.foo() }.
Is it possible to write this as an extension method on A, instead? My use case is writing
with (java.math.RoundingMode.CEILING) { 1 / 2 }
which I would want to return 1, the point being that I want to add operator fun Int.div(Int) to RoundingMode.
No it's not possible. operator div is required to have Int as a receiver.
You can't add also RoundingMode as receiver, since there can only be single function receiver.
What you can do, though, is use Pair<RoundingMode, Int> as a receiver:
operator fun Pair<RoundingMode, Int>.div(i: Int): BigDecimal =
BigDecimal.valueOf(second.toLong()).divide(BigDecimal.valueOf(i.toLong()), first)
with(RoundingMode.CEILING) {
println((this to 1) / 2) // => 1
}
That's not possible, Int already has a div function, thus, if you decide to write an extension function div, you won't be able to apply it, because member functions win over extension functions.
You can write this though:
fun RoundingMode.div(x: Int, y: Int): Int {
return if (this == RoundingMode.CEILING) {
Math.ceil(x.toDouble() / y.toDouble()).toInt()
} else {
Math.floor(x.toDouble() / y.toDouble()).toInt()
}
}
fun main(args: Array<String>) {
with(java.math.RoundingMode.CEILING) {
println(div(1,2))
}
}
It's not possible for a couple of reasons:
There's no "double extension functions" concept in Kotlin
You can't override a method with extension functions, and operator div is already defined in Int
However you can workaround these issues with
A context class and an extension lambda (e.g. block: ContextClass.() -> Unit)
Infix functions (e.g. use 15 div 4 instead of 15 / 4)
See the example below:
class RoundingContext(private val roundingMode: RoundingMode) {
infix fun Int.div(b: Int): Int {
val x = this.toBigDecimal()
val y = b.toBigDecimal()
val res = x.divide(y, roundingMode)
return res.toInt()
}
}
fun <T> using(roundingMode: RoundingMode, block: RoundingContext.() -> T): T {
return with(RoundingContext(roundingMode)) {
block()
}
}
// Test
fun main(args: Array<String>) {
using(RoundingMode.FLOOR) {
println(5 div 2) // 2
}
val x = using(RoundingMode.CEILING) {
10 div 3
}
println(x) // 4
}
Hope it helps!
To read Stars from a file in the Facebook Hacker Cup's 2016 Boomerang Constelations problem, following extension function can be defined:
fun BufferedReader.readStars(n: Int): Set<Star> {
return Array(n) {
val (l1, l2) = readLine().split(" ").map { it.toInt() }
Star(l1, l2)
}.toHashSet()
}
Code is compact but the values are first read into an array and then converted to a HashSet. Is there a way to directly initialize a HashSet with the size of n and initializator function in Kotlin?
UPDATE: Is there an existing way in standard Kotlin libs?
You can always use apply to initialize objects in-place:
HashSet<Star>(n).apply {
repeat(n) {
val (l1, l2) = readLine()!!.split(' ').map { it.toInt() }
put(Star(l1, l2))
}
}
If that's too inconvenient too type every time, write an extension function:
inline fun <T> createHashSet(n : Int, crossinline fn: (Int) -> T) = HashSet<T>(n).apply {
repeat(n) { add(fn(it)) }
}
Usage:
createHashSet<Star>(n) {
val (l1, l2) = readLine()!!.split(' ').map { it.toInt() }
Star(l1, l2)
}
Since HashSet is a java class so you can only initialize it in a way provided by JDK.
While there's no helper method in Kotlin runtime it's easy to write it yourself like so:
public fun <T> hashSetOf(size: Int, initializer: (Int) -> T): HashSet<T> {
val result = HashSet<T>(size)
0.rangeTo(size - 1).forEach {
result.add(initializer(it))
}
return result
}
As #miensol has pointed out HashSet initialization is limited to the constructors made available by the JDK. Kotlin has added a hashSetOf function which initializes an empty HashSet and then adds the specified elements to it.
To avoid first reading the values into an array you can use a kotlin.Sequence who's "values are evaluated lazily":
fun BufferedReader.readStars(n: Int): Set<Star> {
return lineSequence().take(n).map {
val (l1, l2) = it.split(" ").map { it.toInt() }
Star(l1, l2)
}.toHashSet()
}
It seems like you are asking an XY question (http://xyproblem.info/). You really want to know how to write readStars in the most efficient way, but instead you ask about HashSet. I think #mfulton26 answers your question as well depending on what is being asked.
Here is the answer for "how do I write this in the most efficient way:"
You have two options. First, a version that auto-closes the stream at the end:
fun BufferedReader.readStars(n: Int): Set<Star> {
return use {
lineSequence().map { line ->
val idx = line.indexOf(' ')
Star(line.substring(0, idx).toInt(), line.substring(idx + 1).toInt())
}.toSet()
}
}
And second, a version that does not:
fun BufferedReader.readStars(n: Int): Set<Star> {
return lineSequence().map { line ->
val idx = line.indexOf(' ')
Star(line.substring(0, idx).toInt(), line.substring(idx+1).toInt())
}.toSet()
}
Neither version creates an array, neither do they make copies of data. They stream the data through a sequence which creates the Set and fills it directly.
Other notes
No need to use split if you are really concerned about allocations and performance. Just use indexOf(char) and split the string yourself using substring.
If you do a split, then please use split(char) not split(String) when you are looking to split on a char