kotlin koans examples

Overview

Kotlin Koans

Build

Build Status Kotlin Maven Central Junit Guava

--->>> Repo: Getting Started Kotlin <<<---

--->>> Repo: Problems Kotlin <<<---

--->>> Repo: GameBoy Emulator Enviroment <<<---

--->>> Repo: Kotlin Mobile <<<---

--->>> Repo: Kotlin JavaScript <<<---

--->>> Repo: Kotlin Native-iOS <<<---

--->>> Repo: Ktor Examples <<<---

The "src" folder contains the resolved exercises of "https://github.com/jetbrains/workshop-jb"

These are the simple solutions of the kotlin koans ON LINE. If you want to add your answer, you can make a PR

Indexes for exercises online

Introduction [13/42] Koans

Collections [25/42] Koans

Conventions [32/42] Koans

Properties [36/42] Koans

Builders [41/42] Koans

Generic [42/42] Koans

Congratulations!

Introduction

Hello World!

Simple Functions

Take a look at function syntax and make the function start return the string "OK".

In the tasks the function TODO() is used that throws an exception. 
Your job during the koans will be to replace this function invocation with 
a meaningful code according to the problem.

Solution

fun start() = "OK"

Java to Kotlin conversion

We have a handy tool for Java developers: Java to Kotlin converter. 
It works better in Intellij, but you can try it online as well. 
To become familiar with it, please convert the code below.
Copy Java code, choose 'Convert from Java' above and copy the result function back.

public class JavaCode {
    public String toJSON(Collection<Integer> collection) {
        StringBuilder sb = new StringBuilder();
        sb.append("[");
        Iterator<Integer> iterator = collection.iterator();
        while (iterator.hasNext()) {
            Integer element = iterator.next();
            sb.append(element);
            if (iterator.hasNext()) {
                sb.append(", ");
            }
        }
        sb.append("]");
        return sb.toString();
    }
}

Solution

fun toJSON(collection: Collection<Int>): String  {
        val sb = StringBuilder();
        sb.append("[");
        val iterator = collection.iterator();
        while (iterator.hasNext()) {
            var element = iterator.next();
            sb.append(element);
            if (iterator.hasNext()) {
                sb.append(", ");
            }
        }
        sb.append("]");
        return sb.toString();
    }

Named arguments

Default and named arguments help to minimize the number of overloads
and improve the readability of the function invocation. 
The library function joinToString is declared with default values for parameters:

fun joinToString(
    separator: String = ", ",
    prefix: String = "",
    postfix: String = "",
    /* ... */
): String

It can be called on a collection of Strings. Using named arguments 
make the function joinOptions() return the list in a JSON format (e.g., "[a, b, c]")

Solution

fun joinOptions(options: Collection<String>) = options.joinToString(", ","[","]")

Default arguments

There are several overloads of 'foo()' in Java:

public String foo(String name, int number, boolean toUpperCase) {
    return (toUpperCase ? name.toUpperCase() : name) + number;
}
public String foo(String name, int number) {
    return foo(name, number, false);
}
public String foo(String name, boolean toUpperCase) {
    return foo(name, 42, toUpperCase);
}
public String foo(String name) {
    return foo(name, 42);
}

All these Java overloads can be replaced with one function in Kotlin. 
Change the declaration of the function foo in a way that makes the code 
using foo compile. Use default and named arguments.

Solution

fun foo(name: String = "", number: Int = 42, toUpperCase: Boolean = false) =
        (if (toUpperCase) name.toUpperCase() else name) + number

fun useFoo() = listOf(
        foo("a"),
        foo("b", number = 1),
        foo("c", toUpperCase = true),
        foo(name = "d", number = 2, toUpperCase = true)
)

Lambdas

Kotlin supports a functional style of programming. Read about higher-order
functions and function literals (lambdas) in Kotlin.

Pass a lambda to any function to check if the collection contains an even number.
The function any gets a predicate as an argument and returns true 
if there is at least one element satisfying the predicate.

Solution

fun containsEven(collection: Collection<Int>): Boolean = collection.any { it % 2 == 0  }

Strings

Read about different string literals and string templates in Kotlin.

Raw strings are useful for writing regex patterns, you don't need to escape
a backslash by a backslash. Below there is a pattern that matches a date
in format dd.mm.yyyy; in a usual string you'd have to write "(\\d{2})\\.(\\d{2})\\.(\\d{4})".

fun getPattern() = """(\d{2})\.(\d{2})\.(\d{4})"""

Using month variable rewrite this pattern in such a way that it matches 
the date in format 13 JUN 1992.

Solution

val month = "(JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)"

fun getPattern() = """(\d{2}) ${month} """

Data classes

Convert the following Java code to Kotlin:

public static class Person {
    private final String name;
    private final int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }
}

Then add an annotation data to the resulting class. This annotation means 
the compiler will generate a bunch of useful methods in this class:
equals/hashCode, toString and some others. The getPeople function should start to compile.

Then read about classes, properties and data classes in more detail.

Solution

data class Person(
			  val name: String,
			  val age : Int) 

fun getPeople(): List<Person> {
    return listOf(Person("Alice", 29), Person("Bob", 31))
}

Nullable types

Read about null safety and safe calls in Kotlin and rewrite the following 
Java code using only one if expression:

public void sendMessageToClient(
    @Nullable Client client,
    @Nullable String message,
    @NotNull Mailer mailer
) {
    if (client == null || message == null) return;

    PersonalInfo personalInfo = client.getPersonalInfo();
    if (personalInfo == null) return;

    String email = personalInfo.getEmail();
    if (email == null) return;

    mailer.sendMessage(email, message);
}

Solution

fun sendMessageToClient(
        client: Client?, message: String?, mailer: Mailer
){
    val personalInfo = client?.personalInfo
    val email = personalInfo?.email
    if (email != null && message != null) 
        mailer.sendMessage(email,message)
}

class Client (val personalInfo: PersonalInfo?)
class PersonalInfo (val email: String?)
interface Mailer {
    fun sendMessage(email: String, message: String)
}

Smart casts

Smart casts

Rewrite the following Java code using smart casts and when expression:

public int eval(Expr expr) {
    if (expr instanceof Num) {
        return ((Num) expr).getValue();
    }
    if (expr instanceof Sum) {
        Sum sum = (Sum) expr;
        return eval(sum.getLeft()) + eval(sum.getRight());
    }
    throw new IllegalArgumentException("Unknown expression");
}

Solution

fun eval(expr: Expr): Int =
        when (expr) {
            is Num -> expr.value
            is Sum -> (eval(expr.left) + eval(expr.right))
            else -> throw IllegalArgumentException("Unknown expression")
        }

interface Expr
class Num(val value: Int) : Expr
class Sum(val left: Expr, val right: Expr) : Expr

Extension functions

Read about extension functions. Then implement extension functions Int.r() 
and Pair.r() and make them convert Int and Pair to RationalNumber.

Solution

fun Int.r(): RationalNumber = RationalNumber(this,1)

fun Pair<Int, Int>.r(): RationalNumber = RationalNumber(this.first, this.second)
fun Pair<Int, Int>.r(): RationalNumber = RationalNumber(this.component1(), this.component2())

data class RationalNumber(val numerator: Int, val denominator: Int)
    

Object expressions

Read about object expressions that play the same role in Kotlin as anonymous
classes do in Java.

Add an object expression that provides a comparator to sort a list in a descending
order using java.util.Collections class. In Kotlin you use Kotlin library extensions
instead of java.util.Collections, but this example is still a good demonstration of
mixing Kotlin and Java code.

Solution

import java.util.*

fun getList(): List<Int> {
    val arrayList = arrayListOf(1, 5, 2)
[   
	    Collections.sort(arrayList, object : Comparator<Int> {
	    	override fun compare(x: Int, y: Int) = y - x 
	    })

	OR
	    Collections.sort(arrayList, { x, y -> y - x })
	    
	OR 
	    Collections.sort(arrayList, {x:Int, y:Int -> y - x})
]
    return arrayList
}

    return arrayList
}

SAM conversions

SAM conversions

When an object implements a SAM interface (one with a Single Abstract Method), 
you can pass a lambda instead. Read more about SAM conversions in the blog posts
about Kotlin. At first, SAM-constructors were introduced, then SAM-conversions 
were finally supported.

In the previous example change an object expression to a lambda.

Solution

fun getList(): List<Int> {
    val arrayList = arrayListOf(1, 5, 2)
    Collections.sort(arrayList, { x, y -> y - x })
    return arrayList
}

Extensions on collections

Extension functions on collections

Kotlin code can be easily mixed with Java code. Thus in Kotlin we don't 
introduce our own collections, but use standard Java ones (slightly improved). 
Read about read-only and mutable views on Java collections.

In Kotlin standard library there are lots of extension functions that make 
the work with collections more convenient. Rewrite the previous example once 
more using an extension function sortedDescending.

Solution

fun getList(): List<Int> {
    return arrayListOf(1, 5, 2).sorted().reversed()
}

Collections

Introduction

This part was inspired by GS Collections Kata.

Default collections in Kotlin are Java collections, but there are lots of useful extension functions for them. For example, operations that transform a collection to another one, starting with 'to': toSet or toList.

Implement an extension function Shop.getSetOfCustomers(). The class Shop and all related classes can be found at Shop.kt.

Solution

fun Shop.getSetOfCustomers(): Set<Customer> {
    return this.customers.toSet()
}

Filter Map

Implement extension functions Shop.getCitiesCustomersAreFrom() and Shop.getCustomersFrom() using functions map and filter.

val numbers = listOf(1, -1, 2)
numbers.filter { it > 0 } == listOf(1, 2)
numbers.map { it * it } == listOf(1, 1, 4)

Solution

fun Shop.getCitiesCustomersAreFrom(): Set<City> =  customers.map({it.city}).toSet()
fun Shop.getCustomersFrom(city: City): List<Customer> = customers.filter({it.city === city}).toList()

All, Any, Count, FirstOrNull

Implement all the functions below using all, any, count, firstOrNull.

val numbers = listOf(-1, 0, 2)
val isZero: (Int) -> Boolean = { it == 0 }
numbers.any(isZero) == true
numbers.all(isZero) == false
numbers.count(isZero) == 1
numbers.firstOrNull { it > 0 } == 2

Solution

fun Shop.checkAllCustomersAreFrom(city: City): Boolean = customers.all(givenCity(city))
fun Shop.hasCustomerFrom(city: City): Boolean = customers.any(givenCity(city))
fun Shop.countCustomersFrom(city: City): Int = customers.count(givenCity(city))
fun Shop.findAnyCustomerFrom(city: City): Customer? = customers.firstOrNull(givenCity(city))

private fun givenCity(city: City): (Customer) -> Boolean = { it.city === city }

FlatMap

Implement Customer.getOrderedProducts() and Shop.getAllOrderedProducts() using flatMap.

val result = listOf("abc", "12").flatMap { it.toCharList() }
result == listOf('a', 'b', 'c', '1', '2')

Solution

fun Customer.getOrderedProducts(): Set<Product> = orders.flatMap({it.products}).toSet()
fun Shop.getAllOrderedProducts(): Set<Product> = customers.flatMap({it.getOrderedProducts()}).toSet()

Max min

Implement Shop.getCustomerWithMaximumNumberOfOrders() and Customer.getMostExpensiveOrderedProduct() using max, min, maxBy, or minBy.

listOf(1, 42, 4).max() == 42
listOf("a", "ab").minBy { it.length() } == "a"

Solution

fun Shop.getCustomerWithMaximumNumberOfOrders(): Customer? = customers.maxBy({it.orders.count()})
fun Customer.getMostExpensiveOrderedProduct(): Product? = orders.flatMap({it.products}).maxBy({it.price})

Sort

Implement Shop.getCustomersSortedByNumberOfOrders() using sort or sortBy.

listOf("bbb", "a", "cc").sorted() == listOf("a", "bbb", "cc")
listOf("bbb", "a", "cc").sortedBy { it.length() } == listOf("a", "cc", "bbb")

Solution

fun Shop.getCustomersSortedByNumberOfOrders(): List<Customer> = customers.sortedBy({it.orders.size()})

Sum

Implement Customer.getTotalOrderPrice() using sum or sumBy.

listOf(1, 5, 3).sum() == 9
listOf("a", "b", "cc").sumBy { it.length() } == 4

Solution

fun Customer.getTotalOrderPrice(): Double = orders.flatMap({it.products}).sumByDouble({it.price})

Group by

Implement Shop.groupCustomersByCity() using groupBy.

val result = listOf("a", "b", "ba", "ccc", "ad").groupBy { it.length() }
result == mapOf(1 to listOf("a", "b"), 2 to listOf("ba", "ad"), 3 to listOf("ccc"))

Solution

fun Shop.groupCustomersByCity(): Map<City, List<Customer>> {
    val grupo = customers.groupBy({it.city})
    return grupo;
} 

Partition

Implement Shop.getCustomersWithMoreUndeliveredOrdersThanDelivered() using partition.

val numbers = listOf(1, 3, -4, 2, -11)
val (positive, negative) = numbers.partition { it > 0 }
positive == listOf(1, 3, 2)
negative == listOf(-4, -11)

Solution

fun Shop.getCustomersWithMoreUndeliveredOrdersThanDelivered(): Set<Customer> =  customers.filter {
    val (del, und) = it.orders.partition { it.isDelivered }
    und.size > del.size
}.toSet()

Fold

Implement Shop.getProductsOrderedByAllCustomers() using fold.

listOf(1, 2, 3, 4).fold(1, {
    partProduct, element ->
    element * partProduct
}) == 24

Solution

fun Shop.getProductsOrderedByAllCustomers(): Set<Product> {
    return customers.fold(allOrderedProducts, {
        orderedByAll, customer ->
        val orderedProducts = customer.orders.flatMap { it.products }.toSet()
        orderedByAll.intersect(orderedProducts) // [X] intersect [X;C;V] = [X] == retainAll
    })
}

val Customer.orderedProducts: Set<Product> get() {
    return orders.flatMap({it.products}).toSet()
}

val Shop.allOrderedProducts: Set<Product> get() {
    return customers.flatMap({it.orderedProducts}).toSet()
}

Compound tasks

Implement Customer.getMostExpensiveDeliveredProduct() and Shop.getNumberOfTimesProductWasOrdered() using functions from the Kotlin standard library.

Solution

fun Customer.getMostExpensiveDeliveredProduct(): Product? = orders.filter({it.isDelivered}).flatMap({it.products}).maxBy({it.price})

fun Shop.getNumberOfTimesProductWasOrdered(product: Product): Int = customers.flatMap({it.orders.flatMap { it.products }}).count({it == product})

Get used to new style

Rewrite the following Java function to Kotlin.

public Collection<String> doSomethingStrangeWithCollection(
        Collection<String> collection
) {
    Map<Integer, List<String>> groupsByLength = Maps.newHashMap();
    for (String s : collection) {
        List<String> strings = groupsByLength.get(s.length());
        if (strings == null) {
            strings = Lists.newArrayList();
            groupsByLength.put(s.length(), strings);
        }
        strings.add(s);
    }

    int maximumSizeOfGroup = 0;
    for (List<String> group : groupsByLength.values()) {
        if (group.size() > maximumSizeOfGroup) {
            maximumSizeOfGroup = group.size();
        }
    }

    for (List<String> group : groupsByLength.values()) {
        if (group.size() == maximumSizeOfGroup) {
            return group;
        }
    }
    return null;
}

Solution

fun doSomethingStrangeWithCollection(collection: Collection<String>): Collection<String>? {
    val groupsByLength = collection.groupBy{ s -> s?.filter({ it != null}).length }
    val maximumSizeOfGroup = groupsByLength.values.map { group -> group.size() }.max()
    return groupsByLength.values.firstOrNull { group -> group.size == maximumSizeOfGroup }
}

Conventions

Comparison

Read about operator overloading to learn how different conventions for 
operations like ==, <, + work in Kotlin. Add the function compareTo to the 
class MyDate to make it comparable. After that the code below date1 < date2 will 
start to compile.

In Kotlin when you override a member, the modifier override is mandatory.

Solution

data class MyDate(val year: Int, val month: Int, val dayOfMonth: Int) : Comparable<MyDate> {
    override fun compareTo(other: MyDate ): Int{
        if (this.year != other.year) return (this.year - other.year)
        if (this.month != other.month) return (this.month - other.month)
        return (this.dayOfMonth - other.dayOfMonth)
    }
}

fun compare(date1: MyDate, date2: MyDate) = date1 < date2

In range

In Kotlin in checks are translated to the corresponding contains calls:

val list = listOf("a", "b")
"a" in list  // list.contains("a")
"a" !in list // !list.contains("a")
Read about ranges. Make the class DateRange implement the standard Range interface 
to allow in checks with a range of dates.

Solution

Range(override val start: MyDate, override val end: MyDate) : Range<MyDate> {
    override fun contains(item: MyDate): Boolean = ( (start <= item) && (item <= end) )
}

fun checkInRange(date: MyDate, first: MyDate, last: MyDate): Boolean {
    return date in DateRange(first, last)
}

Range to

Implement the function MyDate.rangeTo(). 
This allows you to create a range of dates using the following syntax:
MyDate(2015, 5, 11)..MyDate(2015, 5, 12)

Solution

operator fun MyDate.rangeTo(other: MyDate) = DateRange(this,other)

class DateRange(override val start: MyDate, override val end: MyDate): Range<MyDate> {
    override fun contains(item: MyDate): Boolean = start < item && item < end
}

fun checkInRange(date: MyDate, first: MyDate, last: MyDate): Boolean {
    return date in first..last
}

For loop

Kotlin for loop iterates through anything that provides an iterator. 
Make the class DateRange implement Iterable<MyDate>, so that it could be iterated over. 
You can use the function MyDate.nextDay() defined in DateUtil.kt

Solution

import java.util.NoSuchElementException;

class DateRange(val start: MyDate, val end: MyDate) : Iterable<MyDate>{
    override fun iterator(): Iterator<MyDate>  = object : Iterator<MyDate> {
        var current: MyDate = start

        override fun next(): MyDate {
            if (!hasNext()) {
                throw NoSuchElementException()
            }

            val result = current
            current = current.nextDay()
            return result
        }

        override fun hasNext(): Boolean {
            return current <= end
        }

    }
}

fun iterateOverDateRange(firstDate: MyDate, secondDate: MyDate, handler: (MyDate) -> Unit) {
    for (date in DateRange(firstDate,secondDate)) {
        handler(date)
    }
}

Operators overloading

Implement a kind of date arithmetic. Support adding years, weeks and days to a date. You could be able to write the code like this: date + YEAR * 2 + WEEK * 3 + DAY * 15.

At first, add an extension function 'plus()' to MyDate, taking a TimeInterval as an argument. Use an utility function MyDate.addTimeIntervals() declared in DateUtil.kt

Then, try to support adding several time intervals to a date. You may need an extra class.

Solution

import TimeInterval.*

data class MyDate(val year: Int, val month: Int, val dayOfMonth: Int) 

enum class TimeInterval { DAY, WEEK, YEAR }

operator fun MyDate.plus(timeInterval: TimeInterval): MyDate = addTimeIntervals(timeInterval, 1)

fun task1(today: MyDate): MyDate = addTimeIntervals(today,1,1)

fun task2(today: MyDate): MyDate  = addTimeIntervals(today,2,3,5)

fun addTimeIntervals(myDate: MyDate, year:Int = 0, week: Int = 0, day:Int = 0) : MyDate {
    return myDate
            .addTimeIntervals(TimeInterval.YEAR,year)
            .addTimeIntervals(TimeInterval.WEEK,week)
            .addTimeIntervals(TimeInterval.DAY,day)
}

Multi assignment

Read about multi-declarations and make the following code compile by adding one word.

Solution

data class MyDate(val year: Int, val month: Int, val dayOfMonth: Int)

fun isLeapDay(date: MyDate): Boolean {
    val (year, month, dayOfMonth) = date
    return year % 4 == 0 && month == 2 && dayOfMonth == 29
}

Invoke

Objects with invoke() method can be invoked as a function.

You can add invoke extension for any class, but it's better not to overuse it:

fun Int.invoke() { println(this) }

1() //huh?..
Implement the function Invokable.invoke() so it would count a number of invocations.

Solution

class Invokable {
    public var numberOfInvocations: Int = 0
        private set
    operator public fun invoke(): Invokable {
        numberOfInvocations++
            return this
    }
}

fun invokeTwice(invokable: Invokable) = invokable()()

#Properties

Properties

Read about properties in Kotlin.

Add a custom setter to PropertyExample.propertyWithCounter so that the
counter property is incremented every time propertyWithCounter is assigned to.

Solution

/** 
 * var <propertyName>: <PropertyType> [= <property_initializer>]
 * <getter>
 * <setter>
 */

class PropertyExample() {
    var counter = 0
    var propertyWithCounter: Int? = null
        set(arg:Int?){
        field = arg
            counter++
    }
}

Lazy property

Add a custom getter to make the 'lazy' val really lazy. 
It should be initialized by the invocation of 'initializer()' at 
the moment of the first access.

You can add as many additional properties as you need.

Do not use delegated properties!

Solution

class LazyProperty(val initializer: () -> Int) {
    private val lazyValue : Int? = null
         get() {
            if(field == null)
               field = initializer()
                
         return field
        }
    
    val lazy: Int get() = lazyValue!!
       
}

Delegates examples

Read about delegated properties and make the property lazy by using delegates.

Solution

class LazyProperty(val initializer: () -> Int) {
    val lazyValue: Int by Lazy(initializer)
}

Delegates how it works

Implement the methods of the class 'EffectiveDate' so it can be delegated to. 
Store only the time in milliseconds in 'timeInMillis' property.

Use the extension functions MyDate.toMillis() and Long.toDate(), defined at MyDate.kt

Solution

import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty

class D {
    var date: MyDate by EffectiveDate()
}

class EffectiveDate<R> : ReadWriteProperty<R, MyDate> {

    var timeInMillis: Long? = null

    override fun getValue(thisRef: R, property: KProperty<*>): MyDate {
        return timeInMillis!!.toDate()
    }

    override fun setValue(thisRef: R, property: KProperty<*>, value: MyDate) {
        timeInMillis = value.toMillis()
    }
}

#Builders

Builders how it works

Look at the questions below and give your answers
1. In the Kotlin code
tr {
    td {
        text("Product")
    }
    td {
        text("Popularity")
    }
}

'td' is:
a. special built-in syntactic construct
b. function declaration
c. function invocation

2. In the Kotlin code
tr (color = "yellow") {
    td {
        text("Product")
    }
    td {
        text("Popularity")
    }
}

'color' is:
a. new variable declaration
b. argument name
c. argument value

3. The block
{
    text("Product")
}

from the previous question is:
a. block inside built-in syntax construction td
b. function literal (or "lambda")
c. something mysterious

4. For the code

tr (color = "yellow") {
    this.td {
        text("Product")
    }
    td {
        text("Popularity")
    }
}

which of the following is true:
a. this code doesn't compile
b. this refers to an instance of an outer class
c. this refers to a receiver parameter TR of the function literal:

tr (color = "yellow") { TR.(): Unit ->
      this.td {
          text("Product")
      }
}

Solution

import Answer.*

enum class Answer { a, b, c }

val answers = mapOf<Int, Answer?>(
        1 to Answer.c, 2 to Answer.b, 3 to Answer.b, 4 to Answer.c
)

String and map builders

Extension function literals are very useful for creating builders, e.g.:

fun buildString(build: StringBuilder.() -> Unit): String {
    val stringBuilder = StringBuilder()
    stringBuilder.build()
    return stringBuilder.toString()
}

val s = buildString {
    this.append("Numbers: ")
    for (i in 1..3) {
        // 'this' can be omitted
        append(i)
    }
}

s == "Numbers: 123"
Add and implement the function 'buildMap' with one parameter (of type extension function)
creating a new HashMap, building it and returning it as a result. 
The usage of this function is shown below.

Solution

import java.util.HashMap

fun <H,T> buildMap(build: MutableMap<H,T>.() -> Unit) : Map<H,T> {
	var map =  HashMap<H,T>() / HashTable<H,T>()
    map.build()
    return map
}

fun usage(): Map<Int, String> {
    return buildMap {
        put(0, "0")
        for (i in 1..10) {
            put(i, "$i")
        }
    }
}

The function with

The function with

The previous examples can be rewritten using the library function "with"
https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/with.html#receiver
Write your own implementation of this function named 'myWith'.

Solution

fun <T, R> myWith(receiver: T, f: T.() -> R): R {
    return receiver.f()
}

fun buildString(): String {
    val stringBuilder = StringBuilder()
    myWith (stringBuilder) {
        append("Numbers: ")
        for (i in 1..10) {
            append(i)
        }
    }
    return stringBuilder.toString()
}

fun buildMap(): Map<Int, String> {
    val map = hashMapOf<Int, String>()
    myWith (map) {
        put(0, "0")
        for (i in 1..10) {
            put(i, "$i")
        }
    }
    return map
}

Html builders

1. Fill the table with the proper values from the product list. 
The products are declared in data.kt.

2. Color the table like a chess board (using getTitleColor() and getCellColor()
functions above). Pass a color as an argument to the functions tr, td.

You can run 'JavaScript(Canvas)' configuration to see the rendered table.

Solution

fun renderProductTable(): String {
    fun getTitleColor() = "#b9c9fe"
    fun getCellColor(index: Int, row: Int) = if ((index + row) %2 == 0) "#dce4ff" else "#eff2ff"
    fun renderProductTable(): String {
    return html {
        table {
            tr (color = getTitleColor(), init = {
                td { this.text("Product") }
                td { this.text("Price") }
                td { this.text("Popularity")  }
            })
            val products = getProducts()
            products.forEachIndexed { i, product ->
                tr{
                    td{ this.text(product.description) }
                    td{ this.text(product.price) }
                    td{ this.text(product.popularity) }
                }
            }
        }
    }.toString()
}


Extension function literals

Read about https://kotlinlang.org/docs/reference/lambdas.html#extension-function-expressions

You can declare isEven and isOdd as values, that can be called as extension functions. 
Complete the declarations below.

Solution

fun task(): List<Boolean> {
    val isEven: Int.() -> Boolean = { this % 2 == 0 }
    val isOdd: Int.() -> Boolean = { this % 2 != 0 }

    return listOf(42.isOdd(), 239.isOdd(), 294823098.isEven())
}

Generic

Generic functions

Make the following code compile by implementing a partitionTo function that splits a collection into two collections according to a predicate.

There is a partition() function in the standard library that always returns two newly created lists. You should write a function that splits the collection into two collections given as arguments. The signature of the toCollection() function from the standard library may help you.

Solution

import java.util.*

fun <T,H: MutableCollection<T>> Collection<T>.partitionTo(listHead : H, listBody: H, predicate : (T) -> Boolean ) : Pair<H,H> {
    this.forEach{      
        val isPredicate = predicate.invoke(it)
            if(isPredicate) listHead.add(it)
            else listBody.add(it)
    }
     return Pair(listHead,listBody)
}

fun partitionWordsAndLines() {
    val (words, lines) = listOf("a", "a b", "c", "d e").
            partitionTo(ArrayList<String>(), ArrayList()) { s -> !s.contains(" ") }
    words == listOf("a", "c")
    lines == listOf("a b", "d e")
}

fun partitionLettersAndOtherSymbols() {
    val (letters, other) = setOf('a', '%', 'r', '}').
            partitionTo(HashSet<Char>(), HashSet()) { c -> c in 'a'..'z' || c in 'A'..'Z'}
    letters == setOf('a', 'r')
    other == setOf('%', '}')
}
Comments
  • Solution to i_introduction - Extensions On Collection is incorrect

    Solution to i_introduction - Extensions On Collection is incorrect

    Hi there, first of all this page has been a great resource!

    The solution to Extensions on Collections is listed in the online tutorial as:

    arrayListOf(1, 5, 2).sortedDescending()
    
    opened by RNabel 2
  • Do not use comparator implementation like y-x.

    Do not use comparator implementation like y-x.

    Issue in _10_Object_Expressions

    Comparator implementation like y-x is wrong, because it does not work for some values. See example:

        @Test fun testSort() {
            assertEquals(listOf(5, 2, 1), sort(listOf(2, 5, 1)))
        }
    
        @Test fun testSort2(){
    //wrong, because y-x is fail
            assertEquals(listOf(Integer.MAX_VALUE, Integer.MIN_VALUE), sort(listOf(Integer.MAX_VALUE, Integer.MIN_VALUE)))
        }
    
    
        fun sort(list : List<Int>):List<Int> {
    //change to y.compareTo(x)
            Collections.sort(list, {x:Int, y:Int -> y-x} )
            return list
        }
    
    
    opened by chabapok 1
  • Bump kotlin-stdlib from 1.0.0-beta-1038 to 1.6.0-M1

    Bump kotlin-stdlib from 1.0.0-beta-1038 to 1.6.0-M1

    Bumps kotlin-stdlib from 1.0.0-beta-1038 to 1.6.0-M1.

    Release notes

    Sourced from kotlin-stdlib's releases.

    Kotlin 1.6.0-M1

    Learn how to install Kotlin 1.6.0-M1.

    Changelog

    Android

    • KT-48019 Bundle Kotlin Tooling Metadata into apk artifacts
    • KT-47733 JVM / IR: Android Synthetic don't generate _findCachedViewById function

    Compiler

    New Features

    • KT-12794 Allow runtime retention repeatable annotations when compiling under Java 8
    • KT-47984 In-place arguments inlining for @​InlineOnly functions
    • KT-48194 Try to resolve calls where we don't have enough type information, using the builder inference despite the presence of the annotation
    • KT-26245 Add ability to specify generic type parameters as not-null
    • KT-45949 Kotlin/Native: Improve bound check elimination
    • KT-47699 Support programmatic creation of class annotations and corresponding feature flag on JVM
    • KT-47736 Support conversion from regular functional types to suspending ones in JVM IR
    • KT-39055 Support property delegate created via synthetic method instead of field

    Performance Improvements

    • KT-33835 Bytecode including unnecessary null checks for safe calls where left-hand side is non-nullable
    • KT-41510 Compilation of kotlin html DSL is still too slow
    • KT-48211 We spend a lot of time in ExpectActual declaration checker when there is very small amount of actual/expect declaration
    • KT-39054 Optimize delegated properties which call get/set on the given KProperty instance on JVM
    • KT-47918 JVM / IR: Performance degradation with const-bound for-cycles
    • KT-47785 Compilation time increased when trying to compile AssertJ DB expression in 1.5.21
    • KT-46615 Don't generate nullability assertions in methods for directly invoked lambdas

    Fixes

    • KT-48523 Kotlin/Native: cross-compilation from Linux to MinGW not working when platform.posix is used
    • KT-48295 JVM / IR: VerifyError: Bad access to protected data in getfield
    • KT-48440 JVM IR: Missing checkcast in generated bytecode causes VerifyError in Kotlin 1.5.30
    • KT-48794 Breaking change in 1.5.30: Builder inference lambda contains inapplicable calls so {1} cant be inferred
    • KT-48653 Warnings on non-exhaustive when statements missing in some cases with 1.6
    • KT-48394 JVM: Invalid locals caused by unboxing bytecode optimization
    • KT-48380 kotlin.RuntimeException: Unexpected receiver type
    • KT-47855 Kotlin/Native: compilation fails due to Escape Analysis
    • KT-48291 False positive [ACTUAL_MISSING] Declaration must be marked with 'actual' when implementing actual interface
    • KT-48613 Kotlin/Native fails to compile debug binaries for watchosArm64 target
    • KT-48618 Enable by default "suspend conversion" feature in 1.6
    • KT-48543 Native compiler crashes because of bridges for $default stubs
    • KT-47328 JVM / IR: NoSuchFieldError with missing CHECKCAST
    • KT-47638 Drop EXPERIMENTAL_IS_NOT_ENABLED diagnostic

    ... (truncated)

    Changelog

    Sourced from kotlin-stdlib's changelog.

    1.6.0-M1

    Android

    • KT-48019 Bundle Kotlin Tooling Metadata into apk artifacts
    • KT-47733 JVM / IR: Android Synthetic don't generate _findCachedViewById function

    Compiler

    New Features

    • KT-12794 Allow runtime retention repeatable annotations when compiling under Java 8
    • KT-47984 In-place arguments inlining for @​InlineOnly functions
    • KT-48194 Try to resolve calls where we don't have enough type information, using the builder inference despite the presence of the annotation
    • KT-26245 Add ability to specify generic type parameters as not-null
    • KT-45949 Kotlin/Native: Improve bound check elimination
    • KT-47699 Support programmatic creation of class annotations and corresponding feature flag on JVM
    • KT-47736 Support conversion from regular functional types to suspending ones in JVM IR
    • KT-39055 Support property delegate created via synthetic method instead of field

    Performance Improvements

    • KT-33835 Bytecode including unnecessary null checks for safe calls where left-hand side is non-nullable
    • KT-41510 Compilation of kotlin html DSL is still too slow
    • KT-48211 We spend a lot of time in ExpectActual declaration checker when there is very small amount of actual/expect declaration
    • KT-39054 Optimize delegated properties which call get/set on the given KProperty instance on JVM
    • KT-47918 JVM / IR: Performance degradation with const-bound for-cycles
    • KT-47785 Compilation time increased when trying to compile AssertJ DB expression in 1.5.21
    • KT-46615 Don't generate nullability assertions in methods for directly invoked lambdas

    Fixes

    • KT-48523 Kotlin/Native: cross-compilation from Linux to MinGW not working when platform.posix is used
    • KT-48295 JVM / IR: VerifyError: Bad access to protected data in getfield
    • KT-48440 JVM IR: Missing checkcast in generated bytecode causes VerifyError in Kotlin 1.5.30
    • KT-48794 Breaking change in 1.5.30: Builder inference lambda contains inapplicable calls so {1} cant be inferred
    • KT-48653 Warnings on non-exhaustive when statements missing in some cases with 1.6
    • KT-48394 JVM: Invalid locals caused by unboxing bytecode optimization
    • KT-48380 kotlin.RuntimeException: Unexpected receiver type
    • KT-47855 Kotlin/Native: compilation fails due to Escape Analysis
    • KT-48291 False positive [ACTUAL_MISSING] Declaration must be marked with 'actual' when implementing actual interface
    • KT-48613 Kotlin/Native fails to compile debug binaries for watchosArm64 target
    • KT-48618 Enable by default "suspend conversion" feature in 1.6
    • KT-48543 Native compiler crashes because of bridges for $default stubs
    • KT-47328 JVM / IR: NoSuchFieldError with missing CHECKCAST
    • KT-47638 Drop EXPERIMENTAL_IS_NOT_ENABLED diagnostic
    • KT-48349 OptIn markers are forbidden on local variable / value parameter / property getter only in presence of explicit Target annotation
    • KT-48589 KotlinTypeRefiner is lost, leading to TYPE_MISMATCH and OVERLOAD_RESOLUTION_AMBIGUITY issues with MPP projects
    • KT-48615 Inconsistent behavior with integer literals overflow (Implementation)
    • KT-47937 Implement deprecation of computing constant values of complex boolean expressions in when condition branches and conditions of loops

    ... (truncated)

    Commits
    • 3f1c3ea Build: Add missing verification metadata for httpcore 4.2.1
    • 60d02ea Add changelog for 1.6.0-M1 and move 1.5.x changelogs to a separate file
    • dce8aee Add changelog for 1.5.31
    • 71a4ede Add changelog for 1.5.30
    • 6446866 Minor. Ignore test on JS_IR
    • 102736f Fixup end label of local variable if it is before start label
    • b07cf8a Bump Kotlin/Native version.
    • e575c94 Fix binary compatibility with AS Arctic Fox C14
    • 7613d80 Provide KotlinSourceElementKt.getPsi for bwc with AS
    • 15b0e11 [Native][Tools] Add input directory in the bundles repack script
    • Additional commits viewable in compare view

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    opened by dependabot[bot] 0
  • Bump junit from 4.10 to 4.13.1

    Bump junit from 4.10 to 4.13.1

    Bumps junit from 4.10 to 4.13.1.

    Release notes

    Sourced from junit's releases.

    JUnit 4.13.1

    Please refer to the release notes for details.

    JUnit 4.13

    Please refer to the release notes for details.

    JUnit 4.13 RC 2

    Please refer to the release notes for details.

    JUnit 4.13 RC 1

    Please refer to the release notes for details.

    JUnit 4.13 Beta 3

    Please refer to the release notes for details.

    JUnit 4.13 Beta 2

    Please refer to the release notes for details.

    JUnit 4.13 Beta 1

    Please refer to the release notes for details.

    JUnit 4.12

    Please refer to the release notes for details.

    JUnit 4.12 Beta 3

    Please refer to the release notes for details.

    JUnit 4.12 Beta 2

    No release notes provided.

    JUnit 4.12 Beta 1

    No release notes provided.

    JUnit 4.11

    No release notes provided.

    Commits
    • 1b683f4 [maven-release-plugin] prepare release r4.13.1
    • ce6ce3a Draft 4.13.1 release notes
    • c29dd82 Change version to 4.13.1-SNAPSHOT
    • 1d17486 Add a link to assertThrows in exception testing
    • 543905d Use separate line for annotation in Javadoc
    • 510e906 Add sub headlines to class Javadoc
    • 610155b Merge pull request from GHSA-269g-pwp5-87pp
    • b6cfd1e Explicitly wrap float parameter for consistency (#1671)
    • a5d205c Fix GitHub link in FAQ (#1672)
    • 3a5c6b4 Deprecated since jdk9 replacing constructor instance of Double and Float (#1660)
    • Additional commits viewable in compare view

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    opened by dependabot[bot] 0
  • #Lazy property

    #Lazy property

    `class LazyProperty(val initializer: () -> Int) { private val lazyValue : Int? = null // Trying to re-assign val property, should be changed to var property get() { if(field == null) field = initializer()

         return field
        }
    
    val lazy: Int get() = lazyValue!!
    

    }`

    opened by arnaudram 0
Owner
Victor Bolinches
I build things in software, sometimes with a lot of craziness. Game/Tooling programmer. Twitter - @vicboma1
Victor Bolinches
It is a project that contains lessons and examples about Kotlin programming language. 🇰

Kotlin Tutorials What is Kotlin? I added the platforms it supports and great resources. You can access the article from the link below: https://medium

Halil Özel 94 Dec 22, 2022
Kotlin Examples Problems

Kotlin Examples Problems --->>> Repo: Getting Started Kotlin <<<--- --->>> Repo Kotlin Koans <<<--- --->>> Repo: GameBoy Emulator Enviroment <<<--- --

Victor Bolinches 22 Oct 3, 2022
Kotlin Unit Testing Examples

Kotlin Unit Testing Examples Table of Contents Application Gradle, Kotlin & Groovy Junit4 Junit5 KotlinTest Spek Mockito Mockito-Kotlin Mockk Strikt T

Jarosław 110 Dec 11, 2022
101 examples for Kotlin Programming language.

This is a collection of runnable console applications that highlights the features of Kotlin programming language. The use of console application enab

Dody Gunawinata 192 Dec 1, 2022
Full stack examples of how to use Hotwire JS in Kotlin services

hotwire-kt A collection of Kotlin examples using the Hotwire JS framework to build interactive web apps with a Kotlin Armeria server backend. Using Ho

Andrew (Paradi) Alexander 9 Dec 14, 2022
Getting started Kotlin - Examples and explanations

Getting started Kotlin I'm learning Kotlin, so I have been updating it with examples and explanations about the language that I'm using at work. Proje

Jean Jacques Nascimento Barros 2 Apr 25, 2022
Examples for using Kotlin at a basic level for Android application development.

Kotlin Android Jetpack Basics Ejemplos para usar Kotlin a nivel básico para el desarrollo de aplicaciones Android. Kotlin Android Jetpack Basics Acerc

José Luis González Sánchez 2 Jun 28, 2022
A coding examples project about Kotlin Programming language. 🇰

Kotlin Tutorial ????‍?? What is Kotlin ❓ Kotlin is a new programming language, developed by JetBrains. Jetbrains is a popular software development com

Mustajab Ikram 4 Oct 11, 2022
Examples of Getting Started vídeos

Getting Started Kotlin Learn the basics of getting started with kotlin --->>> Repo: Kotlin Koans <<<--- --->>> Repo: Problems Kotlin <<<--- --->>> Rep

Victor Bolinches 41 Dec 4, 2022
Repo: Programming problems with solutions in Kotlin to help avid Kotlin learners to get a strong hold on Kotlin programming.

Kotlin_practice_problems Repo: Programming problems with solutions in Kotlin to help avid Kotlin learners to get a strong hold on Kotlin programming.

Aman 0 Oct 14, 2021
Mocking for Kotlin/Native and Kotlin Multiplatform using the Kotlin Symbol Processing API (KSP)

Mockative Mocking for Kotlin/Native and Kotlin Multiplatform using the Kotlin Symbol Processing API (KSP). Installation Mockative uses KSP to generate

Mockative 121 Dec 26, 2022
Kotlin-oop - Repositório criado para ser utilizado pelo projeto de Kotlin OOP desenvolvido em Kotlin nas aulas feitas através da plataforma Alura.

Projeto React OOP Repositório criado para ser utilizado pelo projeto de Kotlin OOP desenvolvido em Kotlin nas aulas feitas através da plataforma Alura

Marcos Felipe 1 Jan 5, 2022
Kotlin TodoMVC – full-stack Kotlin application demo

Kotlin full stack TodoMVC This project is an example implementation of the TodoMVC app written in Kotlin. More specifically, it's the Kotlin port of t

Gyula Voros 22 Oct 3, 2022
Integration Testing Kotlin Multiplatform Kata for Kotlin Developers. The main goal is to practice integration testing using Ktor and Ktor Client Mock

This kata is a Kotlin multiplatform version of the kata KataTODOApiClientKotlin of Karumi. We are here to practice integration testing using HTTP stub

Jorge Sánchez Fernández 29 Oct 3, 2022
Small kotlin library for persisting _single instances_ of kotlin data classes

PerSista Small library for persisting single instances of kotlin data classes. NB: PerSista uses typeOf() internally which is marked as @ExperimentalS

Eric Donovan 5 Nov 13, 2022
Kotlin Leaning Notes from Udacity Course | Kotlin Bootcamp for Programmers by Google

Kotlin Beginners Notes These are all personal notes taken from the Udacity Course (ud9011) of Kotlin Bootcamp for Programmers by Google as well as oth

Süha Tanrıverdi 34 Dec 10, 2022
Saga pattern implementation in Kotlin build in top of Kotlin's Coroutines.

Module Saga Website can be found here Add in build.gradle.kts repositories { mavenCentral() } dependencies { implementation("io.github.nomisr

Simon Vergauwen 50 Dec 30, 2022
Kotlin microservices with REST, and gRPC using BFF pattern. This repository contains backend services. Everything is dockerized and ready to "Go" actually "Kotlin" :-)

Microservices Kotlin gRPC Deployed in EC2, Check it out! This repo contains microservices written in Kotlin with BFF pattern for performing CRUD opera

Oguzhan 18 Apr 21, 2022
A sample skeleton backend app built using Spring Boot kotlin, Expedia Kotlin Graphql, Reactive Web that can be deployed to Google App Engine Flexible environmennt

spring-kotlin-gql-gae This is a sample skeleton of a backend app that was built using: Spring Boot(Kotlin) Reactive Web Sprinng Data R2DBC with MYSQL

Dario Mungoi 7 Sep 17, 2022