find the first element in a list beyond some index and satisfying some condition - kotlin

I have as Input:
A givenIndex
A list
I want to find the index of the first positive element in that list but ignoring all the indices that are strictly smaller than givenIndex
For example if givenIndex=2 and the list is listOf(1, 0, 0, 0, 6, 8, 2), the expected output is 4 (where the value is 6).
The following code gives the first positive element but It doesn't take into account ignoring all the indices that are smaller than givenIndex.
val numbers = listOf(1, 0, 0, 0, 6, 8, 2)
val output = numbers.indexOfFirst { it > 0 } //output is 0 but expected is 4

val givenIndex = 2
val output = numbers.withIndex().indexOfFirst { (index, value) -> index >= givenIndex && value > 0 }

Related

Is this how I initialize a list with values in Kotlin?

I want to store a number of counts per value, something like this:
value count
0 -> 6
1 -> 2
2 -> 0
3 -> 7
As shown in the example, the values start at 0 and are consecutive integers.
I want to initialize all counts with 0, so that I can then increment them.
This is what I came up with:
val histogram = Array(numBuckets) { 0 }.toMutableList() as ArrayList
histogram[2]++
It works, but the initialization feels a bit convoluted. Is there a better way? Is the ArrayList the correct collection for the job in the place?
You can just use the MutableList constructor:
val histogram = MutableList(numBuckets) { 0 }
Kevin Coppock's answer works well if the values in the value-count pairs are consecutive and starting at 0. Then the array or list index stands for the value in the value-count pair.
If more flexibility is needed, for example if the values
do not start at zero,
have a step which is not 1,
or have irregular steps (e.g. logarithmic),
it might make sense to introduce pairs, either as Pair<Int, Int> or in the form of a data class:
import kotlin.math.pow
data class HistogramEntry(
var value: Int,
var count: Int
)
Example:
val numBuckets = 5
val regularHistogram = List(numBuckets) { HistogramEntry(it, 0) }
regularHistogram[2].count++
regularHistogram(::println)
Output:
HistogramEntry(value=0, count=0)
HistogramEntry(value=1, count=0)
HistogramEntry(value=2, count=1)
HistogramEntry(value=3, count=0)
HistogramEntry(value=4, count=0)
Another example:
val numBuckets = 5
val logarithmicHistogram = List(numBuckets) { HistogramEntry(10f.pow(it + 1).toInt(), 0) }
logarithmicHistogram[2].count = 12345
logarithmicHistogram.forEach(::println)
Output:
HistogramEntry(value=10, count=0)
HistogramEntry(value=100, count=0)
HistogramEntry(value=1000, count=12345)
HistogramEntry(value=10000, count=0)
HistogramEntry(value=100000, count=0)
And of course a HistogramEntry list could also be built manually:
val list = listOf(
HistogramEntry(value = 234, count = 0),
HistogramEntry(value = 36, count = 0),
HistogramEntry(value = 9, count = 0),
HistogramEntry(value = 178, count = 0),
HistogramEntry(value = 11, count = 0)
)

Kotlin aggregate consecutive list elements

I'd like to sum up consecutive numbers in a Kotlin list.
If the list has a 0 then it should start summing up the numbers after 0. The result would be a list of sums. Basically sum up until the first 0 then until the next 0 and so forth.
For example:
val arr = arrayOf(1, 2, 0, 2, 1, 3, 0, 4)
// list of sums = [3, 6, 4]
At the moment I got it working with fold:
val sums: List<Int> = arr.fold(listOf(0)) { sums: List<Int>, n: Int ->
if (n == 0)
sums + n
else
sums.dropLast(1) + (sums.last() + n)
}
but I wonder if there is a simpler or more efficient way of doing this.
I would personally have written it this way:
val sums = mutableListOf(0).also { acc ->
arr.forEach { if (it == 0) acc.add(0) else acc[acc.lastIndex] += it }
}
Using a mutable list, you avoid having to do any drop / concatenation. The code is also easier to follow.
You can still convert it to an immutable list using .toList() if you need to.

Find the first element in a list that verify a condition

Assuming we are given a list of integers R = [3,5,3,6,0,6,7], an threshold x (integer) and a window size (integer) p. For example, x=4 and p = 2.
I need to find the first index t that verifies the the following conditions:
R[t] >= 4, R[t+1] >= 4. Since p=2, we need to only verify for two boxes t and t+1. If p was equal to 3 we will need to verify for t, t+1 and t+2.
Here the t I am looking for is 5 (indexing is starting from 0).
How to write this in a elegant way in Kotlin (rather than looping on the elements).
A tentative that is giving an error (x=4 and p = 2. The output should be 3 since we start indexing by 0):
val numbers = listOf(1, 2, 3, 4, 6, 8, 2)
val firstIndex = numbers.find { it >= 4 for it in it..it+2-1}
val numbers = listOf(1, 2, 3, 4, 6, 8, 2)
val p = 2
val x = 4
val t = numbers.windowed(p).indexOfFirst { window -> window.all { it >= x } } // t == 3
t will be equal to -1 in case if no matches will be found
Use windowed to check groups of values for each index in the list. Use withIndex() so you are iterating with the indices, which you need in your final result. Then use firstOrNull() (which find() is a redundant alias of). And finally, take ?.index to get the index of the first entry that satisfies the condition, or null if none satisfy.
val x = 4
val p = 3
val list = listOf(2,5,3,6,0,6,7)
val t = list
.windowed(p)
.withIndex()
.firstOrNull { (_, sublist) -> sublist.all { it >= x } }
?.index
find Returns the first element matching the given predicate, or null if no such element was found.
If I've understood correctly, this should work:
fun main() {
val list = listOf(3,5,3,6,0,6,7)
val p = 2
val x = 4
val t = list.withIndex().windowed(p).firstOrNull() { window ->
window.all { it.value >= x }
}?.first()?.index
println(t)
}
Output:
5

Kotlin Array Slice Indexing

Let's say I want to iterate through all but the first element in Kotlin IntArray. Currently, I'm doing it like this:
fun minimalExample(nums: IntArray): Unit {
for(num in nums.sliceArray(IntRange(1,nums.size-1))) println(num)
}
Is there an easy syntax for doing this like in Python (I don't want to have to specify the ending index of the nums array):
for (num in nums[1:])
I think you could use Kotlin's drop which will remove the first n elements of an array.
fun minimalExampleWithDrop(nums: IntArray): Unit {
for(num in nums.drop(1)) println(num)
}
minimalExampleWithDrop(intArrayOf(1,2,3,4,5,6))
// 2
// 3
// 4
// 5
// 6
Repl.it:
https://repl.it/repls/SvelteShadyLivecd
You can alternatively also use the slice method which is present in lists and arrays. Here are examples for both:
val a = listOf(1, 2, 3, 4)
println(a.slice(1..a.size - 1))
val b = arrayOf(1, 2, 3, 4, 5, 6, 7, 8, 9)
println(b.slice(4..5))
This will print out:
[2, 3, 4]
[5, 6]
A basic for loop with 1 as starting index
val myList = intArrayOf(1,2,3,4,5,6)
for(i in 1 until myList.size){
Log.d(TAG,"${myList[i]}")
}
Or since it's an IntArray you can use it as an Iterator and skip elements like shown here
val iterator = myList.iterator()
// skip an element
if (iterator.hasNext()) {
iterator.next()
}
iterator.forEach {
Log.d(TAG,"it -> $it")
}
Just to add to #gil.fernandes answer, you can use slice with until like this:
val list = arrayOf(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
println(list.slice(0 until 5))
This will output:
[0, 1, 2, 3, 4]

Kotlin code - how does FlatMap work here?

The following is code from a LeetCode solution.
This is the description:
Given an array A of non-negative integers, half of the integers in A are odd, and half of the integers are even.
Sort the array so that whenever A[i] is odd, i is odd; and whenever A[i] is even, i is even.
I managed to write code that worked but mine was almost like Java but in Kotlin (a common problem - I know).
I found this code in the comments:
fun sortArrayByParityII(A: IntArray): IntArray {
val even = A.filter { it % 2 == 0 }
val odd = A.filter { it % 2 == 1 }
return even.zip(odd).flatMap { listOf(it.first, it.second) }.toIntArray()
}
I know that the first couple of line do. They simple filter the array into even and odd arrays.
I even understand (after looking up) what the "zip" does.
What I can't figure out is what this does:
flatMap { listOf(it.first, it.second) }
Let's look step by step:
fun main() {
val list = (1..10).toList()
val even = list.filter { it % 2 == 0 } // [2, 4, 6, 8, 10]
val odd = list.filter { it % 2 == 1 } // [1, 3, 5, 7, 9]
val zipped = even.zip(odd) // [(2, 1), (4, 3), (6, 5), (8, 7), (10, 9)]
val flatten = zipped.flatMap { listOf(it.first, it.second) } // [2, 1, 4, 3, 6, 5, 8, 7, 10, 9]
}
flatMap takes a function which returns a list and inserts elements of this list in to initial list. So [(2, 1), (4, 3)] becomes [2, 1, 4, 3]
given the filtered lists:
odd = [1,3,5,7,9,...]
even = [2,4,6,8,...]
the zip function concatenates each single item of each list into a list of tuples:
even.zip(odd)
// [(2,1),(4,3),(6,5),(8,7),...]
flat map here is doing the operation on each item(tuple) and returns a single list, it picks first then second item in each tuple and adds them into a single list:
even.zip(add).flatMap { listOf(it.first, it.second) }
// [2, 1, 4, 3, 6, 5, 8, 7, 10, 9]