1
1
Fork 0

Converted AtomicKotlin course to a new format

This commit is contained in:
Svetlana Isakova 2019-07-15 14:55:19 +02:00
commit b40d0329be
1489 changed files with 19296 additions and 0 deletions

5
.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
.idea
.gradle
/.coursecreator/
/**/build
/**/out

View File

@ -0,0 +1,11 @@
// FoldingLists/FoldAndReduce.kt
import atomictest.eq
fun main(args: Array<String>) {
val list = listOf(1, 2, 3, 4)
list.fold(1) { acc, elem -> acc * elem } eq
1 * 1 * 2 * 3 * 4
list.reduce { acc, elem -> acc * elem } eq
1 * 2 * 3 * 4
}

View File

@ -0,0 +1,16 @@
// FoldingLists/FoldRight.kt
import atomictest.eq
fun main(args: Array<String>) {
val list = listOf('a', 'b', 'c', 'd')
list.fold("*") {
accumulator, element ->
"($accumulator) + $element"
} eq "((((*) + a) + b) + c) + d"
list.foldRight("*") {
element, accumulator ->
"$element + ($accumulator)"
} eq "a + (b + (c + (d + (*))))"
}

View File

@ -0,0 +1,21 @@
// FoldingLists/FoldVsForLoop.kt
import atomictest.eq
fun main(args: Array<String>) {
val list = listOf(1, 10, 100, 1000)
val initial = 0
val operation =
{ sum: Int, i: Int -> sum + i }
val s = list.fold(initial) {
sum, i -> operation(sum, i)
}
s eq 1111
var accumulator = initial
for (i in list) {
accumulator = operation(accumulator, i)
}
accumulator eq 1111
}

View File

@ -0,0 +1,9 @@
// FoldingLists/SumViaFold.kt
import atomictest.eq
fun main(args: Array<String>) {
val list = listOf(1, 10, 100, 1000)
list.fold(0) {
sum, n -> sum + n
} eq 1111
}

View File

@ -0,0 +1,10 @@
type: theory
files:
- name: src/SumViaFold.kt
visible: true
- name: src/FoldVsForLoop.kt
visible: true
- name: src/FoldRight.kt
visible: true
- name: src/FoldAndReduce.kt
visible: true

View File

@ -0,0 +1,2 @@
id: 497924
update_date: Wed, 03 Oct 2018 12:40:54 UTC

View File

@ -0,0 +1,2 @@
<h2 style="text-align: center;">Folding Lists</h2><p>Examples accompanying the atom.
<a href="https://stepik.org/lesson/107901/step/1" rel="nofollow noopener noreferrer">Read "Folding Lists" atom online.</a></p>

View File

@ -0,0 +1,13 @@
package foldingLists01
import atomictest.eq
fun <T> List<T>.size(): Int =
fold(0) { length, _ ->
length + 1
}
fun main(args: Array<String>) {
val list = listOf(1, 2, 3)
list.size() eq 3
}

View File

@ -0,0 +1,12 @@
type: edu
files:
- name: src/Task.kt
visible: true
placeholders:
- offset: 84
length: 55
placeholder_text: TODO("fold(0) { ??? }")
- name: test/Tests.kt
visible: false
feedback_link: |
https://docs.google.com/forms/d/e/1FAIpQLSdkaliSwYkjiV21bZl0yP-In2g5p17sAQCfaGjyHx_QYMWTiQ/viewform?usp=pp_url&entry.189755027=Functional+Programming+%2F+Folding+Lists+%2F+Exercise1

View File

@ -0,0 +1,2 @@
id: 497925
update_date: Wed, 03 Oct 2018 12:40:55 UTC

View File

@ -0,0 +1,2 @@
<h2 style="text-align: center;">Folding Lists (#1)</h2><p>Implement <code>size()</code> using <code>fold()</code>.
<code>size()</code> returns the number of elements in the list.</p>

View File

@ -0,0 +1,25 @@
package foldingLists01
import org.junit.Assert
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runners.MethodSorters
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
class TestSize {
private fun <T> checkSize(list: List<T>) {
Assert.assertEquals("Wrong 'size' for $list:", list.size, list.size())
}
@Test
fun test1Sample() = checkSize(listOf(1, 2, 3))
@Test
fun test2() = checkSize(listOf('a', 'b', 'c', 'd', 'e'))
@Test
fun test3() = checkSize(listOf<Int>())
@Test
fun test4() = checkSize(listOf(null))
}

View File

@ -0,0 +1,14 @@
package foldingLists02
import atomictest.eq
fun <T> List<T>.count(predicate: (T) -> Boolean): Int =
fold(0) {
count, element ->
if (predicate(element)) count + 1 else count
}
fun main(args: Array<String>) {
val list = listOf(1, -2, 3)
list.count { it > 0 } eq 2
}

View File

@ -0,0 +1,12 @@
type: edu
files:
- name: src/Task.kt
visible: true
placeholders:
- offset: 110
length: 106
placeholder_text: TODO("fold(???) { ??? }")
- name: test/Tests.kt
visible: false
feedback_link: |
https://docs.google.com/forms/d/e/1FAIpQLSdkaliSwYkjiV21bZl0yP-In2g5p17sAQCfaGjyHx_QYMWTiQ/viewform?usp=pp_url&entry.189755027=Functional+Programming+%2F+Folding+Lists+%2F+Exercise2

View File

@ -0,0 +1,2 @@
id: 497926
update_date: Wed, 03 Oct 2018 12:40:56 UTC

View File

@ -0,0 +1 @@
<h2 style="text-align: center;">Folding Lists (#2)</h2><p>Implement <code>count()</code> using <code>fold()</code>.</p>

View File

@ -0,0 +1,20 @@
package foldingLists02
import org.junit.Assert
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runners.MethodSorters
import kotlin.collections.count as countLibrary
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
class TestCount {
private fun <T> checkCount(list: List<T>, predicateString: String, predicate: (T) -> Boolean) {
Assert.assertEquals("Wrong implementation for 'count'. Wrong result for counting $predicateString in $list", list.countLibrary(predicate), list.count(predicate))
}
@Test
fun test1Sample() = checkCount(listOf(1, -2, 3), "{ it > 0 }") { it > 0 }
@Test
fun test2() = checkCount(listOf("abc", "cd", "eea"), "{ it.contains('a') }") { it.contains('a') }
}

View File

@ -0,0 +1,14 @@
package foldingLists3
import atomictest.eq
fun <T> List<T>.any(predicate: (T) -> Boolean): Boolean =
fold(false) {
found, element ->
if (predicate(element)) true else found
}
fun main(args: Array<String>) {
val list = listOf(1, -2, 3)
list.any { it < 0 } eq true
}

View File

@ -0,0 +1,12 @@
type: edu
files:
- name: src/Task.kt
visible: true
placeholders:
- offset: 111
length: 105
placeholder_text: TODO("fold(???) { ??? }")
- name: test/Tests.kt
visible: false
feedback_link: |
https://docs.google.com/forms/d/e/1FAIpQLSdkaliSwYkjiV21bZl0yP-In2g5p17sAQCfaGjyHx_QYMWTiQ/viewform?usp=pp_url&entry.189755027=Functional+Programming+%2F+Folding+Lists+%2F+Exercise3

View File

@ -0,0 +1,2 @@
id: 497927
update_date: Wed, 03 Oct 2018 12:40:57 UTC

View File

@ -0,0 +1 @@
<h2 style="text-align: center;">Folding Lists (#3)</h2><p>Implement <code>any()</code> using <code>fold()</code>.</p>

View File

@ -0,0 +1,23 @@
package foldingLists3
import org.junit.Assert
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runners.MethodSorters
import kotlin.collections.any as anyLibrary
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
class TestMapImpl {
private fun <T> checkAny(list: List<T>, predicateString: String, predicate: (T) -> Boolean) {
Assert.assertEquals("Wrong 'any' implementation. Wrong result for checking $predicateString in $list:", list.anyLibrary(predicate), list.any(predicate))
}
@Test
fun test1Sample() = checkAny(listOf(1, -2, 3), "{ it < 0 }") { it < 0 }
@Test
fun test2() = checkAny(listOf("abc", "cd", "eea"), "{ it.contains('a') }") { it.contains('a') }
@Test
fun test3() = checkAny(listOf("abc", "cd", "eea"), "{ it.contains('f') }") { it.contains('f') }
}

View File

@ -0,0 +1,24 @@
package foldingLists4
import atomictest.eq
class Condition(val check: (Int) -> Boolean)
fun Condition.combine(other: Condition): Condition =
Condition { check(it) && other.check(it) }
fun List<Condition>.combineAll(): Condition = reduce(Condition::combine)
fun main(args: Array<String>) {
val isPositive = Condition { it > 0 }
val isEven = Condition { it % 2 == 0 }
val lessThan10 = Condition { it < 10 }
val conditions = listOf(isPositive, isEven, lessThan10)
val isEvenPositiveAndLessThan10 = conditions.combineAll()
isEvenPositiveAndLessThan10.check(8) eq true
isEvenPositiveAndLessThan10.check(5) eq false
isEvenPositiveAndLessThan10.check(12) eq false
}

View File

@ -0,0 +1,12 @@
type: edu
files:
- name: src/Task.kt
visible: true
placeholders:
- offset: 249
length: 18
placeholder_text: TODO()
- name: test/Tests.kt
visible: false
feedback_link: |
https://docs.google.com/forms/d/e/1FAIpQLSdkaliSwYkjiV21bZl0yP-In2g5p17sAQCfaGjyHx_QYMWTiQ/viewform?usp=pp_url&entry.189755027=Functional+Programming+%2F+Folding+Lists+%2F+Exercise4

View File

@ -0,0 +1,2 @@
id: 497928
update_date: Wed, 03 Oct 2018 12:40:58 UTC

View File

@ -0,0 +1,4 @@
<h2 style="text-align: center;">Folding Lists (#4)</h2><p>Complete the implementation of the <code>combineAll()</code> function using <code>reduce()</code>.
It allows to combine several conditions (you can assume that a list is non-empty).
<code>Condition.combine()</code> function which combines two conditions is already
provided.</p>

View File

@ -0,0 +1,44 @@
package foldingLists4
import org.junit.Assert
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runners.MethodSorters
import kotlin.collections.any as anyLibrary
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
class TestConditions {
private fun checkSample(isEvenPositiveAndLessThan10: Condition, result: Boolean, value: Int) {
Assert.assertEquals("Wrong result for 'isEvenPositiveAndLessThan10.check(8)'",
result, isEvenPositiveAndLessThan10.check(value))
}
@Test
fun testSample() {
val isPositive = Condition { it > 0 }
val isEven = Condition { it % 2 == 0 }
val lessThan10 = Condition { it < 10 }
val conditions = listOf(isPositive, isEven, lessThan10)
val isEvenPositiveAndLessThan10 = conditions.combineAll()
checkSample(isEvenPositiveAndLessThan10, true, 8)
checkSample(isEvenPositiveAndLessThan10, false, 5)
checkSample(isEvenPositiveAndLessThan10, false, 12)
}
@Test
fun test2() {
val isPositive = Condition { it > 0 }
val isEven = Condition { it % 2 == 0 }
val lessThan10 = Condition { it < 10 }
val conditions = listOf(isPositive, isEven, lessThan10)
val isEvenPositiveAndLessThan10 = conditions.combineAll()
checkSample(isEvenPositiveAndLessThan10, true, 2)
checkSample(isEvenPositiveAndLessThan10, false, 7)
checkSample(isEvenPositiveAndLessThan10, false, 13)
}
}

View File

@ -0,0 +1,6 @@
content:
- Examples
- Exercise 1
- Exercise 2
- Exercise 3
- Exercise 4

View File

@ -0,0 +1,3 @@
id: 175322
update_date: Wed, 03 Oct 2018 12:51:47 UTC
unit: 150008

View File

@ -0,0 +1,28 @@
// FromListsToMaps/AssociateBy.kt
import fromliststomaps.*
import atomictest.eq
fun main(args: Array<String>) {
val map: Map<String, Person> =
people().associateBy { it.name }
map eq mapOf(
"Alice" to Person("Alice", 21),
"Arthricia" to Person("Arthricia", 15),
"Bob" to Person("Bob", 25),
"Bill" to Person("Bill", 25),
"Birdperson" to Person("Birdperson", 42),
"Charlie" to Person("Charlie", 21),
"Crocubot" to Person("Crocubot", 42),
"Franz" to Person("Franz", 21),
"Revolio" to Person("Revolio", 33))
// associateBy() fails when the key isn't
// unique -- elements disappear:
val ages = people().associateBy { it.age }
ages eq mapOf(
21 to Person("Franz", 21),
15 to Person("Arthricia", 15),
25 to Person("Bill", 25),
42 to Person("Crocubot", 42),
33 to Person("Revolio", 33))
}

View File

@ -0,0 +1,18 @@
// FromListsToMaps/FilteringMap.kt
import atomictest.eq
fun main(args: Array<String>) {
val map = mapOf(1 to "one",
2 to "two", 3 to "three", 4 to "four")
map.filterKeys { it % 2 == 1 } eq
"{1=one, 3=three}"
map.filterValues { it.contains('o') } eq
"{1=one, 2=two, 4=four}"
map.filter { entry ->
entry.key % 2 == 1 &&
entry.value.contains('o')
} eq "{1=one}"
}

View File

@ -0,0 +1,13 @@
// FromListsToMaps/GetOrPut.kt
import atomictest.eq
fun main(args: Array<String>) {
val map = mapOf(1 to "one", 2 to "two")
map.getOrElse(0) { "zero" } eq "zero"
val mutableMap = map.toMutableMap()
mutableMap.getOrPut(0) { "zero" } eq
"zero"
mutableMap eq "{1=one, 2=two, 0=zero}"
}

View File

@ -0,0 +1,21 @@
// FromListsToMaps/GroupBy.kt
import fromliststomaps.*
import atomictest.eq
fun main(args: Array<String>) {
val map: Map<Int, List<Person>> =
people().groupBy(Person::age)
map[15] eq listOf(Person("Arthricia", 15))
map[21] eq listOf(
Person("Alice", 21),
Person("Charlie", 21),
Person("Franz", 21))
map[22] eq null
map[25] eq listOf(
Person("Bob", 25),
Person("Bill", 25))
map[33] eq listOf(Person("Revolio", 33))
map[42] eq listOf(
Person("Birdperson", 42),
Person("Crocubot", 42))
}

View File

@ -0,0 +1,34 @@
// FromListsToMaps/GroupByVsFilter.kt
import fromliststomaps.*
import atomictest.eq
fun main(args: Array<String>) {
val groups =
people().groupBy { it.name.first() }
// groupBy() produces map-speed access:
groups['A'] eq listOf(Person("Alice", 21),
Person("Arthricia", 15))
groups['Z'] eq null
// Must repeat filter() for each character:
people().filter {
it.name.first() == 'A'
} eq listOf(Person("Alice", 21),
Person("Arthricia", 15))
people().filter {
it.name.first() == 'F'
} eq listOf(Person("Franz", 21))
people().partition {
it.name.first() == 'A'
} eq Pair(
listOf(Person("Alice", 21),
Person("Arthricia", 15)),
listOf(Person("Bob", 25),
Person("Bill", 25),
Person("Birdperson", 42),
Person("Charlie", 21),
Person("Crocubot", 42),
Person("Franz", 21),
Person("Revolio", 33)))
}

View File

@ -0,0 +1,14 @@
// FromListsToMaps/People.kt
package fromliststomaps
data class Person(
val name: String,
val age: Int
)
fun people() = listOf("Alice", "Arthricia",
"Bob", "Bill", "Birdperson", "Charlie",
"Crocubot", "Franz", "Revolio").zip(
listOf(21,15,25,25,42,21,42,21,33)) {
name, age -> Person(name, age)
}

View File

@ -0,0 +1,10 @@
// FromListsToMaps/SimilarOperation.kt
import atomictest.eq
fun main(args: Array<String>) {
val map = mapOf(1 to "one",
-2 to "minus two")
map.any { (key, _) -> key < 0 } eq true
map.all { (key, _) -> key < 0 } eq false
map.maxBy { it.key }?.value eq "one"
}

View File

@ -0,0 +1,23 @@
// FromListsToMaps/TransformingMap.kt
import atomictest.eq
fun main(args: Array<String>) {
val even = mapOf(2 to "two", 4 to "four")
even.map { // [1]
"${it.key}=${it.value}"
} eq listOf("2=two", "4=four")
even.map { (key, value) -> // [2]
"$key=$value"
} eq listOf("2=two", "4=four")
even.mapKeys { (num, _) -> -num } // [3]
.mapValues { (_, str) -> "minus $str" } eq
mapOf(-2 to "minus two",
-4 to "minus four")
even.map { (key, value) ->
-key to "minus $value"
}.toMap() eq mapOf(-2 to "minus two", // [4]
-4 to "minus four")
}

View File

@ -0,0 +1,18 @@
type: theory
files:
- name: src/People.kt
visible: true
- name: src/GroupBy.kt
visible: true
- name: src/GroupByVsFilter.kt
visible: true
- name: src/AssociateBy.kt
visible: true
- name: src/GetOrPut.kt
visible: true
- name: src/FilteringMap.kt
visible: true
- name: src/TransformingMap.kt
visible: true
- name: src/SimilarOperation.kt
visible: true

View File

@ -0,0 +1,2 @@
id: 497900
update_date: Wed, 03 Oct 2018 12:40:20 UTC

View File

@ -0,0 +1,2 @@
<h2 style="text-align: center;">From Lists to Maps</h2><p>Examples accompanying the atom.
<a href="https://stepik.org/lesson/107894/step/1" rel="nofollow noopener noreferrer">Read "From Lists to Maps" atom online.</a></p>

View File

@ -0,0 +1,22 @@
package fromListstoMaps01
import atomictest.eq
data class Person(val name: String, val age: Int)
fun buildAgeToNamesMap(people: List<Person>): Map<Int, List<String>> {
return people.groupBy(Person::age).mapValues { (_, group) ->
group.map(Person::name)
}
}
fun main(args: Array<String>) {
val people = listOf(Person("Alice", 21),
Person("Bob", 25), Person("Charlie", 25))
buildAgeToNamesMap(people) eq
mapOf(21 to listOf("Alice"),
25 to listOf("Bob", "Charlie"))
buildString { }
}

View File

@ -0,0 +1,12 @@
type: edu
files:
- name: src/Task.kt
visible: true
placeholders:
- offset: 175
length: 98
placeholder_text: TODO()
- name: test/Tests.kt
visible: false
feedback_link: |
https://docs.google.com/forms/d/e/1FAIpQLSdkaliSwYkjiV21bZl0yP-In2g5p17sAQCfaGjyHx_QYMWTiQ/viewform?usp=pp_url&entry.189755027=Functional+Programming+%2F+From+Lists+to+Maps+%2F+Exercise1

View File

@ -0,0 +1,2 @@
id: 497901
update_date: Wed, 03 Oct 2018 12:40:21 UTC

View File

@ -0,0 +1,2 @@
<h2 style="text-align: center;">From Lists to Maps (#1)</h2><p>Implement the function that given a list of people builds a map where key
is age and value is a list of names of people of this age.</p>

View File

@ -0,0 +1,41 @@
package fromListstoMaps01
import org.junit.Assert
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runners.MethodSorters
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
class TestPersonsMap {
private fun check(
list: List<Person>
) {
Assert.assertEquals("Wrong result for $list:",
list.groupBy(Person::age).mapValues { (_, group) ->
group.map(Person::name)
},
buildAgeToNamesMap(list))
}
@Test
fun test1Sample() = check(listOf(Person("Alice", 21),
Person("Bob", 25), Person("Charlie", 25)))
@Test
fun test2() = check(listOf())
@Test
fun test3() = check(listOf(Person("Alice", 21), Person("Bob", 25)))
@Test
fun test4() = check(listOf(Person("Bob", 25), Person("Charlie", 25)))
@Test
fun test5() = check(listOf(
Person("A", 10), Person("B", 10),
Person("C", 20), Person("D", 20), Person("E", 20), Person("F", 20),
Person("X", 30), Person("Y", 30), Person("Z", 30)
))
}

View File

@ -0,0 +1,21 @@
package fromListstoMaps02
import atomictest.eq
fun <T, R> List<T>.groupBy(keySelector: (T) -> R): Map<R, List<T>> {
val result = mutableMapOf<R, MutableList<T>>()
for (element in this) {
val list = result.getOrPut(keySelector(element)) { mutableListOf() }
list += element
}
return result
}
data class Person(val name: String, val age: Int)
fun main(args: Array<String>) {
val people = listOf(Person("Alice", 21),
Person("Bob", 25), Person("Charlie", 25))
people.groupBy(Person::age) eq ""
}

View File

@ -0,0 +1,12 @@
type: edu
files:
- name: src/Task.kt
visible: true
placeholders:
- offset: 173
length: 130
placeholder_text: TODO()
- name: test/Tests.kt
visible: false
feedback_link: |
https://docs.google.com/forms/d/e/1FAIpQLSdkaliSwYkjiV21bZl0yP-In2g5p17sAQCfaGjyHx_QYMWTiQ/viewform?usp=pp_url&entry.189755027=Functional+Programming+%2F+From+Lists+to+Maps+%2F+Exercise2

View File

@ -0,0 +1,2 @@
id: 497902
update_date: Wed, 03 Oct 2018 12:40:23 UTC

View File

@ -0,0 +1 @@
<h2 style="text-align: center;">From Lists to Maps (#2)</h2><p>Implement <code>groupBy()</code> function. Use <code>getOrPut()</code>.</p>

View File

@ -0,0 +1,37 @@
package fromListstoMaps02
import org.junit.Assert
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runners.MethodSorters
import kotlin.collections.groupBy as groupByLibrary
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
class TestPersonsMap {
private fun <T, R> check(
list: List<T>,
keySelector: (T) -> R,
keySelectorStr: String
) {
Assert.assertEquals("Wrong result for $list grouped by $keySelectorStr",
list.groupByLibrary(keySelector),
list.groupBy(keySelector))
}
@Test
fun test1Sample() = check(listOf(Person("Alice", 21),
Person("Bob", 25), Person("Charlie", 25)),
Person::age, "Person::age")
@Test
fun test2() = check(listOf("abc", "ahh", "never"),
{ it.first() }, "{ it.first() }")
@Test
fun test3() = check((1..20).toList(), { it % 3 }, "{ it % 3 }")
@Test
fun test4() = check(listOf(Person("Alice", 21),
Person("Bob", 25), Person("Charlie", 25)),
Person::name, "Person::name")
}

View File

@ -0,0 +1,15 @@
package fromListstoMaps03
import atomictest.eq
fun <T, R> List<T>.associateBy(keySelector: (T) -> R): Map<R, T> =
groupBy(keySelector).mapValues { it.value.last() }
data class Person(val name: String, val age: Int)
fun main(args: Array<String>) {
val people = listOf(Person("Alice", 21),
Person("Bob", 25), Person("Charlie", 25))
people.associateBy(Person::name) eq ""
}

View File

@ -0,0 +1,12 @@
type: edu
files:
- name: src/Task.kt
visible: true
placeholders:
- offset: 124
length: 50
placeholder_text: TODO("groupBy(???).???")
- name: test/Tests.kt
visible: false
feedback_link: |
https://docs.google.com/forms/d/e/1FAIpQLSdkaliSwYkjiV21bZl0yP-In2g5p17sAQCfaGjyHx_QYMWTiQ/viewform?usp=pp_url&entry.189755027=Functional+Programming+%2F+From+Lists+to+Maps+%2F+Exercise3

View File

@ -0,0 +1,2 @@
id: 497903
update_date: Wed, 03 Oct 2018 12:40:24 UTC

View File

@ -0,0 +1,3 @@
<h2 style="text-align: center;">From Lists to Maps (#3)</h2><p>Implement <code>associateBy</code> using <code>groupBy</code>.
If two elements have the same key returned by <code>keySelector</code> the last one should
be added to the map.</p>

View File

@ -0,0 +1,37 @@
package fromListstoMaps03
import org.junit.Assert
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runners.MethodSorters
import kotlin.collections.associateBy as associateByLibrary
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
class TestPersonsMap {
private fun <T, R> check(
list: List<T>,
keySelector: (T) -> R,
keySelectorStr: String
) {
Assert.assertEquals("Wrong result for $list associated by $keySelectorStr",
list.associateByLibrary(keySelector),
list.associateBy(keySelector))
}
@Test
fun test1Sample() = check(listOf(Person("Alice", 21),
Person("Bob", 25), Person("Charlie", 25)),
Person::age, "Person::age")
@Test
fun test2() = check(listOf("abc", "ahh", "never"),
{ it.first() }, "{ it.first() }")
@Test
fun test3() = check((1..5).toList(), { it }, "{ it }")
@Test
fun test4() = check(listOf(Person("Alice", 21),
Person("Bob", 25), Person("Charlie", 25)),
Person::name, "Person::name")
}

View File

@ -0,0 +1,5 @@
content:
- Examples
- Exercise 1
- Exercise 2
- Exercise 3

View File

@ -0,0 +1,3 @@
id: 175315
update_date: Wed, 03 Oct 2018 12:50:51 UTC
unit: 150001

View File

@ -0,0 +1,24 @@
// FunctionTypes/AnyFunImplementation.kt
import atomictest.eq
fun <T> List<T>.any( // [1]
predicate: (T) -> Boolean // [2]
): Boolean {
for (element in this) {
if (predicate(element)) // [3]
return true
}
return false
}
fun main(args: Array<String>) {
val ints = listOf(1, 2, -3)
ints.any { it > 0 } eq true // [4]
val strings = listOf("abc", " ")
strings.any { it.isBlank() } eq true // [5]
strings.any { it.isBlank() } eq true // [5]
strings.any(String::isNotBlank) eq // [6]
true
}

View File

@ -0,0 +1,19 @@
// FunctionTypes/DefiningRepeat.kt
package definingrepeat
fun repeat(
times: Int,
action: (Int) -> Unit // [1]
) {
for (index in 0 until times)
action(index) // [2]
}
fun main(args: Array<String>) {
repeat(3) { println("#$it") } // [3]
}
/* Output:
#0
#1
#2
*/

View File

@ -0,0 +1,12 @@
// FunctionTypes/FunctionTypeExamples.kt
import atomictest.eq
fun main(args: Array<String>) {
val helloWorld: () -> String =
{ "Hello, world!" }
helloWorld() eq "Hello, world!"
val sum: (Int, Int) -> Int =
{ x, y -> x + y }
sum(1, 2) eq 3
}

View File

@ -0,0 +1,14 @@
// FunctionTypes/NullableFunctionType.kt
import atomictest.eq
fun main(args: Array<String>) {
val returnTypeNullable: (String) -> Int? =
{ null }
val mightBeNull: ((String) -> Int)? = null
returnTypeNullable("abc") eq null
// Won't compile without a null check:
// mightBeNull("abc")
if (mightBeNull != null) {
mightBeNull("abc")
}
}

View File

@ -0,0 +1,14 @@
// FunctionTypes/NullableReturnType.kt
import atomictest.eq
fun main(args: Array<String>) {
val transform: (String) -> Int? =
{ s: String -> s.toIntOrNull() }
transform("112") eq 112
transform("abc") eq null
val list = listOf("112", "abc")
list.mapNotNull(transform) eq listOf(112)
list.mapNotNull { it.toIntOrNull() } eq
listOf(112)
}

View File

@ -0,0 +1,9 @@
// FunctionTypes/RepeatByInt.kt
fun main(args: Array<String>) {
repeat(2) { println("hi!") }
}
/* Output:
hi!
hi!
*/

View File

@ -0,0 +1,9 @@
// FunctionTypes/RepeatVerbose.kt
fun main(args: Array<String>) {
repeat(2, { println("hi!") })
}
/* Output:
hi!
hi!
*/

View File

@ -0,0 +1,9 @@
// FunctionTypes/SimpleOperation.kt
import atomictest.eq
fun main(args: Array<String>) {
val isPositive: (Int) -> Boolean =
{ it > 0 }
val list = listOf(1, 2, -3)
list.any(isPositive) eq true
}

View File

@ -0,0 +1,18 @@
type: theory
files:
- name: src/SimpleOperation.kt
visible: true
- name: src/FunctionTypeExamples.kt
visible: true
- name: src/AnyFunImplementation.kt
visible: true
- name: src/RepeatByInt.kt
visible: true
- name: src/RepeatVerbose.kt
visible: true
- name: src/DefiningRepeat.kt
visible: true
- name: src/NullableReturnType.kt
visible: true
- name: src/NullableFunctionType.kt
visible: true

View File

@ -0,0 +1,2 @@
id: 497887
update_date: Wed, 03 Oct 2018 12:40:05 UTC

View File

@ -0,0 +1,2 @@
<h2 style="text-align: center;">Function Types</h2><p>Examples accompanying the atom.
<a href="https://stepik.org/lesson/107892/step/1" rel="nofollow noopener noreferrer">Read "Function Types" atom online.</a></p>

View File

@ -0,0 +1,16 @@
package functionTypes1
import atomictest.eq
fun <T, R> List<T>.map(transform: (T) -> R): List<R> {
val result = mutableListOf<R>()
for (e in this) {
result += transform(e)
}
return result
}
fun main(args: Array<String>) {
val list = listOf(1, 2, 3)
list.map { "$it!" } eq listOf("1!", "2!", "3!")
}

View File

@ -0,0 +1,12 @@
type: edu
files:
- name: src/Task.kt
visible: true
placeholders:
- offset: 141
length: 54
placeholder_text: TODO()
- name: test/Tests.kt
visible: false
feedback_link: |
https://docs.google.com/forms/d/e/1FAIpQLSdkaliSwYkjiV21bZl0yP-In2g5p17sAQCfaGjyHx_QYMWTiQ/viewform?usp=pp_url&entry.189755027=Functional+Programming+%2F+Function+Types+%2F+Exercise1

View File

@ -0,0 +1,2 @@
id: 497888
update_date: Wed, 03 Oct 2018 12:40:06 UTC

View File

@ -0,0 +1 @@
<h2 style="text-align: center;">Function Types (#1)</h2><p>Implement <code>map()</code> function by hand.</p>

View File

@ -0,0 +1,33 @@
package functionTypes1
import org.junit.Assert
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runners.MethodSorters
import kotlin.collections.map as mapLibrary
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
class TestMapImpl {
private fun <T, R> check(
list: List<T>,
predicateStr: String,
predicate: (T) -> R
) {
Assert.assertEquals("Wrong result for $list\n" +
"predicate = $predicateStr",
list.map(predicate),
list.mapLibrary(predicate))
}
@Test
fun test1Sample() = check(listOf(1, 2, 3), "\$it!") { "$it!" }
@Test
fun test2() = check(listOf("1", "2", "3"), "{ it.toInt() }") { it.toInt() }
@Test
fun test3() = check(listOf("1", "2", "d"), "{ it.toIntOrNull() }") { it.toIntOrNull() }
@Test
fun test4() = check(listOf('a', 'b', 'd'), "{ it + 1 }") { it + 1 }
}

View File

@ -0,0 +1,17 @@
package functionTypes2
import atomictest.eq
fun List<Int>.transform1(): List<Int> {
return filter { it % 2 == 0 }.map { it * it }
}
fun List<Int>.transform2(): List<Int> {
return mapNotNull { if (it % 2 == 0) it * it else null }
}
fun main(args: Array<String>) {
val list = listOf(1, 2, 3)
list.transform1() eq listOf(4)
list.transform2() eq listOf(4)
}

View File

@ -0,0 +1,12 @@
type: edu
files:
- name: src/Task.kt
visible: true
placeholders:
- offset: 203
length: 34
placeholder_text: TODO()
- name: test/Tests.kt
visible: false
feedback_link: |
https://docs.google.com/forms/d/e/1FAIpQLSdkaliSwYkjiV21bZl0yP-In2g5p17sAQCfaGjyHx_QYMWTiQ/viewform?usp=pp_url&entry.189755027=Functional+Programming+%2F+Function+Types+%2F+Exercise2

View File

@ -0,0 +1,2 @@
id: 497889
update_date: Wed, 03 Oct 2018 12:40:06 UTC

View File

@ -0,0 +1,3 @@
<h2 style="text-align: center;">Function Types (#2)</h2><p>Replace the code that calls first <code>filter()</code>, then <code>map()</code> with one invocation
of the function <code>mapNotNull()</code>. Complete the implementation of <code>transform2()</code>
function so that it worked similarly to <code>transform1()</code>.</p>

View File

@ -0,0 +1,27 @@
package functionTypes2
import org.junit.Assert
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runners.MethodSorters
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
class TestMapNotNull {
private fun check(
list: List<Int>
) {
Assert.assertEquals("Wrong result for $list:",
list.filter { it % 2 == 0 }.map { it * it },
list.transform2())
list.transform1()
}
@Test
fun test1Sample() = check(listOf(1, 2, 3))
@Test
fun test2() = check(listOf(1, -2, 3, -4))
@Test
fun test3() = check(listOf(11, 22, 30))
}

View File

@ -0,0 +1,25 @@
package functionTypes3
import atomictest.eq
fun <T, R : Any> Iterable<T>.mapIndexedNotNull(
transform: (Int, T) -> R?
): List<R> {
val result = mutableListOf<R>()
for ((index, e) in this.withIndex()) {
val transformed = transform(index, e)
if (transformed != null) {
result += transformed
}
}
return result
}
fun main(args: Array<String>) {
val list = listOf("a", "b", "c", "d")
list.mapIndexedNotNull { index, s ->
if (index % 2 == 0) "$s!" else null
} eq listOf("a!", "c!")
}

View File

@ -0,0 +1,12 @@
type: edu
files:
- name: src/Task.kt
visible: true
placeholders:
- offset: 181
length: 179
placeholder_text: TODO()
- name: test/Tests.kt
visible: false
feedback_link: |
https://docs.google.com/forms/d/e/1FAIpQLSdkaliSwYkjiV21bZl0yP-In2g5p17sAQCfaGjyHx_QYMWTiQ/viewform?usp=pp_url&entry.189755027=Functional+Programming+%2F+Function+Types+%2F+Exercise3

View File

@ -0,0 +1,2 @@
id: 497890
update_date: Wed, 03 Oct 2018 12:40:07 UTC

View File

@ -0,0 +1,9 @@
<h2 style="text-align: center;">Function Types (#3)</h2><p>Implement <code>mapIndexedNotNull()</code> function by hand. Like <code>mapNotNull()</code> it applies
the given transformation to each element and filters out <code>null</code>s.
Like <code>mapIndexed()</code> it bases the transformation on both the element and
its index.</p><p>Note the generic types <code>R?</code> (in <code>(Int, T) -&gt; R?</code>) and <code>List&lt;R&gt;</code>.
Lambda argument may return <code>null</code> as a result, so lambda's return type
is nullable <code>R?</code>. <code>mapIndexNotNull()</code> returns a list of non-nullable elements,
so the function return type is <code>List&lt;R&gt;</code>. To express that <code>R</code> is a non-nullable
type, we specify the constraint on a generic type parameter <code>R : Any</code>. Type
constraints will be covered in [Generics] later.</p>

View File

@ -0,0 +1,40 @@
package functionTypes3
import org.junit.Assert
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runners.MethodSorters
import kotlin.collections.mapIndexedNotNull as mapIndexedNotNullLibrary
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
class TestMapIndexedNotNullImpl {
private fun <T, R : Any> check(
list: List<T>,
predicateStr: String,
predicate: (Int, T) -> R?
) {
Assert.assertEquals("Wrong result for $list\n" +
"predicate = $predicateStr",
list.mapIndexedNotNull(predicate),
list.mapIndexedNotNullLibrary(predicate))
}
@Test
fun test1Sample() = check(listOf(1, 2, 3), "{ index, e -> \"\$index: \$e!\" }") { index, e -> "$index: $e!" }
@Test
fun test2() = check(listOf("1", "2", "3"), "{ index, e -> index + e.toInt() }") { index, e -> index + e.toInt() }
@Test
fun test3() = check(listOf("1", "2", "d"),
"""
{
index, e ->
val i = e.toIntOrNull()
if (i == null) null else index * i
}""".replaceIndent()
) { index, e ->
val i = e.toIntOrNull()
if (i == null) null else index * i
}
}

View File

@ -0,0 +1,15 @@
package functionTypes4
fun <A, B, C> ((A) -> B).andThen(action: (B) -> C): (A) -> C =
{ a: A -> action(this(a)) }
fun main(args: Array<String>) {
val multiply2: (Int) -> Int = { x: Int -> x * 2 }
val println: (Int) -> Unit = { i: Int -> println("Result: $i") }
val composition = multiply2.andThen(println)
composition(5)
}
/* Output:
Result: 10
*/

View File

@ -0,0 +1,12 @@
type: edu
files:
- name: src/Task.kt
visible: true
placeholders:
- offset: 105
length: 15
placeholder_text: TODO()
- name: test/Tests.kt
visible: false
feedback_link: |
https://docs.google.com/forms/d/e/1FAIpQLSdkaliSwYkjiV21bZl0yP-In2g5p17sAQCfaGjyHx_QYMWTiQ/viewform?usp=pp_url&entry.189755027=Functional+Programming+%2F+Function+Types+%2F+Exercise4

View File

@ -0,0 +1,2 @@
id: 497891
update_date: Wed, 03 Oct 2018 12:40:08 UTC

View File

@ -0,0 +1,4 @@
<h2 style="text-align: center;">Function Types (#4)</h2><p>Implement <code>andThen()</code> function. It combines the actions of two functions.
<code>f.andThen(g)</code> should return a new function that first applies <code>f</code>, and then
applies <code>g</code> to the result: <code>{arg -&gt; g(f(arg))}</code>.
Note that <code>andThen()</code> is declared as an extension function on a function type.</p>

View File

@ -0,0 +1,52 @@
package functionTypes4
import org.junit.Assert
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runners.MethodSorters
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
class TestAndThen {
private fun <A, B, C> check(
arg: A,
f: (A) -> B,
g: (B) -> C,
fStr: String,
gStr: String
) {
Assert.assertEquals("Wrong result for f(g(arg))\n" +
"arg = $arg\n" +
"f = $fStr\n" +
"g = $gStr",
g(f(arg)),
f.andThen(g)(arg))
}
@Test
fun test1() = check("123",
f = { s: String -> s.toInt() },
g = { i: Int -> i + 1 },
fStr = "{ s: String -> s.toInt() }",
gStr = "{ i: Int -> i + 1 }")
@Test
fun test2() = check(111,
f = { i: Int -> i + 1 },
g = { i: Int -> i.toString() },
fStr = "{ i: Int -> i + 1 }",
gStr = "{ i: Int -> i.toString() }")
@Test
fun test3() = check(listOf(1, 2, 3),
f = { l: List<Int> -> l.map { it + 1 } },
g = { l: List<Int> -> l.joinToString() },
fStr = "{ l: List<Int> -> l.map { it + 1 } }",
gStr = "{ l: List<Int> -> l.joinToString() }")
@Test
fun test4() = check("ABC",
f = { s: String -> s.toIntOrNull() },
g = { i: Int? -> i ?: 0 },
fStr = "{ s: String -> s.toIntOrNull() }",
gStr = "{ i: Int? -> i ?: 0 }")
}

View File

@ -0,0 +1,6 @@
content:
- Examples
- Exercise 1
- Exercise 2
- Exercise 3
- Exercise 4

View File

@ -0,0 +1,3 @@
id: 175313
update_date: Wed, 03 Oct 2018 12:50:35 UTC
unit: 149999

View File

@ -0,0 +1,13 @@
// LocalFunctions/CustomLabel.kt
fun main(args: Array<String>) {
val list = listOf(1, 2, 3, 4, 5)
val value = 3
list.forEach tag@{ // [1]
if (it == value) return@tag // [2]
}
println("This line is called")
}
/* Output:
This line is called
*/

View File

@ -0,0 +1,27 @@
// LocalFunctions/HelperFunction.kt
package localfunctions
import atomictest.eq
class Window(
var height: Int,
var width: Int,
var isVisible: Boolean
)
fun minimizeWindow(window: Window) {
with(window) {
if (!window.isVisible) return // [1]
height = 0
width = 0
}
// ... // [2]
}
fun main(args: Array<String>) {
Window(100, 100, true)
.also { minimizeWindow(it) }
.height eq 0
Window(100, 100, false)
.also { minimizeWindow(it) }
.height eq 100
}

View File

@ -0,0 +1,15 @@
// LocalFunctions/InterestingSessions.kt
package localfunctions
import atomictest.eq
fun main(args: Array<String>) {
sessions.any(
fun(session: Session): Boolean { // [1]
if (session.title.contains("Kotlin") &&
session.speaker in myFavSpeakers) {
return true
}
// ... more checks
return false
}) eq true
}

View File

@ -0,0 +1,14 @@
// LocalFunctions/LabeledReturn.kt
package localfunctions
import atomictest.eq
fun main(args: Array<String>) {
sessions.any { session ->
if (session.title.contains("Kotlin") &&
session.speaker in myFavSpeakers) {
return@any true
}
// ... more checks
false
} eq true
}

View File

@ -0,0 +1,10 @@
// LocalFunctions/LocalExtensions.kt
import atomictest.eq
fun main(args: Array<String>) {
fun String.exclaim() = "$this!"
"Hello".exclaim() eq "Hello!"
"Hallo".exclaim() eq "Hallo!"
"Bonjour".exclaim() eq "Bonjour!"
"Ciao".exclaim() eq "Ciao!"
}

View File

@ -0,0 +1,15 @@
// LocalFunctions/LocalFunctionReference.kt
package localfunctions
import atomictest.eq
fun main(args: Array<String>) {
fun interesting(session: Session): Boolean {
if (session.title.contains("Kotlin") &&
session.speaker in myFavSpeakers) {
return true
}
// ... more checks
return false
}
sessions.any(::interesting) eq true
}

View File

@ -0,0 +1,16 @@
// LocalFunctions/LocalFunctions.kt
fun main(args: Array<String>) {
val logMsg = StringBuilder()
fun log(message: String) =
logMsg.appendln(message)
log("Starting computation")
// Imitating computation
val x = 42
log("Computation result: $x")
println(logMsg.toString())
}
/* Output:
Starting computation
Computation result: 42
*/

View File

@ -0,0 +1,12 @@
// LocalFunctions/ReturnFromFun.kt
fun main(args: Array<String>) {
val list = listOf(1, 2, 3, 4, 5)
val value = 3
list.forEach {
if (it == value) return // [1]
}
println("This line is NOT called") // [2]
}
/* Output:
*/

View File

@ -0,0 +1,12 @@
// LocalFunctions/Session.kt
package localfunctions
class Session(
val title: String,
val speaker: String
)
val sessions = listOf(Session(
"Kotlin in Production", "Christina Lee"))
val myFavSpeakers = setOf("Christina Lee")

Some files were not shown because too many files have changed in this diff Show More