Last active
July 27, 2020 06:00
-
-
Save nicokosi/2cb6964e18b14b15a71ba4a493f64b61 to your computer and use it in GitHub Desktop.
My answers to Kotlin Playground Koans: https://play.kotlinlang.org/koans
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* My answers to [Kotlin Playground Koans](https://play.kotlinlang.org/koans) */ | |
/* Intro */ | |
// Hello, world! | |
fun start(): String = "OK" | |
// Named arguments | |
fun joinOptions(options: Collection<String>) = | |
options.joinToString(prefix = "[", postfix = "]") | |
// Default arguments | |
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 | |
fun containsEven(collection: Collection<Int>): Boolean = | |
collection.any { it -> it % 2 == 0 } | |
// Strings | |
val month = "(JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)" | |
fun getPattern(): String = """\d{2}\s${month}\s\d{4}""" | |
// Data classes | |
data class Person(private val name: String, private val age: Int) | |
fun getPeople(): List<Person> = | |
listOf(Person("Alice", 29), Person("Bob", 31)) | |
// Nullable types | |
fun sendMessageToClient( | |
client: Client?, message: String?, mailer: Mailer) { | |
var email = client?.personalInfo?.email | |
if (email == null || message == null) return | |
return mailer.sendMessage( | |
client?.personalInfo?.email!!, | |
message) | |
} | |
// Smart casts | |
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 | |
fun Int.r(): RationalNumber = | |
RationalNumber(toInt(), 1) | |
fun Pair<Int, Int>.r(): RationalNumber = | |
RationalNumber(first.toInt(), second.toInt()) | |
data class RationalNumber(val numerator: Int, val denominator: Int) | |
// Object expressions | |
fun getList(): List<Int> { | |
val arrayList = arrayListOf(1, 5, 2) | |
java.util.Collections.sort( | |
arrayList, | |
object : Comparator<Int> { | |
override fun compare(a: Int, b: Int) = b - a | |
} | |
) | |
return arrayList | |
} | |
// Single Abstract Method conversions | |
fun getList(): List<Int> { | |
val arrayList = arrayListOf(1, 5, 2) | |
java.util.Collections.sort(arrayList, { x, y -> y - x }) | |
return arrayList | |
} | |
// Extensions on collections | |
fun getList(): List<Int> = arrayListOf(1, 5, 2).sortedDescending() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* My answers to [Kotlin Playground Koans](https://play.kotlinlang.org/koans) */ | |
/* Conventions */ | |
// Comparison | |
data class MyDate(val year: Int, val month: Int, val dayOfMonth: Int) | |
: Comparable<MyDate> { | |
override fun compareTo(other: MyDate) = | |
year -other.year + month - other.month + dayOfMonth - other.dayOfMonth | |
} | |
fun compare(date1: MyDate, date2: MyDate) = date1 < date2 | |
// In range | |
class DateRange(val start: MyDate, val endInclusive: MyDate) { | |
operator fun contains(date: MyDate) = | |
date.compareTo(start) > 0 && date.compareTo(endInclusive) < 0 | |
} | |
fun checkInRange(date: MyDate, first: MyDate, last: MyDate) | |
= date in DateRange(first, last) | |
// Range to | |
operator fun MyDate.rangeTo(other: MyDate) = DateRange(this, other) | |
class DateRange( | |
override val start: MyDate, | |
override val endInclusive: MyDate): ClosedRange<MyDate> | |
fun checkInRange(date: MyDate, first: MyDate, last: MyDate) = | |
date in first..last | |
// For loop | |
class DateRange(val start: MyDate, val end: MyDate): Iterable<MyDate> { | |
override operator fun iterator(): Iterator<MyDate> { | |
return object: Iterator<MyDate> { | |
var currentDate = start | |
override fun hasNext(): Boolean { | |
return currentDate <= end | |
} | |
override fun next(): MyDate { | |
val now = currentDate | |
currentDate = currentDate.nextDay() | |
return now | |
} | |
} | |
} | |
} | |
fun iterateOverDateRange(firstDate: MyDate, secondDate: MyDate, handler: (MyDate) -> Unit) { | |
for (date in firstDate..secondDate) { | |
handler(date) | |
} | |
} | |
// Operators overloading | |
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 = | |
this.addTimeIntervals(timeInterval, 1) | |
fun task1(today: MyDate): MyDate = today + YEAR + WEEK | |
operator fun TimeInterval.times(number: Int): TimeIntervals = TimeIntervals(number, this) | |
data class TimeIntervals(val number: Int, val timeInterval: TimeInterval) | |
operator fun MyDate.plus(timeIntervals: TimeIntervals): MyDate = | |
this.addTimeIntervals(timeIntervals.timeInterval, timeIntervals.number) | |
fun task2(today: MyDate): MyDate = today + YEAR * 2 + WEEK * 3 + DAY * 5 | |
// Destructuring declarations | |
class MyDate(val year: Int, val month: Int, val dayOfMonth: Int) { | |
operator fun component1() = year | |
operator fun component2() = month | |
operator fun component3() = dayOfMonth | |
} | |
fun isLeapDay(date: MyDate): Boolean { | |
val (year, month, dayOfMonth) = date | |
// 29 February of a leap year | |
return year % 4 == 0 && month == 2 && dayOfMonth == 29 | |
} | |
// Invoke | |
class Invokable { | |
var numberOfInvocations: Int = 0 | |
private set | |
operator fun invoke(): Invokable { | |
numberOfInvocations++ | |
return this | |
} | |
} | |
fun invokeTwice(invokable: Invokable) = invokable()() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* My answers to [Kotlin Playground Koans](https://play.kotlinlang.org/koans) */ | |
/* Collections */ | |
// Introduction | |
fun Shop.getSetOfCustomers(): Set<Customer> = customers.toSet() | |
// Filter map | |
// Return the set of cities the customers are from | |
fun Shop.getCitiesCustomersAreFrom(): Set<City> = | |
customers.map { it.city }.toSet() | |
// Return a list of the customers who live in the given city | |
fun Shop.getCustomersFrom(city: City): List<Customer> = | |
customers.filter { it.city == city } | |
// All Any and other predicates | |
fun Shop.checkAllCustomersAreFrom(city: City): Boolean = | |
customers | |
.filter { it.city != city } | |
.isEmpty() | |
fun Shop.hasCustomerFrom(city: City): Boolean = | |
customers | |
.filter { it.city == city } | |
.isNotEmpty() | |
fun Shop.countCustomersFrom(city: City): Int = | |
customers | |
.filter { it.city == city } | |
.size | |
fun Shop.findAnyCustomerFrom(city: City): Customer? = | |
customers | |
.filter { it.city == city } | |
.firstOrNull() | |
// FlatMap | |
val Customer.orderedProducts: Set<Product> get() = | |
orders | |
.flatMap { it.products } | |
.toSet() | |
val Shop.allOrderedProducts: Set<Product> get() = | |
customers | |
.flatMap { it.orders } | |
.flatMap { it.products } | |
.toSet() | |
// Max min | |
fun Shop.getCustomerWithMaximumNumberOfOrders(): Customer? = | |
customers | |
.sortedByDescending { it.orders.size } | |
.firstOrNull() | |
fun Customer.getMostExpensiveOrderedProduct(): Product? = | |
orders | |
.flatMap { it.products } | |
.toSet() | |
.sortedByDescending { it.price } | |
.firstOrNull() | |
// Sort | |
fun Shop.getCustomersSortedByNumberOfOrders() = | |
customers | |
.sortedBy { it.orders.size } | |
// Sum | |
fun Customer.getTotalOrderPrice(): Double = | |
orders | |
.flatMap { it.products } | |
.map { it.price } | |
.sum() | |
// Group by | |
fun Shop.groupCustomersByCity(): Map<City, List<Customer>> = | |
customers.groupBy { it.city } | |
// Partition | |
fun Shop.getCustomersWithMoreUndeliveredOrdersThanDelivered(): Set<Customer> = | |
customers | |
.partition { | |
it.orders.filter{ it.isDelivered == false }.size > it.orders.filter{ it.isDelivered == true}.size | |
} | |
.first | |
.toSet() | |
// Fold | |
fun Shop.getSetOfProductsOrderedByEveryCustomer(): Set<Product> = | |
customers.fold( | |
orderedProducts, { | |
orderedByAll, customer -> customer.orders | |
.flatMap { it.products } | |
.filter { it in orderedByAll } | |
.toSet() | |
} | |
) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment