Tuesday, December 23, 2014

Arrays and Indexers in Kotlin



Today's post is about Arrays and Indexers in Kotlin. Here below you will find a very easy to follow program, that demonstrate arrays and indexer, by implementing some simple tasks that will make you grasp the idea of those 2 features real quick. The main goal of this post, is not really teaching arrays because, come on, you probably already know "all" about them, in fact, it is more to show you how you do that in Kotlin, in this case, compared to all other 22 languages on future posts, which essentially, is the real aim behind this blog.

By the way, if you missed my (not so) recent post (anymore), "New Series - Arrays and Indexers", check it out. It has more details about the following program, and a bunch of definitions for the concepts used on this, and the following, posts. Or you can check my previous posts about arrays in Java just to compare.

I encourage you to copy the code below and try it yourself, normally, all programs you find in this blog are source code complete, just paste it on your IDE and run it.

There is room for improvement of the code, using generics is one example, but Generics, Collections, lambdas, etc. will have their own "series" of posts.


package kotlinarrays

import java.util.Random

fun main(args: Array<String>) {
    // Single-dimensional Array(s)
    printTitle("Reverse Array Elements")

    // Declare and Initialize Array of Chars
    //val letters = Array<Char>(5, {c -> ' '})
    val letters = CharArray(5)
    letters[0] = 'A'
    letters[1] = 'E'
    letters[2] = 'I'
    letters[3] = 'O'
    letters[4] = 'U'

    printArrayChar(letters)
    val inverse_letters = reverseChar(letters)
    printArrayChar(inverse_letters)

    printTitle("Sort Integer Array Elements")

    // Declare and Initialize Array of Integers
    val numbers: IntArray = intArray(10, 8, 3, 1, 5)
    printArrayInt(numbers)
    val ordered_numbers = bubbleSortInt(numbers)
    printArrayInt(ordered_numbers)

    printTitle("Sort String Array Elements")

    // Declare and Initialize and Array of Strings
    val names: Array<String> = array(
        "Damian",
        "Rogelio",
        "Carlos",
        "Luis",
        "Daniel"
    )
    printArrayString(names)
    val ordered_names: Array<String> = bubbleSortString(names)
    printArrayString(ordered_names)

    // Multi-dimensional Array (Matrix row,column)

    printTitle("Transpose Matrix")

    /* Matrix row=2,col=3
     * A =  [6  4 24]
     *      [1 -9  8]
    */
    val matrix = array(array(6, 4, 24),
                       array(1, -9, 8))
    printMatrix(matrix)
    val transposed_matrix = transposeMatrix(matrix)
    printMatrix(transposed_matrix)

    // Jagged Array (Array-of-Arrays)

    printTitle("Upper Case Random Array & Graph Number of Elements")

    /*
     * Creating an array of string arrays using the String.Split method
     * instead of initializing it manually as follows:
     *
     * val text:Array<Array<String>> = array(
     *      array( "word1", "word2", "wordN" ),
     *      array( "word1", "word2", "wordM" ),
     *      ...
     *      )
     *
     * Text extract from: "El ingenioso hidalgo don Quijote de la Mancha"
     *
     */
    val text: Array<Array<String>> = array(
    "Hoy es el día más hermoso de nuestra vida, querido Sancho;".split(" "),
    "los obstáculos más grandes, nuestras propias indecisiones;".split(" "),
    "nuestro enemigo más fuerte, miedo al poderoso y nosotros mismos;".split(" "),
    "la cosa más fácil, equivocarnos;".split(" "),
    "la más destructiva, la mentira y el egoísmo;".split(" "),
    "la peor derrota, el desaliento;".split(" "),
    "los defectos más peligrosos, la soberbia y el rencor;".split(" "),
    "las sensaciones más gratas, la buena conciencia...".split(" ")
    )

    printJaggedArray(text)
    upperCaseRandomArray(text)
    printJaggedArray(text)
    graphJaggedArray(text)

    // Array Exceptions

    printTitle("Common Array Exceptions")

    //printCommonArrayExceptions(null) // Null-Safety
    printCommonArrayExceptions(text)

    // Accessing Class Array Elements through Indexer

    printTitle("Alphabets")

    val vowels = Alphabet(5)
    vowels[0] = 'a'
    vowels[1] = 'e'
    vowels[2] = 'i'
    vowels[3] = 'o'
    vowels[4] = 'u'

    println("\nVowels = {${charArray(vowels[0], vowels[1], vowels[2], vowels[3], vowels[4]).joinToString(",")}}")

    val en = Alphabet(0)
    en.init("abcdefghijklmnopqrstuvwxyz")
    println("English Alphabet = {${en.toString()}}")

    val en2 = Alphabet(0)
    en2.init(en.slice(9, 10))
    println("Alphabet Extract en[9..19] = {${en2}}")

    val word1 = charArray(en[6], en[14], en[14], en[3]).joinToString("")
    val word2 = charArray(en[1], en[24], en[4]).joinToString("")
    val word3 = charArray(en[4], en[21], en[4], en[17],
            en[24], en[14], en[13], en[4]).joinToString("")

    println("\n$word1 $word2, $word3!")
}

fun reverseChar(arr: CharArray): CharArray {
    val reversed = CharArray(arr.size())
    var i: Int = arr.size()-1
    for (j in 0..i) {
        reversed[i] = arr[j]
        i--
    }
    return reversed
}

fun bubbleSortInt(arr: IntArray): IntArray {
    var swap: Int
    for(i in arr.indices) {
        for(j in 0..arr.size() - 2) {
            if (arr[j] > arr[j + 1]) {
                swap = arr[j]
                arr[j] = arr[j + 1]
                arr[j + 1] = swap
            }
        }
    }
    return arr
}

fun bubbleSortString(arr: Array<String>): Array<String> {
    var swap: String
    for(i in arr.indices) {
        for(j in 0..arr.size() - 2) {
            if (arr[j][0] > arr[j + 1][0]) {
                swap = arr[j]
                arr[j] = arr[j + 1]
                arr[j + 1] = swap
            }
        }
    }
    return arr
}

fun transposeMatrix(m: Array<Array<Int>>): Array<Array<Int>> {
    /* Transposing a Matrix 2,3
     *
     * A =  [6  4 24]T [ 6  1]
     *      [1 -9  8]  [ 4 -9]
     *                 [24  8]
    */
    val transposed = Array(m[0].size(), {c -> Array(m.size(), {v -> 0})})
    for (i in m.indices) {
        for (j in m[0].indices) {
            transposed[j][i] = m[i][j]
        }
    }
    return transposed
}

fun upperCaseRandomArray(arr: Array<Array<String>>) {
    val r = Random()
    val i = r.nextInt(arr.size())
    for (j in arr[i].indices) {
        arr[i][j] = arr[i][j].toUpperCase()
    }
}

fun printArrayChar(arr: CharArray) {
    println("\nPrint Array Content ${arr.javaClass.getName()}[${arr.size()}]")

    for (i in arr.indices) {
        println(java.lang.String.format(" array [%2d] = %2s", i, arr[i]))
    }
}

fun printArrayInt(arr: IntArray) {
    println("\nPrint Array Content ${arr.javaClass.getName()}[${arr.size()}]")

    for (i in arr.indices) {
        println(java.lang.String.format(" array [%2d] = %2d", i, arr[i]))
    }
}

fun printArrayString(arr: Array<String>) {
    println("\nPrint Array Content ${arr.javaClass.getName()}[${arr.size()}]")

    for (i in arr.indices) {
        println(java.lang.String.format(" array [%2d] = %2s", i, arr[i]))
    }
}

fun printMatrix(m: Array<Array<Int>>) {
    println("\nPrint Matrix Content ${m.javaClass.getName()}[${m.size()},${m[0].size()}]")

    for(i in m.indices) {
        for(j in m[0].indices) {
            println(java.lang.String.format(" array [%2d,%2d] = %2d", i, j, m[i][j]))
        }
    }
}

fun graphJaggedArray(arr:Array<Array<String>>) {
    /* When using Arrays, we can use foreach instead of for:
     *
     * for (i in arr.indices)
     *   for (j in arr.indices)
     *
    */
    println("\nPrint Text Content ${arr.javaClass.getName()}")
    var lineCount = 1
    for(s in arr) {
        print(java.lang.String.format("Line%2s|", lineCount))
        for(w in s) {
            print(java.lang.String.format("%3s", '*'))
        }
        println(" (${s.size()})")
        lineCount += 1
    }
}

fun printJaggedArray(arr: Array<Array<String>>) {
    println("\nPrint Jagged Array Content ${arr.javaClass.getName()}")
    var line: StringBuilder
    for(i in arr.indices) {
        line = StringBuilder {}
        for(j in arr[i].indices) {
            line.append(' ').append(arr[i][j])
        }
        if (line.toString() == line.toString().toUpperCase())
            line.append(" <-- [UPPERCASED]")
        println(line)
    }
}

fun printCommonArrayExceptions(arr: Array<Array<String>>) {
    try {
        arr[100][100] = "hola"
    } catch(ex: ArrayIndexOutOfBoundsException) {
        println("\nException: \n${ex.javaClass.getName()}\n${ex.getMessage()}\n")
    } catch(ex: Exception) {
        println("\nException: \n${ex.javaClass.getName()}\n${ex.getMessage()}\n")
    }
}

fun printTitle(message: String) {
    println()
    println("=".repeat(54))
    println(message)
    println("=".repeat(54))
}


// Main Constructor and Array Field
class Alphabet (private val size: Int) {
    private var letters = CharArray(size)

    // Indexer Getter/Setter
    fun get(index: Int): Char = letters[index]
    fun set(index: Int, value: Char) {
        letters[index] = value.toString().toUpperCase().charAt(0)
    }

    //
    fun size() = letters.size()

    // Constructors
    // Classes in Kotlin can only have a single constructor.
    // Using methods instead.
    fun init(list: String) {
        letters = list.toUpperCase().toCharArray()
    }

    fun init(arr: CharArray) {
        letters = arr
    }

    // Overridden Method
    override fun toString(): String = letters.joinToString(".")

    // Method
    fun slice(start: Int, length: Int): CharArray {
        val result = CharArray(length)
        var i: Int = 0
        for(c in letters.slice(start..start+length-1)) {
            result[i++] = c
        }
        return result
    }
}


The output:




























































































Voilà, that's it. Next post in the following days.

No comments:

Post a Comment