List<List<Char>> + List<Char> = List<Any>? - kotlin

I have a below code which works.
class ListManipulate(val list: List<Char>, val blockCount: Int) {
val result: MutableList<List<Char>> = mutableListOf()
fun permute(sequence: List<Int> = emptyList(), start: Int = 0, count: Int = blockCount) {
if (count == 0) {
result.add(constructSequence(sequence))
return
}
for (i in start .. list.size - count) {
permute(sequence + i, i + 1, count - 1)
}
}
private fun constructSequence(sequence: List<Int>): List<Char> {
var result = emptyList<Char>()
for (i in sequence) {
result += list[i]
}
return result
}
}
However, when I change the result from MutableList to normal List, i.e.
var result: List<List<Char>> = emptyList()
// ...
result += constructSequence(sequence)
I got this error Type mismatch. Require: List<List<Char>>; Found: List<Any>
The full code as below
class ListManipulate(val list: List<Char>, val blockCount: Int) {
var result: List<List<Char>> = emptyList()
fun permute(sequence: List<Int> = emptyList(), start: Int = 0, count: Int = blockCount) {
if (count == 0) {
result += constructSequence(sequence)
return
}
for (i in start .. list.size - count) {
permute(sequence + i, i + 1, count - 1)
}
}
private fun constructSequence(sequence: List<Int>): List<Char> {
var result = emptyList<Char>()
for (i in sequence) {
result += list[i]
}
return result
}
}
Why result + constructSequence(sequence) would result in List<Any> instead of List<List<Char>>?
Is there a way I could still use the normal List> and not the mutable list?

CTRL + click on the + in IDEA, you'll see that it takes you to the following function:
/**
* Returns a list containing all elements of the original collection and then all elements of the given [elements] collection.
*/
public operator fun <T> Collection<T>.plus(elements: Iterable<T>): List<T> {
/* ... */
}
Which means that you add all the individual elements of elements to the receiver. That is, you'll add all T's to the List<List<T>>. Since List<T> is not T, you'll get List<Any> as a result.

The problem is that += is overloaded. If it sees an Iterable, Array or Sequence it behaves differently. You have to explicitly use plusElement() to achieve the behaviour you intend.
Consider the following code.:
class ListManipulate(val list: List<Char>, val blockCount: Int) {
var result: List<List<Char>> = emptyList()
fun permute(sequence: List<Int> = emptyList(), start: Int = 0, count: Int = blockCount) {
if (count == 0) {
result = result.plusElement(constructSequence(sequence))
return
}
for (i in start..list.size - count) {
permute(sequence + i, i + 1, count - 1)
}
}
private fun constructSequence(sequence: List<Int>): List<Char> =
List(sequence.size, { i -> list[sequence[i]] })
}
PS: I also took the liberty to update your constructSequence() to something more concise.
Btw: += uses addAll internally.
/**
* Returns a list containing all elements of the original collection and then all elements of the given [elements] collection.
*/
public operator fun <T> Collection<T>.plus(elements: Iterable<T>): List<T> {
if (elements is Collection) {
val result = ArrayList<T>(this.size + elements.size)
result.addAll(this)
result.addAll(elements)
return result
} else {
val result = ArrayList<T>(this)
result.addAll(elements)
return result
}
}
Side note: you can also do:
result.toMutableList().add(constructSequence(sequence))
It is fine to return a MutableList, the only difference really is that the List interface doesnt have the manipulation methods. Internally both are represented by an ArrayList
#SinceKotlin("1.1")
#kotlin.internal.InlineOnly
public inline fun <T> List(size: Int, init: (index: Int) -> T): List<T> = MutableList(size, init)

Related

Using abstract with Binary Search in Kotlin

I have a task in kotlin to use an abstract class, and the example was about binary search
so it shows an error message in the run.
first class is non
first class there's a non abstract class but it a parent class
second an abstract class the inherite the parent classes
third a class that display the operation
and that's my code:
open class BinarySearch() {
fun BinarySearchFunction(arr: Array<Int>, l: Int, r: Int, x: Int): Int {
if(r >= 1) {
var mid:Int=1+(r-1)/2
if (arr[mid] == x) {
return mid
}
if(arr[mid] > x){
return BinarySearchFunction(arr,l,mid-1,x)
}
return BinarySearchFunction(arr,mid+1,r,x)
}
return -1
}
open fun displayMassage(Massage:String){}
}
abstract class print(): BinarySearch() {
fun Function() {
var obj = BinarySearch()
var a = arrayOf<Int>(2, 3, 4, 10, 40)
var n = a.size
var x = 10
var result = obj.BinarySearchFunction(a, 0, n - 1, x)
if(result == -1)
println("Element not present")
else
println("Element found at index $result")
}
}
class display():print(){
override fun displayMassage(massage:String){
println(massage)
}
}
fun main() {
var dis=display()
dis.displayMassage("The Binary Search : ")
dis.Function()
}
You have an error in the implementation of the algorithm causing it to do infinite recursion.
I believe
var mid: Int = 1 + (r - 1) / 2
actually needs to be
var mid: Int = l + (r - 1) / 2

Is there a function to search in a ArrayList from a position?

I read carefully the ArrayList documentation in Kotlin and apparently there is no way to search a value in ArrayList starting from a pointer. The alternative is write your own function iterating the right elements in ArrayList and testing the condition.
So I've programmed the following code:
fun <T> ArrayList<T>.findNext(cond: (T) -> Boolean, p: Int = 0): Int {
for (i in p..this.lastIndex)
if (cond(this[i])) return i
return -1
}
data class Person (
var name: String,
var age: Int
)
fun main() {
var v = arrayListOf<Person>()
v.add(Person("Paul", 22))
v.add(Person("Laura", 24))
v.add(Person("Paul", 50))
v.add(Person("Mary", 24))
println(v.findNext({it.name=="Paul"})) // 0
println(v.findNext({it.name=="Paul"}, 1)) // 2
println(v.findNext({it.name=="Paul"}, 3)) // -1
}
Is there something better than this?
You can avoid any intermediate collections:
inline fun <T> List<T>.findNext(p: Int = 0, cond: (T) -> Boolean) =
listIterator(p).withIndex().asSequence().find { cond(it.value) }?.let { it.index + p }
By swapping the arguments you can call it like this:
println(v.findNext {it.name=="Paul"}) // 0
println(v.findNext(1) {it.name=="Paul"}) // 2
println(v.findNext(3) {it.name=="Paul"}) // null
fun main() {
var v = arrayListOf<Person>()
v.add(Person("Paul", 22))
v.add(Person("Laura", 24))
v.add(Person("Paul", 50))
v.add(Person("Mary", 24))
println(v.findNext({ it.name == "Paul" },0))//IndexedValue(index=0, value=Person(name=Paul, age=22))
println(v.findNext({ it.name == "Paul" },2))//IndexedValue(index=2, value=Person(name=Paul, age=50))
println(v.findNext({ it.name == "Paul" },3))//null
}
private fun <T> List<T>.findNext(cond: (T) -> Boolean, position: Int): IndexedValue<T>? {
return withIndex().filter { it.index >= position }.firstOrNull { cond(it.value) }
}
maybe use withIndex and a filter ?
val arrayNames = listOf<String>("Paul", "Ann", "Paul", "Roger","Peter")
arrayNames.withIndex().filter {
it.value == "Paul" //value contains the original name
}.forEach{
println(it.index) //indext contains the position.
}
this will give you the output 0 and 2
for your case (person object instead of String) you will use
it.value.name == "Paul"

Convert collection of numbers to range formatted string with Kotlin

I have a very large list of numbers. I need to pass this list of numbers as a URL query parameter. Since these lists can get so large, it could potentially cause the request URL to exceed the allowed length of a URL; also, it's a bit difficult to debug a string of sequential numbers (E.G. 1,2,3,..,500,782). To remedy these issues, I would like to convert the sequential number list string to one that is formatted using a range notation (E.G. -5..-3,1..500,782). How do I create this range notation string using Kotlin and how do I parse the string back to a collection of numbers also using Kotlin?
This will convert a Collection<Int> to a string that uses the "range notation" specified:
fun Collection<Int>.toRangesString(): String {
if (this.isEmpty()) {
return ""
}
if (this.size <= 2) {
return this.toSortedSet().joinToString(",")
}
val rangeStrings = mutableListOf<String>()
var start: Int? = null
var prev: Int? = null
for (num in this.toSortedSet()) {
if (prev == null) {
start = num
prev = num
continue
}
if (num != (prev + 1)) {
_addRangeString(rangeStrings, start!!, prev)
start = num
prev = num
continue
}
prev = num
}
if (start != null) {
_addRangeString(rangeStrings, start, prev!!)
}
return rangeStrings.joinToString(",")
}
private fun _addRangeString(rangeStrings: MutableList<String>, start: Int, prev: Int) {
rangeStrings.add(
when {
(start == prev) -> start.toString()
((start + 1) == prev) -> "${start},${prev}"
else -> "${start}..${prev}"
}
)
}
...and this will parse those range notated strings into a Set<Int>:
fun parseRangesString(str: String): Set<Int> {
if (str.isBlank()) {
return setOf()
}
val ranges = str.trim().split(",")
val numbers = mutableListOf<Int>()
for (range in ranges) {
if (range.contains("..")) {
val (start, end) = range.split("..")
numbers.addAll(start.toInt()..end.toInt())
continue
}
numbers.add(range.toInt())
}
return numbers.toSet()
}
...and, finally, even better than using a huge collection of numbers, you can use Kotlin's IntRange (or LongRange) class:
fun toIntRanges(str: String): Collection<IntRange> = _toRanges(str, ::_createIntRange)
fun toLongRanges(str: String): Collection<LongRange> = _toRanges(str, ::_createLongRange)
private fun <T : ClosedRange<*>> _toRanges(str: String, createRange: (start: String, end: String) -> T): Collection<T> {
if (str.isBlank()) {
return listOf()
}
val rangeStrs = str.trim().split(",")
val ranges = mutableListOf<T>()
for (rangeStr in rangeStrs) {
if (rangeStr.contains("..")) {
val (start, end) = rangeStr.split("..")
ranges.add(createRange(start, end))
continue
}
ranges.add(createRange(rangeStr, rangeStr))
}
return ranges.toList()
}
private fun _createIntRange(start: String, end: String) = IntRange(start.toInt(), end.toInt())
private fun _createLongRange(start: String, end: String) = LongRange(start.toLong(), end.toLong())

How can I take varying chunks out of a Kotlin Sequence?

If I have a Kotlin sequence, every invocation of take(n) restarts the sequence.
val items = generateSequence(0) {
if (it > 9) null else it + 1
}
#Test fun `take doesn't remember position`() {
assertEquals(listOf(0, 1), items.take(2).toList())
assertEquals(listOf(0, 1, 2), items.take(3).toList())
}
Is there an easy way of write say, another(n) such that
#Test fun `another does remember position`() {
assertEquals(listOf(0, 1), items.another(2).toList())
assertEquals(listOf(2, 3, 4), items.another(3).toList())
}
I suppose that I have to have something that isn't the Sequence to keep the state, so maybe what I'm actually asking for is a nice definition of fun Iterator<T>.another(count: Int): List<T>
Sequence does not remember its position, but its iterator does remember:
val iterator : Iterator<Int> = items.iterator()
Now all you need is something like take(n) but for Iterator<T>:
public fun <T> Iterator<T>.another(n: Int): List<T> {
require(n >= 0) { "Requested element count $n is less than zero." }
if (n == 0) return emptyList()
var count = 0
val list = ArrayList<T>(n)
for (item in this) {
list.add(item)
if (++count == n)
break
}
return list
}
What about this:
#Test
fun `another does remember position`() {
val items: Sequence<Int> = generateSequence(0) {
if (it > 9) null else it + 1
}
val (first, rest) = items.another(2)
assertEquals(listOf(0, 1), first.toList())
assertEquals(listOf(2, 3, 4), rest.another(3).first.toList())
}
fun <T> Sequence<T>.another(n: Int): Pair<Sequence<T>, Sequence<T>> {
return this.take(n) to this.drop(n)
}
To answer the last part of your question:
I suppose that I have to have something that isn't the Sequence to keep the state, so maybe what I'm actually asking for is a nice definition of fun Iterator.another(count: Int): List
One such implementation would be:
fun <T> Iterator<T>.another(count: Int): List<T> {
val collectingList = mutableListOf<T>()
while (hasNext() && collectingList.size < count) {
collectingList.add(next())
}
return collectingList.toList()
}
This passes your test if you use the iterator produced by the sequence:
#Test
fun `another does remember position`() {
val items = generateSequence(0) {
if (it > 9) null else it + 1
}.iterator() //Use the iterator of this sequence.
assertEquals(listOf(0, 1), items.another(2))
assertEquals(listOf(2, 3, 4), items.another(3))
}
To me what you've described is an iterator, since it's something that allows you to go over a collection or sequence etc. but also remember its last position.
NB the implementation above wasn't written to take into consideration what should happen for non-positive counts passed in, and if the count is larger than what's left to iterate over you'll be returned a list which has smaller size than n. I suppose you could consider this an exercise for yourself :-)
Sequence does not remember its position, but its iterator does remember:
val iterator : Iterator<Int> = items.iterator()
Unfortunately there is no take(n) for an iterator, so to use the one from stdlib you need to wrap iter into an Iterable:
val iterable : Iterable<Int> = items.iterator().asIterable()
fun <T> Iterator<T>.asIterable() : Iterable<T> = object : Iterable<T> {
private val iter = this#asIterable
override fun iterator() = iter
}
That makes itareble.take(n) remember its position, but unfortunately there is a of-by-one error because the standard .take(n) asks for one element too many:
public fun <T> Iterable<T>.take(n: Int): List<T> {
require(n >= 0) { "Requested element count $n is less than zero." }
if (n == 0) return emptyList()
if (this is Collection<T>) {
if (n >= size) return toList()
if (n == 1) return listOf(first())
}
var count = 0
val list = ArrayList<T>(n)
for (item in this) {
if (count++ == n)
break
list.add(item)
}
return list.optimizeReadOnlyList()
}
That can be fixed with a little tweak:
public fun <T> Iterable<T>.take2(n: Int): List<T> {
require(n >= 0) { "Requested element count $n is less than zero." }
if (n == 0) return emptyList()
if (this is Collection<T>) {
if (n >= size) return toList()
if (n == 1) return listOf(first())
}
var count = 0
val list = ArrayList<T>(n)
for (item in this) {
list.add(item)
//count++
if (++count == n)
break
}
return list
}
Now both of you tests pass:
#Test fun `take does not remember position`() {
assertEquals(listOf(0, 1), items.take2(2).toList())
assertEquals(listOf(0, 1, 2), items.take2(3).toList())
}
#Test fun `another does remember position`() {
assertEquals(listOf(0, 1), iter.take2(2).toList())
assertEquals(listOf(2, 3, 4), iter.take2(3).toList())
}
You could create a function generateStatefulSequence which creates a sequence which keeps its state by using a second sequence's iterator to provide the values.
The iterator is captured in the closure of that function.
On each iteration the seed lambda ({ i.nextOrNull() }) of the returned sequence starts off with the next value provided by the iterator.
// helper
fun <T> Iterator<T>.nextOrNull() = if(hasNext()) { next() } else null
fun <T : Any> generateStatefulSequence(seed: T?, nextFunction: (T) -> T?): Sequence<T> {
val i = generateSequence(seed) {
nextFunction(it)
}.iterator()
return generateSequence(
seedFunction = { i.nextOrNull() },
nextFunction = { i.nextOrNull() }
)
}
Usage:
val s = generateStatefulSequence(0) { if (it > 9) null else it + 1 }
println(s.take(2).toList()) // [0, 1]
println(s.take(3).toList()) // [2, 3, 4]
println(s.take(10).toList()) // [5, 6, 7, 8, 9, 10]
Try it out
Here is a nice definition of fun Iterator<T>.another(count: Int): List<T> as requested:
fun <T> Iterator<T>.another(count: Int): List<T> =
if (count > 0 && hasNext()) listOf(next()) + this.another(count - 1)
else emptyList()
As another workaround (similar to the suggestion by Willi Mentzel above) would be to create a asStateful() extension method that converts any sequence into a one that will remember the position, by wrapping it into an Iterable that always yields the same iterator.
class StatefulIterable<out T>(wrapped: Sequence<T>): Iterable<T> {
private val iterator = wrapped.iterator()
override fun iterator() = iterator
}
fun <T> Sequence<T>.asStateful(): Sequence<T> = StatefulIterable(this).asSequence()
Then you can do:
val items = generateSequence(0) {
if (it > 9) null else it + 1
}.asStateful()
#Test fun `stateful sequence does remember position`() {
assertEquals(listOf(0, 1), items.take(2).toList())
assertEquals(listOf(2, 3, 4), items.take(3).toList())
}
Try it here: https://pl.kotl.in/Yine8p6wn

Multidimensional '3D' Matrix in Kotlin

What will be the syntax of creating a 3D matrix in Kotlin. It's Java equivalent is as follows:
public static final int[][][] data = {{{0,0},{0}},{{0,1},{0}},{{1,0},{0}},{{1,1},{1}}};
Thanks
Edit:
Also how can I print the Kotlin code using the simple println?
When working with arrays in most languages I find it nice to create a helper class, rather than working directly with an int[][][] type. This way you can ensure certain invariants hold (such as all rows having the same length), and ensure better data locality. It can also let you efficiently implement certain operations such as slicing, sub-matrices, transpose etc.
My usual set of classes would look something like this for 3D. (though I'd probably template on the stored type, rather than hard code it for Int)
Its pretty incomplete, but the main at the end shows how many of the functions work.
But to show how you can create a 3D array from values you can do
val V = /* .. as in mEQ5aNLrK3lqs3kfSa5HbvsTWe0nIu's answer */
val M = Matrix3D(NX,NY,NZ).transform( { v, ix, iy, iz -> V[ix][iy][iz] } )
Further examples are
fun main(args: Array<String>) {
// Create an empty matrix
val v = Matrix3D(4,4,2);
// We can access elements via [a,b,c] or [a][b][c]
v[0,1,1] = 7;
print(v)
println("v[0,1,1]=" + v[0,1,1])
println("v[0][1][1]=" + v[0][1][1])
println("-----")
// Make the matrix a little more interesting
v.transform({ w,ix,iy,iz -> ix+iy+iz})
print(v)
println("-----")
// Transform just the slice with ix=2
// Slices are fast, as they copy no elements.
// but if you change them you change the original
v[2].transform({w,iy,iz -> w+3})
print(v)
// If you dont want to change the original you can always
// create an independent copy
print(v[2].bake().transform({w,iy,iz -> w-3}))
println("-----")
// W is the slice of v with ix=0
// Can easily extend the slicing options to allow slicing along
// any axis - I'd like to add v[_,1,_] to mean the slice with iy=1
// but I've not got to that yet.
val W = v[0]
print("W=\n")
print(v[0])
print("W^T=\n")
// Fast transpose, no elements are copied.
val WT=v[0].transpose()
print(WT)
// Changing the transpose slice writes back into the original
WT[1,1]=5
print(V)
}
fun print(M:Matrix3D) {
for(iz in 0..(M.nz-1)) {
for(iy in 0..(M.ny-1)) {
for(ix in 0..(M.nx-1)){
print("%d ".format(M[ix,iy,iz]))
}
print("\n")
}
print("\n")
}
}
fun print(M:Matrix2D) {
for(iy in 0..(M.ny-1)) {
for(ix in 0..(M.nx-1)){
print("%d ".format(M[ix,iy]))
}
print("\n")
}
}
The library code looks like this:
class Matrix1D(
val v:Array<Int>,
val nx:Int,
val offset:Int,
val xstride:Int) {
// TODO: Check that the nx,offset,strides etc are valid
constructor(nx:Int) : this(Array(nx,{i->0}), nx, 0, 1) {
}
fun offsetof(ix:Int):Int {
return offset + ix*xstride
}
operator fun get(ix:Int): Int {
return v[offsetof(ix)]
}
operator fun set(ix:Int, v:Int) {
this.v[offsetof(ix)] = v
}
fun reverse() : Matrix1D {
return Matrix1D(v, nx, offsetof(nx-1), -xstride)
}
fun submatrix(startx:Int, newNX:Int) : Matrix1D {
return Matrix1D(v,newNX,offsetof(startx), xstride)
}
fun transform(body: (Int, Int) -> Int ) {
for(ix in 0..(nx-1)){
this[ix] = body(this[ix], ix)
}
}
fun bake() : Matrix1D {
val rv = Matrix1D(nx);
for(ix in 0..(nx-1)) {
rv[ix] = this[ix]
}
return rv
}
}
class Matrix2D(
val v:Array<Int>,
val nx:Int, val ny:Int,
val offset:Int,
val xstride:Int, val ystride:Int) {
// TODO: Check that the nx,ny,offset,strides etc are valid
constructor(nx:Int, ny:Int) : this(Array(nx*ny,{i->0}), nx, ny, 0, 1, nx ) {
}
fun offsetof(ix:Int,iy:Int): Int {
return offset + ix*xstride + iy*ystride
}
operator fun get(ix:Int,iy:Int): Int {
return v[offsetof(ix,iy)]
}
operator fun set(ix:Int,iy:Int,v:Int) {
this.v[offsetof(ix,iy)] = v
}
operator fun get(ix:Int): Matrix1D {
return Matrix1D(v, ny, offsetof(ix,0), ystride)
}
fun transpose(): Matrix2D {
return Matrix2D(v,ny,nx,offset,ystride,xstride)
}
fun submatrix(startx:Int, starty:Int, newNX:Int, newNY:Int) : Matrix2D {
return Matrix2D(v,newNX,newNY,offsetof(startx,starty), xstride, ystride)
}
fun transform(body: (Int, Int, Int) -> Int ) {
for(iy in 0..(ny-1)) {
for(ix in 0..(nx-1)){
this[ix,iy] = body(this[ix,iy], ix,iy)
}
}
}
fun bake() : Matrix2D {
val rv = Matrix2D(nx,ny);
for(ix in 0..(nx-1)) {
for(iy in 0..(ny-1)) {
rv[ix,iy] = this[ix,iy]
}
}
return rv
}
}
class Matrix3D(
val v:Array<Int>,
val nx:Int, val ny:Int, val nz:Int,
val offset:Int,
val xstride:Int, val ystride:Int, val zstride:Int) {
// TODO: Check that the nx,ny,nz,offset,strides etc are valid
constructor(nx:Int, ny:Int, nz:Int) : this(Array(nx*ny*nz,{i->0}), nx, ny, nz, 0, 1, nx, nx*ny ) {
}
operator fun get(ix:Int,iy:Int,iz:Int): Int {
return v[offset + ix*xstride + iy*ystride + iz*zstride]
}
operator fun set(ix:Int,iy:Int,iz:Int, v:Int) {
this.v[offset + ix*xstride + iy*ystride + iz*zstride] = v
}
operator fun get(ix:Int): Matrix2D {
return Matrix2D(v, ny, nz, offset + ix*xstride, ystride, zstride )
}
fun transform(body: (Int, Int, Int, Int) -> Int ) {
for(iz in 0..(nz-1)) {
for(iy in 0..(ny-1)) {
for(ix in 0..(nx-1)){
this[ix,iy,iz] = body(this[ix,iy,iz], ix,iy,iz)
}
}
}
}
fun bake() : Matrix3D {
val rv = Matrix3D(nx,ny,nz);
for(ix in 0..(nx-1)) {
for(iy in 0..(ny-1)) {
for(iz in 0..(nz-1)){
rv[ix,iy,iz] = this[ix,iy,iz]
}
}
}
return rv
}
}
Kotlin currently does not support array literals.
You can use a combination of arrayOf() and intArrayOf():
val data = arrayOf(
arrayOf(intArrayOf(0, 0), intArrayOf(0)),
arrayOf(intArrayOf(0, 1), intArrayOf(0)),
arrayOf(intArrayOf(1, 0), intArrayOf(0)),
arrayOf(intArrayOf(1, 1), intArrayOf(1))
)
You can cut down a little bit on the verbosity using import aliasing if needed:
import kotlin.arrayOf as arr
import kotlin.intArrayOf as iarr
val data = arr(
arr(iarr(0, 0), iarr(0)),
arr(iarr(0, 1), iarr(0)),
arr(iarr(1, 0), iarr(0)),
arr(iarr(1, 1), iarr(1))
)
Also note that you can auto-convert Java code to Kotlin
in IntelliJ IDEA: copy Java code into a Kotlin file, a confirmation prompt will open.
online: using http://try.kotlinlang.org.
Using Multik
Multik Multidimensional array library for Kotlin.
Syntax for creating 3D array
mk.d3array(2, 2, 3) { it * it }
//output
/*[[[0, 1, 4],
[9, 16, 25]],
[[1, 0, 0],
[1, 1, 1]]]
*/
Note:Multik supports up to 4 dimensions
The Multik project’s GitHub repository
For more info check Jetbrain blog post