Converted AtomicKotlin course to a new format
This commit is contained in:
commit
b40d0329be
|
@ -0,0 +1,5 @@
|
|||
.idea
|
||||
.gradle
|
||||
/.coursecreator/
|
||||
/**/build
|
||||
/**/out
|
|
@ -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
|
||||
}
|
|
@ -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 + (*))))"
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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
|
|
@ -0,0 +1,2 @@
|
|||
id: 497924
|
||||
update_date: Wed, 03 Oct 2018 12:40:54 UTC
|
|
@ -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>
|
|
@ -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
|
||||
}
|
|
@ -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
|
|
@ -0,0 +1,2 @@
|
|||
id: 497925
|
||||
update_date: Wed, 03 Oct 2018 12:40:55 UTC
|
|
@ -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>
|
|
@ -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))
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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
|
|
@ -0,0 +1,2 @@
|
|||
id: 497926
|
||||
update_date: Wed, 03 Oct 2018 12:40:56 UTC
|
|
@ -0,0 +1 @@
|
|||
<h2 style="text-align: center;">Folding Lists (#2)</h2><p>Implement <code>count()</code> using <code>fold()</code>.</p>
|
|
@ -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') }
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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
|
|
@ -0,0 +1,2 @@
|
|||
id: 497927
|
||||
update_date: Wed, 03 Oct 2018 12:40:57 UTC
|
|
@ -0,0 +1 @@
|
|||
<h2 style="text-align: center;">Folding Lists (#3)</h2><p>Implement <code>any()</code> using <code>fold()</code>.</p>
|
|
@ -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') }
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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
|
|
@ -0,0 +1,2 @@
|
|||
id: 497928
|
||||
update_date: Wed, 03 Oct 2018 12:40:58 UTC
|
|
@ -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>
|
|
@ -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)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
content:
|
||||
- Examples
|
||||
- Exercise 1
|
||||
- Exercise 2
|
||||
- Exercise 3
|
||||
- Exercise 4
|
|
@ -0,0 +1,3 @@
|
|||
id: 175322
|
||||
update_date: Wed, 03 Oct 2018 12:51:47 UTC
|
||||
unit: 150008
|
|
@ -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))
|
||||
}
|
|
@ -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}"
|
||||
}
|
|
@ -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}"
|
||||
}
|
|
@ -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))
|
||||
}
|
|
@ -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)))
|
||||
}
|
|
@ -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)
|
||||
}
|
|
@ -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"
|
||||
}
|
|
@ -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")
|
||||
}
|
|
@ -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
|
|
@ -0,0 +1,2 @@
|
|||
id: 497900
|
||||
update_date: Wed, 03 Oct 2018 12:40:20 UTC
|
|
@ -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>
|
|
@ -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 { }
|
||||
}
|
|
@ -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
|
|
@ -0,0 +1,2 @@
|
|||
id: 497901
|
||||
update_date: Wed, 03 Oct 2018 12:40:21 UTC
|
|
@ -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>
|
|
@ -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)
|
||||
))
|
||||
}
|
|
@ -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 ""
|
||||
}
|
|
@ -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
|
|
@ -0,0 +1,2 @@
|
|||
id: 497902
|
||||
update_date: Wed, 03 Oct 2018 12:40:23 UTC
|
|
@ -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>
|
|
@ -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")
|
||||
}
|
|
@ -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 ""
|
||||
}
|
|
@ -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
|
|
@ -0,0 +1,2 @@
|
|||
id: 497903
|
||||
update_date: Wed, 03 Oct 2018 12:40:24 UTC
|
|
@ -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>
|
|
@ -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")
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
content:
|
||||
- Examples
|
||||
- Exercise 1
|
||||
- Exercise 2
|
||||
- Exercise 3
|
|
@ -0,0 +1,3 @@
|
|||
id: 175315
|
||||
update_date: Wed, 03 Oct 2018 12:50:51 UTC
|
||||
unit: 150001
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
*/
|
|
@ -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
|
||||
}
|
|
@ -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")
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
// FunctionTypes/RepeatByInt.kt
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
repeat(2) { println("hi!") }
|
||||
}
|
||||
/* Output:
|
||||
hi!
|
||||
hi!
|
||||
*/
|
|
@ -0,0 +1,9 @@
|
|||
// FunctionTypes/RepeatVerbose.kt
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
repeat(2, { println("hi!") })
|
||||
}
|
||||
/* Output:
|
||||
hi!
|
||||
hi!
|
||||
*/
|
|
@ -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
|
||||
}
|
|
@ -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
|
|
@ -0,0 +1,2 @@
|
|||
id: 497887
|
||||
update_date: Wed, 03 Oct 2018 12:40:05 UTC
|
|
@ -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>
|
|
@ -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!")
|
||||
}
|
|
@ -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
|
|
@ -0,0 +1,2 @@
|
|||
id: 497888
|
||||
update_date: Wed, 03 Oct 2018 12:40:06 UTC
|
|
@ -0,0 +1 @@
|
|||
<h2 style="text-align: center;">Function Types (#1)</h2><p>Implement <code>map()</code> function by hand.</p>
|
|
@ -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 }
|
||||
}
|
|
@ -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)
|
||||
}
|
|
@ -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
|
|
@ -0,0 +1,2 @@
|
|||
id: 497889
|
||||
update_date: Wed, 03 Oct 2018 12:40:06 UTC
|
|
@ -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>
|
|
@ -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))
|
||||
}
|
|
@ -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!")
|
||||
}
|
|
@ -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
|
|
@ -0,0 +1,2 @@
|
|||
id: 497890
|
||||
update_date: Wed, 03 Oct 2018 12:40:07 UTC
|
9
9