Multidimensional '3D' Matrix in Kotlin - 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

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

Writing an addition visitor function in Kotlin

I'm trying to write a visitor function in Kotlin that adds two integers together. I've been working off of some sample code and I can't figure out what these .value or .visit functions are. It doesn't seem to be declared in the sample code, so I'm unsure how to declare it in my code. Whenever I compile the code, I get an error saying that value is an unresolved reference.
Relevant Kotlin code:
package backend
import org.antlr.v4.runtime.*
import grammar.*
abstract class Data
class IntData(val value: Int): Data() {
override fun toString(): String
= "Int($value)"
}
class Context(): HashMap<String, Data>() {
constructor(parent: Context): this() {
this.putAll(parent)
}
}
abstract class Expr {
abstract fun eval(scope: Context): Data
fun run(program: Expr) {
try {
val data = program.eval(Context())
println("=> ${data}")
} catch(e: Exception) {
println("[err] ${e}")
}
}
}
class IntLiteral(val value: Int): Expr() {
override fun eval(scope:Context): Data
= IntData(value)
}
enum class Op {
Add,
Sub,
Mul,
Div
}
class Arithmetic(
val op: Op,
val left: Expr,
val right: Expr): Expr() {
override fun eval(scope: Context): Data {
val x = (left.eval(scope) as IntData).value
val y = (right.eval(scope) as IntData).value
return IntData(
when(op) {
Op.Add -> x + y
Op.Mul -> x * y
Op.Sub -> x - y
Op.Div -> x / y
}
)
}
}
}
class Compiler: PLBaseVisitor<Expr>() {
val scope = mutableMapOf<String, Expr>()
override fun visitAddExpr(ctx: PLParser.AddExprContext): Expr {
val xValue = this.visit(ctx.x)
val yValue = this.visit(ctx.y)
val result = xValue.value + yValue.value
return IntLiteral(result)
}
}
Relevant Antlr Grammar:
expr : x=expr '+' y=expr # addExpr
| x=expr '-' y=expr # subExpr
| x=expr '*' y=expr # mulExpr
| x=expr '/' y=expr # divExpr
;
Code I'm trying to execute:
val test = """
x=1+2
print(x)
"""
fun parse(source: String): PLParser.ProgramContext {
val input = CharStreams.fromString(source)
val lexer = PLLexer(input)
val tokens = CommonTokenStream(lexer)
val parser = PLParser(tokens)
}
val testTree = parse(source1)
val testTree = parse(source1)
fun execute(program: Expr?) {
if(program == null) {
println("Program is null.")
return
}
try {
val data = program.eval(Context())
println("> ${data}")
} catch(e: Exception) {
println("[err] ${e}")
}
}
execute(testProgram)
Code from sample:
data class NodeValue(val value: Int)
val visitor = object: CalcBaseVisitor<NodeValue>() {
override fun visitAddition(ctx: CalcParser.AdditionContext): NodeValue {
val xValue = this.visit(ctx.x)
val yValue = this.visit(ctx.y)
return NodeValue(xValue.value + yValue.value)
}
override fun visitValue(ctx: CalcParser.ValueContext): NodeValue {
val lexeme = ctx.Number().getText()
return NodeValue(lexeme.toInt())
}
}
You don’t show the code for your program.eval() method.
The eval function would need to create an instance of your Visitor. (You’ve done that and called it visitor).
You also have the root expr node in you program variable.
Now you would have your visitor “visit” that node and save the return value:
val nodeVal = visitor.visit(program)
At that point nodeVal.value will have the result of visiting that expression.
note: since you’re doing the evaluation in your visitor, there’s not really any use for your Arithmetic class (unless you refactor your visitor to use it instead of just doing the math, but I don’t see much value in that as the visitor is already pretty easy to read).

Concise conversion of List<List<Double>> to Array<DoubleArray>?

I wrote this in Kotlin:
fun fromLists(cells: List<List<Double>>): Matrix {
return Matrix(cells.stream()
.map { x -> x.toDoubleArray() }
.toArray { i: Int -> Array(i, { k: Int -> DoubleArray(k) }) } )
}
Is there any way to reduce repetition in this code?
(Matrix itself is uninteresting, it just wraps an Array<DoubleArray>)
val ex1: Array<DoubleArray> = cells.map { it.toDoubleArray() }.toTypedArray()
// this should be faster, it doesn't create extra List like the previous example
val ex2: Array<DoubleArray> = Array(cells.size) { i -> cells[i].toDoubleArray() }

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

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)

Kotlin: Convert large List to sublist of set partition size

I'm looking for a function equivalent to Groovy's collate which would partition a large List into batches for processing. I did see subList which could be adapted into a similar function but wanted to check and make sure I wasn't missing an in-built or crazy simple alternative to rolling my own.
With Kotlin 1.3, according to your needs, you may choose one of the following ways to solve your problem.
#1. Using chunked
fun main() {
val list = listOf(2, 4, 3, 10, 8, 7, 9)
val newList = list.chunked(2)
//val newList = list.chunked(size = 2) // also works
print(newList)
}
/*
prints:
[[2, 4], [3, 10], [8, 7], [9]]
*/
#2. Using windowed
fun main() {
val list = listOf(2, 4, 3, 10, 8, 7, 9)
val newList = list.windowed(2, 2, true)
//val newList = list.windowed(size = 2, step = 2, partialWindows = true) // also works
println(newList)
}
/*
prints:
[[2, 4], [3, 10], [8, 7], [9]]
*/
NOTE: For Kotlin 1.2 and newer, please see the chunked and windowed functions that are now in the standard library. There is no need for a custom solution.
Here is an implementation of a lazy batching extension function which will take a collection, or anything that can become a Sequence and return a Sequence of List each of that size, with the last one being that size or smaller.
Example usage to iterate a list as batches:
myList.asSequence().batch(5).forEach { group ->
// receive a Sequence of size 5 (or less for final)
}
Example to convert batches of List to Set:
myList.asSequence().batch(5).map { it.toSet() }
See the first test case below for showing the output given specific input.
Code for the function Sequence<T>.batch(groupSize):
public fun <T> Sequence<T>.batch(n: Int): Sequence<List<T>> {
return BatchingSequence(this, n)
}
private class BatchingSequence<T>(val source: Sequence<T>, val batchSize: Int) : Sequence<List<T>> {
override fun iterator(): Iterator<List<T>> = object : AbstractIterator<List<T>>() {
val iterate = if (batchSize > 0) source.iterator() else emptyList<T>().iterator()
override fun computeNext() {
if (iterate.hasNext()) setNext(iterate.asSequence().take(batchSize).toList())
else done()
}
}
}
Unit tests proving it works:
class TestGroupingStream {
#Test fun testConvertToListOfGroupsWithoutConsumingGroup() {
val listOfGroups = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10).asSequence().batch(2).toList()
assertEquals(5, listOfGroups.size)
assertEquals(listOf(1,2), listOfGroups[0].toList())
assertEquals(listOf(3,4), listOfGroups[1].toList())
assertEquals(listOf(5,6), listOfGroups[2].toList())
assertEquals(listOf(7,8), listOfGroups[3].toList())
assertEquals(listOf(9,10), listOfGroups[4].toList())
}
#Test fun testSpecificCase() {
val originalStream = listOf(1,2,3,4,5,6,7,8,9,10)
val results = originalStream.asSequence().batch(3).map { group ->
group.toList()
}.toList()
assertEquals(listOf(1,2,3), results[0])
assertEquals(listOf(4,5,6), results[1])
assertEquals(listOf(7,8,9), results[2])
assertEquals(listOf(10), results[3])
}
fun testStream(testList: List<Int>, batchSize: Int, expectedGroups: Int) {
var groupSeenCount = 0
var itemsSeen = ArrayList<Int>()
testList.asSequence().batch(batchSize).forEach { groupStream ->
groupSeenCount++
groupStream.forEach { item ->
itemsSeen.add(item)
}
}
assertEquals(testList, itemsSeen)
assertEquals(groupSeenCount, expectedGroups)
}
#Test fun groupsOfExactSize() {
testStream(listOf(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15), 5, 3)
}
#Test fun groupsOfOddSize() {
testStream(listOf(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18), 5, 4)
testStream(listOf(1,2,3,4), 3, 2)
}
#Test fun groupsOfLessThanBatchSize() {
testStream(listOf(1,2,3), 5, 1)
testStream(listOf(1), 5, 1)
}
#Test fun groupsOfSize1() {
testStream(listOf(1,2,3), 1, 3)
}
#Test fun groupsOfSize0() {
val testList = listOf(1,2,3)
val groupCountZero = testList.asSequence().batch(0).toList().size
assertEquals(0, groupCountZero)
val groupCountNeg = testList.asSequence().batch(-1).toList().size
assertEquals(0, groupCountNeg)
}
#Test fun emptySource() {
listOf<Int>().asSequence().batch(1).forEach { groupStream ->
fail()
}
}
}
A more simplistic/functional-style solution would be
val items = (1..100).map { "foo_${it}" }
fun <T> Iterable<T>.batch(chunkSize: Int) =
withIndex(). // create index value pairs
groupBy { it.index / chunkSize }. // create grouping index
map { it.value.map { it.value } } // split into different partitions
items.batch(3)
Note 1: Personally I'd prefer partition as a method name here, but it's already present in Kotlin's stdlib to separate a lists into 2 parts given a predicate.
Note 2: The the iterator solution from Jayson may scale better than this solution for large collections.
In Kotlin 1.2 M2 and later you can use chunked and windowed (see Kotlin 1.2 M2 is out | Kotlin Blog). Note that there are Sequence variances too (see kotlin.sequences - Kotlin Programming Language).
For versions of Kotlin prior to 1.2 M2 I recommend using Lists.partition(List, int) from google-guava (it uses java.util.List.subList(int, int)):
If you are unfamiliar with Guava see CollectionUtilitiesExplained · google/guava Wiki for more details.
You can create your own Kotlin extension function for it if you want:
fun <T> List<T>.collate(size: Int): List<List<T>> = Lists.partition(this, size)
If you want an extension function for mutable lists then in a separate Kotlin file (to avoid platform declaration clashes):
fun <T> MutableList<T>.collate(size: Int): List<MutableList<T>> = Lists.partition(this, size)
If you want something lazy loaded like in Jayson Minard's answer you can use Iterables.partition(Iterable, int). You might also be interested in Iterables.paddedPartition(Iterable, int) if you want to pad the last sublist if it is smaller than the specified size. These return Iterable<List<T>> (I don't see much point in making it Iterable<Iterable<T>> as subList returns an efficient view).
If for some reason you don't want to depend on Guava you can roll your own pretty easily using the subList function you mentioned:
fun <T> List<T>.collate(size: Int): List<List<T>> {
require(size > 0)
return if (isEmpty()) {
emptyList()
} else {
(0..lastIndex / size).map {
val fromIndex = it * size
val toIndex = Math.min(fromIndex + size, this.size)
subList(fromIndex, toIndex)
}
}
}
or
fun <T> List<T>.collate(size: Int): Sequence<List<T>> {
require(size > 0)
return if (isEmpty()) {
emptySequence()
} else {
(0..lastIndex / size).asSequence().map {
val fromIndex = it * size
val toIndex = Math.min(fromIndex + size, this.size)
subList(fromIndex, toIndex)
}
}
}
Dummy Array
for (i in 0..49){
var data="java"
}
array.add(data)
Used:
var data=array?.chunked(15)
kotlin's method
There is unfortunately no built-in function for that yet and while functional and Sequence-based implementations from other answers look nice, if you just need is List of Lists, I'd suggest writing a little bit of ugly, imperative, but performant code.
This is my final result:
fun <T> List<T>.batch(chunkSize: Int): List<List<T>> {
if (chunkSize <= 0) {
throw IllegalArgumentException("chunkSize must be greater than 0")
}
val capacity = (this.size + chunkSize - 1) / chunkSize
val list = ArrayList<ArrayList<T>>(capacity)
for (i in 0 until this.size) {
if (i % chunkSize == 0) {
list.add(ArrayList(chunkSize))
}
list.last().add(this.get(i))
}
return list
}