kotlin variable with range or 2 values? - kotlin

I am trying to make out this line but I have found no explanation about it.
var max = Int.MIN_VALUE to 0
Is 'max' a kind of range or does it have 2 values(Int.MIN_VALUE and 0).
Where can I find any reference about it?

max is an implicitly typed Kotlin Pair.
It's the same as writing:
var max: Pair<Int, Int> = Pair(Int.MIN_VALUE, 0)

Related

How would I map a list of items to the arguments of another function?

I am trying to figure out the best way to map my sorted map to the arguments of another function. This is an example of what I have.
data class ValueDescription (val length: Int, val count: Int)
// Now I am trying to map to a variable that looks like this
// This variable cannot be changed, I have to return this variable in this format
// The output will be a list of ValueDescriptions with a length and count for each entry of the map I have
// I will add the results of myValues to a mutable list later
val myValues = ValueDescription(_length here__, __count here__)
I have a sorted map that I want to map to my values
// The map will look like this
// Where both Ints hold the lengths and counts
// For example I would have the length of 7 to count of 8
val out = Map<Int, Int>
How can I take the values in my sorted map and place them into the variable myValues?
I tried to map by looping through my map with the forEach method and doing something like
out.map{it.key to myValues.ValueDescription.length}
but this doesn't seem to work.
I'm not sure I completely understood the question. If I got it correctly, your input is the Map<Int, Int> and you want to transform it to a List<ValueDescription>.
You can definitely use the map function for this:
val inputMap: Map<Int, Int> = TODO("provide the initial map here")
val myValues = inputMap.map { (l, c) -> ValueDescription(l, c) }
The map function here iterates over the entries of the map, and transforms each of them into a value of type ValueDescription by calling our lambda (the part between braces { ... }).
Each entry of the map here contains a key (the length) and a value (the count). Instead of using it.key and it.value, you can also use parentheses like I did here with (l, c) to destructure the entry into its 2 parts and give them names like l and c. The above is equivalent to:
val myValues = inputMap.map { ValueDescription(it.key, it.value) }

Input out of range for Int datatype, not passing a testcase

I am trying to solve the following question on LeetCode; Write a function that takes an unsigned integer and returns the number of '1' bits it has. Constraints: The input must be a binary string of length 32.
I have written the following code for that which works fine for inputs 00000000000000000000000000001011 and 00000000000000000000000010000000 (provided internally by the website) but give output 0 for input 11111111111111111111111111111101 and in my local compiler for the last input it says "out of range"
class Solution {
// you need treat n as an unsigned value
fun hammingWeight(n:Int):Int {
var num = n
var setCountBit = 0
while (num > 0) {
setCountBit++
num= num and num-1
}
return setCountBit
}
}
To correctly convert binary string to Int and avoid "out of range error", you need to do the following (I believe LeetCode does the same under the hood):
fun binaryStringToInt(s: String): Int = s.toUInt(radix = 2).toInt()
"11111111111111111111111111111101" is equivalent to 4294967293. This is greater than Int.MAX_VALUE, so it will be represented as negative number after .toInt() convertion (-3 in this case).
Actually, this problem could be solved with one-liner in Kotlin 1.4:
fun hammingWeight(n: Int): Int = n.countOneBits()
But LeetCode uses Kotlin 1.3.10, so you need to adjust your solution to handle negative Ints as well.
Please change the type of your input variable from Int to a type like Double .At the moment The given value is bigger than the maximum value that a type Int number can store.

Kotlin function that returns 0 for negative values and the same value for positive ones

I'm a bit annoyed with the line of code below. I'm wondering if there are any build-in function in the Kotlin SDK that could do the same in a more elegant way.
val result = if (value > 0) value else 0
val result = value.coerceAtLeast(0)
https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.ranges/coerce-at-least.html
also you can use
val result = max(0, value)

Kotlin - Get Maximum value in ArrayList of Ints

I have this ArrayList
var amplititudes: ArrayList<Int> = ArrayList()
amplititudes.add(1)
amplititudes.add(2)
amplititudes.add(3)
amplititudes.add(4)
amplititudes.add(3)
amplititudes.add(2)
amplititudes.add(1)
I want to get the maximum value i.e 4. What will be the easiest way to find the max element? I know about the max() method , but it will forces me to use ? with the return value since it could be null. Is there any solution which is better than this?
You can use built-in functionality with maxOrNull (docs):
val amplitudes = listOf(1,2,3,4,3,2,1)
val max = amplitudes.maxOrNull() ?: 0
max() becomes deprecated starting from Kotlin 1.4, please use maxOrNull()
val list = listOf(10, 2, 33)
val max: Int = list.maxOrNull() ?: 0
You can use max(), if you want to use the default comparison (as in your case with ints), or maxBy, if you want to use a custom selector (i.e., algorithm) to compare values.
Note that both return int? (in your case), since the collection might be empty (i.e., no maximum value is present)
max() deprecated in Kotlin 1.4.
But it was reintroduced in 1.7 . More details here
Both max() and maxOrNull() can be used.
The difference is,
max() returns non null values.If the collection is empty it will throw NoSuchElementException.
maxOrNull() returns a nullable value, so if element not present in collection it would return null.
If you are sure that collection will not be empty or you have handled exception, you can use max().Otherwise it is recommended is to use maxOrNull() and have default value if it returns null.
val amplitudes = listOf(10,8,20,15,30,90)
//Here it returns non-null int
val max:Int = amplitudes.max()
println(max) //90
//Here it returns nullable int
val max :Int? = amplitudes.maxOrNull()
println(max) //90
//Here we can make it as non-nullable type using elvis operator.
val max1 :Int = amplitudes.maxOrNull()?:0
println(max) //90
val amplitudes1 = listOf<Int>()
val max2 :Int? = amplitudes1.maxOrNull()
println(max2) //prints null
val max3:Int = amplitudes1.max()
println(max3) // Throws NoSuchElementException
Playground Link

Difference between fold and reduce in Kotlin, When to use which?

I am pretty confused with both functions fold() and reduce() in Kotlin, can anyone give me a concrete example that distinguishes both of them?
fold takes an initial value, and the first invocation of the lambda you pass to it will receive that initial value and the first element of the collection as parameters.
For example, take the following code that calculates the sum of a list of integers:
listOf(1, 2, 3).fold(0) { sum, element -> sum + element }
The first call to the lambda will be with parameters 0 and 1.
Having the ability to pass in an initial value is useful if you have to provide some sort of default value or parameter for your operation. For example, if you were looking for the maximum value inside a list, but for some reason want to return at least 10, you could do the following:
listOf(1, 6, 4).fold(10) { max, element ->
if (element > max) element else max
}
reduce doesn't take an initial value, but instead starts with the first element of the collection as the accumulator (called sum in the following example).
For example, let's do a sum of integers again:
listOf(1, 2, 3).reduce { sum, element -> sum + element }
The first call to the lambda here will be with parameters 1 and 2.
You can use reduce when your operation does not depend on any values other than those in the collection you're applying it to.
The major functional difference I would call out (which is mentioned in the comments on the other answer, but may be hard to understand) is that reduce will throw an exception if performed on an empty collection.
listOf<Int>().reduce { x, y -> x + y }
// java.lang.UnsupportedOperationException: Empty collection can't be reduced.
This is because .reduce doesn't know what value to return in the event of "no data".
Contrast this with .fold, which requires you to provide a "starting value", which will be the default value in the event of an empty collection:
val result = listOf<Int>().fold(0) { x, y -> x + y }
assertEquals(0, result)
So, even if you don't want to aggregate your collection down to a single element of a different (non-related) type (which only .fold will let you do), if your starting collection may be empty then you must either check your collection size first and then .reduce, or just use .fold
val collection: List<Int> = // collection of unknown size
val result1 = if (collection.isEmpty()) 0
else collection.reduce { x, y -> x + y }
val result2 = collection.fold(0) { x, y -> x + y }
assertEquals(result1, result2)
Another difference that none of the other answers mentioned is the following:
The result of a reduce operation will always be of the same type (or a super type) as the data that is being reduced.
We can see that from the definition of the reduce method:
public inline fun <S, T : S> Iterable<T>.reduce(operation: (acc: S, T) -> S): S {
val iterator = this.iterator()
if (!iterator.hasNext()) throw UnsupportedOperationException("Empty collection can't be reduced.")
var accumulator: S = iterator.next()
while (iterator.hasNext()) {
accumulator = operation(accumulator, iterator.next())
}
return accumulator
}
On the other hand, the result of a fold operation can be anything, because there are no restrictions when it comes to setting up the initial value.
So, for example, let us say that we have a string that contains letters and digits. We want to calculate the sum of all the digits.
We can easily do that with fold:
val string = "1a2b3"
val result: Int = string.fold(0, { currentSum: Int, char: Char ->
if (char.isDigit())
currentSum + Character.getNumericValue(char)
else currentSum
})
//result is equal to 6
reduce - The reduce() method transforms a given collection into a single result.
val numbers: List<Int> = listOf(1, 2, 3)
val sum: Int = numbers.reduce { acc, next -> acc + next }
//sum is 6 now.
fold - What would happen in the previous case of an empty list? Actually, there’s no right value to return, so reduce() throws a RuntimeException
In this case, fold is a handy tool. You can put an initial value by it -
val sum: Int = numbers.fold(0, { acc, next -> acc + next })
Here, we’ve provided initial value. In contrast, to reduce(), if the collection is empty, the initial value will be returned which will prevent you from the RuntimeException.
Simple Answer
Result of both reduce and fold is "a list of items will be transformed into a single item".
In case of fold,we provide 1 extra parameter apart from list but in case of reduce,only items in list will be considered.
Fold
listOf("AC","Fridge").fold("stabilizer") { freeGift, itemBought -> freeGift + itemBought }
//output: stabilizerACFridge
In above case,think as AC,fridge bought from store & they give stabilizer as gift(this will be the parameter passed in the fold).so,you get all 3 items together.Please note that freeGift will be available only once i.e for the first iteration.
Reduce
In case of reduce,we get items in list as parameters and can perform required transformations on it.
listOf("AC","Fridge").reduce { itemBought1, itemBought2 -> itemBought1 + itemBought2 }
//output: ACFridge
The difference between the two functions is that fold() takes an initial value and uses it as the accumulated value on the first step, whereas the first step of reduce() uses the first and the second elements as operation arguments on the first step.