In a 3x3 matrix representation, i can find the sum of both diagonals with one liners in Swift as below,
let array = [
[1, 2, 3],
[4, 5, 6],
[-7, 8, 9]
]
let d1 = array.enumerated().map({ $1[$0] }).reduce(0, +)
let d2 = array.reversed().enumerated().map({ $1[$0] }).reduce(0, +)
print(d1) // prints 15
print(d2) // prints 1
I am able to find map and reduce equivalents in Kotlin as flatMap and fold but couldn't find for enumerated.
How can we achieve similar with higher order functions in Kotlin?
Starting with this input:
val input: Array<Array<Int>> = arrayOf(
arrayOf(1, 2, 3),
arrayOf(4, 5, 6),
arrayOf(-7, 8, 9)
)
this is how I'd phrase the diagonal sums:
val mainDiagonalSum = input.indices
.map { input[it][it] }
.reduce(Int::plus)
val counterDiagonalSum = input.indices
.map { input[input.size - 1 - it][it] }
.reduce(Int::plus)
Note that this is an improvement over your solution because it doesn't have to create the reversed array. It improves the time complexity from O(n2) to O(n).
If you're dealing with large matrices, it would pay to reduce the space complexity from O(n) to O(1) as well, by using fold instead of reduce:
val mainDiagonalSum = input.indices
.fold(0) { sum, i -> sum + input[i][i] }
val counterDiagonalSum = input.indices
.fold(0) { sum, i -> sum + input[input.size - 1 - i][i] }
It looks like you're looking for withIndex
Related
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.
Is there any function (like fold, map, filter), which gets 2 arrays and lambda-function (for example multiplication) as parameters and returns third array?
I've used cycle for, but is there more beautiful method?
Yes, there is zip (nice example at the bottom of the page), see this (different) example:
fun main() {
val a = arrayOf( 1, 2, 3, 4 )
val b = arrayOf( 1, 2, 3, 4 )
val c = a.zip(b) { i, j -> i * j }
println(c)
}
which outputs
[1, 4, 9, 16]
There isn't a built in specifically but you can do this:
array1.zip(array2).map { (x,y) -> x*y }
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]
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]
I have a sequence of interleaved data (with fixed stride) and I'd like to reduce it to a single value for each "structure" (n*stride values to n values).
I could just use loop writing into the mutable list with selected step for reader index, but I'm looking for more functional and readable approach. Any thoughts?
For example:
Input sequence consists of RGB triplets (stride 3) and output is grayscale.
Imperative way is like:
fun greyscale(stream:List<Byte>):List<Byte>{
val out = ArrayList(stream.size / 3)
var i = 0; var o = 0
while(i < stream.size)
out[o++]=(stream[i++] + stream[i++] + stream[i++])/3
return out
}
How can I make something like that without explicitly implementing a function and mutable container, but purely on functional extensions like .map and so on?
Kotlin 1.2 (Milestone 1 was released yesterday) brings the chunked method on collections. It chunks up the collection into blocks of a given size. You can use this to implement your function:
fun greyscale(stream: List<Byte>): List<Byte> =
stream.chunked(3)
.map { (it.sum() / 3).toByte() }
A possible way would be grouping by the index of the elements (in this case /3) and mapping these groups to their sum.
stream.withIndex()
.groupBy { it.index / 3 }
.toSortedMap()
.values
.map { (it.sumBy { it.value } / 3).toByte() }
Also strictly functional, but using Rx, would be possible by using window(long)
Observable.from(stream)
.window(3)
.concatMap { it.reduce(Int::plus).toObservable() }
.map { (it / 3).toByte() }
Similar to #marstran's answer, in Kotlin 1.2 you can use chunked function, but providing the transform lambda to it:
fun greyscale(stream: List<Byte>): List<Byte> =
stream.chunked(3) { it.average().toByte() }
This variant has an advantage that it doesn't instantiate a new List for every triple, but rather creates a single List and reuses it during the entire operation.
Excludes remaining elements:
const val N = 3
fun greyscale(stream: List<Byte>) = (0 until stream.size / N)
.map { it * N }
.map { stream.subList(it, it + N).sum() / N }
.map(Int::toByte)
Output
[1, 2, 3, 4, 5, 6] => [2, 5]
[1, 2, 3, 4, 5] => [2]
Includes remaining elements:
const val N = 3
fun greyscale(stream: List<Byte>) = (0 until (stream.size + N - 1) / N)
.map { it * N }
.map { stream.subList(it, minOf(stream.size, it + N)).sum() / N }
.map(Int::toByte)
Output
[1, 2, 3, 4, 5, 6] => [2, 5]
[1, 2, 3, 4, 5] => [2, 3]
Best what I'm capable of is this:
fun grayscale(rgb:List<Byte>):List<Byte>
= rgb.foldIndexed(
IntArray(rgb.size / 3),
{ idx, acc, i ->
acc[idx / 3] = acc[idx / 3] + i; acc
}).map{ (it / 3).toByte() }
Output
in: [1, 2, 3, 4, 5, 6]
out: [2, 5]
And variations with ArrayList with add and last