Regenerated samples
This commit is contained in:
parent
7544ee333c
commit
f18e5da6d7
|
@ -24,9 +24,9 @@ private fun <L, R> runTest(
|
|||
* Compares the string representation
|
||||
* of the object with the string `value`.
|
||||
*/
|
||||
infix fun <T : Any> T.eq(value: String) {
|
||||
runTest(this, value) {
|
||||
this.toString() == value.trimIndent()
|
||||
infix fun <T : Any> T.eq(rval: String) {
|
||||
runTest(this, rval) {
|
||||
this.toString().trim() == rval.trimIndent()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -34,9 +34,9 @@ infix fun <T : Any> T.eq(value: String) {
|
|||
* Verifies that this object is
|
||||
* equal to `value`.
|
||||
*/
|
||||
infix fun <T> T.eq(value: T) {
|
||||
runTest(this, value) {
|
||||
this == value
|
||||
infix fun <T> T.eq(rval: T) {
|
||||
runTest(this, rval) {
|
||||
this == rval
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -44,9 +44,9 @@ infix fun <T> T.eq(value: T) {
|
|||
* Verifies that this object is not
|
||||
* equal to `value`.
|
||||
*/
|
||||
infix fun <T> T.neq(value: T) {
|
||||
runTest(this, value, checkEquals = false) {
|
||||
this != value
|
||||
infix fun <T> T.neq(rval: T) {
|
||||
runTest(this, rval, checkEquals = false) {
|
||||
this != rval
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -54,9 +54,9 @@ infix fun <T> T.neq(value: T) {
|
|||
* Verifies that a `Double` number is equal
|
||||
* to `value` within a positive delta.
|
||||
*/
|
||||
infix fun Double.eq(value: Double) {
|
||||
runTest(this, value) {
|
||||
abs(this - value) < 0.0000001
|
||||
infix fun Double.eq(rval: Double) {
|
||||
runTest(this, rval) {
|
||||
abs(this - rval) < 0.0000001
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -16,4 +16,4 @@ val ages = listOf(21, 15, 25, 25, 42, 21,
|
|||
fun people(): List<Person> =
|
||||
names.zip(ages) { name, age ->
|
||||
Person(name, age)
|
||||
}
|
||||
}
|
|
@ -1,5 +1,4 @@
|
|||
## Building Maps (#1)
|
||||
|
||||
Implement a function named `demographic(people: List<Person>)` returning a
|
||||
`Map` where the key is age and the value is a list of names of people of that
|
||||
age.
|
||||
Implement a function named `demographic(people: List<Person>)` returning a `Map`
|
||||
where the key is age and the value is a list of names of people of that age.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
## Building Maps (#3)
|
||||
|
||||
Implement `associateBy(keySelector: (T) -> R)` using `groupBy()`. If two
|
||||
elements have the same key produced by `keySelector` then the last one should
|
||||
be added to the `Map`.
|
||||
elements have the same key produced by `keySelector` then the last one should be
|
||||
added to the `Map`.
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
// FoldingLists/FoldAndReduce.kt
|
||||
import atomictest.eq
|
||||
|
||||
fun main() {
|
||||
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
|
||||
}
|
|
@ -3,16 +3,9 @@ import atomictest.eq
|
|||
|
||||
fun main() {
|
||||
val list = listOf(1, 10, 100, 1000)
|
||||
val initial = 0
|
||||
var accumulator = 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)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
// FoldingLists/ReduceAndReduceRight.kt
|
||||
import atomictest.eq
|
||||
|
||||
fun main() {
|
||||
val chars = "A B C D E F G H I".split(" ")
|
||||
chars.fold("X") { a, e -> "$a $e"} eq
|
||||
"X A B C D E F G H I"
|
||||
chars.foldRight("X") { a, e -> "$a $e" } eq
|
||||
"A B C D E F G H I X"
|
||||
chars.reduce { a, e -> "$a $e" } eq
|
||||
"A B C D E F G H I"
|
||||
chars.reduceRight { a, e -> "$a $e" } eq
|
||||
"A B C D E F G H I"
|
||||
}
|
|
@ -6,7 +6,7 @@ files:
|
|||
visible: true
|
||||
- name: src/FoldRight.kt
|
||||
visible: true
|
||||
- name: src/FoldAndReduce.kt
|
||||
- name: src/ReduceAndReduceRight.kt
|
||||
visible: true
|
||||
- name: src/RunningFold.kt
|
||||
visible: true
|
||||
|
|
|
@ -18,7 +18,6 @@ fun main() {
|
|||
val isEvenPositiveAndLessThan10 = conditions.combineAll()
|
||||
|
||||
isEvenPositiveAndLessThan10.check(8) eq true
|
||||
|
||||
isEvenPositiveAndLessThan10.check(5) eq false
|
||||
isEvenPositiveAndLessThan10.check(12) eq false
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
## Folding Lists (#4)
|
||||
|
||||
The starter code provides a `Condition` class and a function
|
||||
`Condition.combine()` that combines two conditions. There's also a skeleton
|
||||
for the `List<Condition>` extension function `combineAll()` that combines all
|
||||
the conditions in the `List`. Complete the implementation using `reduce()`,
|
||||
assuming the `List` is non-empty.
|
||||
`Condition.combine()` that combines two conditions. There's also a skeleton for
|
||||
the `List<Condition>` extension function `combineAll()` that combines all the
|
||||
conditions in the `List`. Complete the implementation using `reduce()`, assuming
|
||||
the `List` is non-empty.
|
||||
|
|
|
@ -8,7 +8,7 @@ fun main() {
|
|||
log("Starting computation")
|
||||
val x = 42 // Imitate computation
|
||||
log("Computation result: $x")
|
||||
logMsg.toString().trim() eq """
|
||||
logMsg.toString() eq """
|
||||
Starting computation
|
||||
Computation result: 42
|
||||
"""
|
||||
|
|
|
@ -3,9 +3,7 @@ package localfunctions
|
|||
import atomictest.eq
|
||||
|
||||
fun first(): (Int) -> Int {
|
||||
val func = fun (i: Int): Int {
|
||||
return i + 1
|
||||
}
|
||||
val func = fun(i: Int) = i + 1
|
||||
func(1) eq 2
|
||||
return func
|
||||
}
|
||||
|
@ -21,12 +19,26 @@ fun third(): () -> String {
|
|||
return ::greet
|
||||
}
|
||||
|
||||
fun main() {
|
||||
val firstFun: (Int) -> Int = first()
|
||||
val secondFun: (String) -> String = second()
|
||||
val thirdFun: () -> String = third()
|
||||
fun fourth() = fun() = "Hi!"
|
||||
|
||||
firstFun(42) eq 43
|
||||
secondFun("xyz") eq "xyz!"
|
||||
thirdFun() eq "Hi!"
|
||||
fun fifth() = { "Hi!" }
|
||||
|
||||
fun main() {
|
||||
val funRef1: (Int) -> Int = first()
|
||||
val funRef2: (String) -> String = second()
|
||||
val funRef3: () -> String = third()
|
||||
val funRef4: () -> String = fourth()
|
||||
val funRef5: () -> String = fifth()
|
||||
|
||||
funRef1(42) eq 43
|
||||
funRef2("xyz") eq "xyz!"
|
||||
funRef3() eq "Hi!"
|
||||
funRef4() eq "Hi!"
|
||||
funRef5() eq "Hi!"
|
||||
|
||||
first()(42) eq 43
|
||||
second()("xyz") eq "xyz!"
|
||||
third()() eq "Hi!"
|
||||
fourth()() eq "Hi!"
|
||||
fifth()() eq "Hi!"
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
// LocalFunctions/Task1.kt
|
||||
package localFunctionsExercise1
|
||||
import atomictest.eq
|
||||
|
||||
fun f(): Int {
|
||||
fun g(): Int {
|
||||
|
@ -10,5 +11,5 @@ fun f(): Int {
|
|||
}
|
||||
|
||||
fun main() {
|
||||
println(f())
|
||||
f() eq 47
|
||||
}
|
|
@ -3,7 +3,7 @@ files:
|
|||
- name: src/Task.kt
|
||||
visible: true
|
||||
placeholders:
|
||||
- offset: 77
|
||||
- offset: 98
|
||||
length: 63
|
||||
placeholder_text: TODO()
|
||||
- name: test/Tests.kt
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
## Local Functions (#2)
|
||||
|
||||
The `createCounter()` function creates a pair of functions for managing the
|
||||
counter. Instead of creating a class, we manipulate the counter using only
|
||||
The `createCounter()` function creates a pair of functions for managing a
|
||||
`counter`. Instead of creating a class, we manipulate the `counter` using only
|
||||
functions.
|
||||
|
||||
In `createCounter()` define a local variable `counter`. Then define two local
|
||||
functions:
|
||||
|
||||
- `inc()`: increases the `counter` value by one
|
||||
+ `inc()`: increases the `counter` value by one
|
||||
|
||||
- `value()`: returns the value of `counter`
|
||||
+ `value()`: returns the value of `counter`
|
||||
|
||||
Finally, return a pair of function references to these local functions:
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
## Local Functions (#3)
|
||||
|
||||
Complete the implementation of the `createContainer()` function. It returns a
|
||||
pair of functions to control the `Int` container. The first function adds an
|
||||
`Int` element to the container, the second function removes an element from the
|
||||
container and returns it. If the container is empty, it returns `null`.
|
||||
`Pair` of functions to control the `Int` container. The first function puts an
|
||||
`Int` element into the container, the second function removes the element from
|
||||
the container and returns it. If the container is empty, the second function
|
||||
returns `null`.
|
||||
|
|
|
@ -1,11 +1,25 @@
|
|||
// Recursion/Task1.kt
|
||||
package recursionExercise1
|
||||
import atomictest.*
|
||||
|
||||
tailrec fun simulation(group: String, level: Int) {
|
||||
println("Simulation: $group Reality: $level")
|
||||
trace("Simulation: $group Reality: $level")
|
||||
if (level > 0) simulation(group, level - 1)
|
||||
}
|
||||
|
||||
fun main() {
|
||||
// simulation("FOO", 10)
|
||||
simulation("FOO", 10)
|
||||
trace eq """
|
||||
Simulation: FOO Reality: 10
|
||||
Simulation: FOO Reality: 9
|
||||
Simulation: FOO Reality: 8
|
||||
Simulation: FOO Reality: 7
|
||||
Simulation: FOO Reality: 6
|
||||
Simulation: FOO Reality: 5
|
||||
Simulation: FOO Reality: 4
|
||||
Simulation: FOO Reality: 3
|
||||
Simulation: FOO Reality: 2
|
||||
Simulation: FOO Reality: 1
|
||||
Simulation: FOO Reality: 0
|
||||
"""
|
||||
}
|
|
@ -3,8 +3,8 @@ files:
|
|||
- name: src/Task.kt
|
||||
visible: true
|
||||
placeholders:
|
||||
- offset: 50
|
||||
length: 147
|
||||
placeholder_text: tailrec fun simulation() { TODO() }
|
||||
- offset: 124
|
||||
length: 89
|
||||
placeholder_text: TODO()
|
||||
- name: test/Tests.kt
|
||||
visible: false
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
## Recursion (#1)
|
||||
|
||||
Write a tail recursive function called `simulation()` that takes a `String`
|
||||
called `group` and an `Int` called `level`. It displays `"Simulation: $group
|
||||
Reality: level"`, then calls itself with `level - 1` as long as `level` is
|
||||
greater than zero.
|
||||
called `group` and an `Int` called `level`. It traces `"Simulation: $group
|
||||
Reality: $level"`, then calls itself with `level - 1` as long as `level` is
|
||||
greater than zero. The code in `main()` tests your solution.
|
||||
|
|
|
@ -5,13 +5,15 @@ import org.junit.Test
|
|||
import org.junit.runners.MethodSorters
|
||||
import util.TIMEOUT
|
||||
import util.checkParametersOfTopLevelFunction
|
||||
import util.runAndCheckSystemOutput
|
||||
import util.runAndCheckTraceOutput
|
||||
|
||||
|
||||
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
||||
class TestRecursionExercise1 {
|
||||
private fun expectedOutput(group: String, n: Int) = buildString {
|
||||
@OptIn(ExperimentalStdlibApi::class)
|
||||
private fun expectedOutput(group: String, n: Int) = buildList {
|
||||
(n downTo 0).forEach {
|
||||
appendLine("Simulation: $group Reality: $it")
|
||||
add("Simulation: $group Reality: $it")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -26,7 +28,7 @@ class TestRecursionExercise1 {
|
|||
val simulationFunction = ::simulation
|
||||
checkParametersOfTopLevelFunction(simulationFunction, listOf("group" to "kotlin.String", "level" to "kotlin.Int"))
|
||||
|
||||
runAndCheckSystemOutput("Wrong result for 'simulation(\"$group\", $level)'",
|
||||
runAndCheckTraceOutput("Wrong result for 'simulation(\"$group\", $level)'",
|
||||
expectedOutput(group, level)) {
|
||||
simulationFunction.call(group, level)
|
||||
}
|
||||
|
|
|
@ -15,11 +15,11 @@ fun addConnection(first: City, second: City) {
|
|||
}
|
||||
|
||||
fun City.allReachableRecursive(): Set<City> {
|
||||
// stores all the cities reachable from the the given city:
|
||||
// Stores all cities reachable from the given city:
|
||||
val connections = mutableSetOf<City>()
|
||||
|
||||
// add all connections reachable
|
||||
// from 'current' city to 'connections' set
|
||||
// Add all connections reachable
|
||||
// from 'current' city to 'connections' Set
|
||||
fun addConnectionsFrom(current: City) {
|
||||
if (current in connections) return
|
||||
connections += current
|
||||
|
@ -34,16 +34,16 @@ fun City.allReachableRecursive(): Set<City> {
|
|||
}
|
||||
|
||||
fun City.allReachableIterative(): Set<City> {
|
||||
// stores all the cities reachable from the given city
|
||||
// Stores all cities reachable from the given city
|
||||
val connections = mutableSetOf<City>()
|
||||
// stores all the cities which direct connections are to be analyzed
|
||||
// Stores all cities for which direct connections are to be analyzed
|
||||
val toBeAnalyzed = mutableSetOf(this)
|
||||
|
||||
// for each 'current' city from 'toBeAnalyzed' set:
|
||||
// unmark it (remove from 'to be analyzed' set)
|
||||
// if it's already in 'connections', do nothing
|
||||
// add it to 'connections'
|
||||
// mark all its connections as 'to be analyzed'
|
||||
// For each 'current' city from 'toBeAnalyzed' set:
|
||||
// - Unmark it (remove from 'to be analyzed' set)
|
||||
// - If it's already in 'connections', do nothing
|
||||
// - Add it to 'connections'
|
||||
// - Mark all its connections as 'to be analyzed'
|
||||
while (toBeAnalyzed.isNotEmpty()) {
|
||||
val current = toBeAnalyzed.first()
|
||||
|
||||
|
|
|
@ -3,10 +3,10 @@ files:
|
|||
- name: src/Task.kt
|
||||
visible: true
|
||||
placeholders:
|
||||
- offset: 627
|
||||
- offset: 619
|
||||
length: 131
|
||||
placeholder_text: TODO()
|
||||
- offset: 1346
|
||||
- offset: 1342
|
||||
length: 204
|
||||
placeholder_text: TODO()
|
||||
- name: test/Tests.kt
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
## Recursion (#4)
|
||||
|
||||
The starter code provides a class `City`. Implement an extension function
|
||||
`City.allReachable()` that builds a set of all cities reachable from the
|
||||
current `City`. Implement it in two ways: recursive and iterative.
|
||||
`City.allReachable()` that builds a set of all cities reachable from the current
|
||||
`City`. Implement it both recursively and iteratively.
|
||||
|
||||
The direct connections for each `City` are stored in its `connections`
|
||||
property. `allReachable()` should return all the cities reachable from the
|
||||
given city via other cities. The city is reachable from itself, so it should be
|
||||
also present in the resulting set.
|
||||
The direct connections for each `City` are stored in its `connections` property.
|
||||
`allReachable()` should return all the cities reachable from the given city via
|
||||
other cities. The city is reachable from itself, so it should be also present in
|
||||
the resulting set.
|
||||
|
||||
For example, consider the following connections graph:
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Sequences/DefineTakeIf.kt
|
||||
package usingsequences
|
||||
package sequences
|
||||
import atomictest.eq
|
||||
|
||||
fun <T> T.takeIf(
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Sequences/EagerVsLazyEvaluation.kt
|
||||
package usingsequences
|
||||
package sequences
|
||||
import atomictest.*
|
||||
|
||||
fun Int.isEven(): Boolean {
|
||||
|
@ -19,18 +19,20 @@ fun Int.lessThanTen(): Boolean {
|
|||
|
||||
fun main() {
|
||||
val list = listOf(1, 2, 3, 4)
|
||||
|
||||
trace(">>> List:")
|
||||
trace(list
|
||||
.filter(Int::isEven)
|
||||
.map(Int::square)
|
||||
.any(Int::lessThanTen))
|
||||
|
||||
trace(
|
||||
list
|
||||
.filter(Int::isEven)
|
||||
.map(Int::square)
|
||||
.any(Int::lessThanTen)
|
||||
)
|
||||
trace(">>> Sequence:")
|
||||
trace(list.asSequence()
|
||||
.filter(Int::isEven)
|
||||
.map(Int::square)
|
||||
.any(Int::lessThanTen))
|
||||
trace(
|
||||
list.asSequence()
|
||||
.filter(Int::isEven)
|
||||
.map(Int::square)
|
||||
.any(Int::lessThanTen)
|
||||
)
|
||||
trace eq """
|
||||
>>> List:
|
||||
1.isEven()
|
||||
|
|
|
@ -1,16 +1,10 @@
|
|||
// Sequences/GenerateSequence1.kt
|
||||
import atomictest.*
|
||||
import atomictest.eq
|
||||
|
||||
fun main() {
|
||||
val inputs = mutableListOf(
|
||||
"first", "second", "third", "XXX", "4th")
|
||||
val items = generateSequence {
|
||||
val input = inputs.removeAt(0)
|
||||
if (input != "XXX") input else null
|
||||
}
|
||||
items.toList() eq "[first, second, third]"
|
||||
capture {
|
||||
items.toList()
|
||||
} eq "IllegalStateException: This " +
|
||||
"sequence can be consumed only once."
|
||||
val naturalNumbers =
|
||||
generateSequence(1) { it + 1 }
|
||||
naturalNumbers.take(3).toList() eq
|
||||
listOf(1, 2, 3)
|
||||
naturalNumbers.take(10).sum() eq 55
|
||||
}
|
|
@ -1,11 +1,16 @@
|
|||
// Sequences/GenerateSequence2.kt
|
||||
import atomictest.eq
|
||||
import atomictest.*
|
||||
|
||||
fun main() {
|
||||
val inputs = mutableListOf(
|
||||
"first", "second", "third", "XXX", "4th")
|
||||
val lines = generateSequence {
|
||||
inputs.removeAt(0).takeIf { it != "XXX" }
|
||||
val items = mutableListOf(
|
||||
"first", "second", "third", "XXX", "4th"
|
||||
)
|
||||
val seq = generateSequence {
|
||||
items.removeAt(0).takeIf { it != "XXX" }
|
||||
}
|
||||
lines.toList() eq "[first, second, third]"
|
||||
seq.toList() eq "[first, second, third]"
|
||||
capture {
|
||||
seq.toList()
|
||||
} eq "IllegalStateException: This " +
|
||||
"sequence can be consumed only once."
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
// Sequences/NoComputationYet.kt
|
||||
import atomictest.eq
|
||||
import usingsequences.*
|
||||
import sequences.*
|
||||
|
||||
fun main() {
|
||||
val r = listOf(1, 2, 3, 4)
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
// Sequences/NumberSequence1.kt
|
||||
import atomictest.eq
|
||||
|
||||
fun main() {
|
||||
val naturalNumbers =
|
||||
generateSequence(1) { it + 1 }
|
||||
naturalNumbers.take(3).toList() eq
|
||||
listOf(1, 2, 3)
|
||||
naturalNumbers.take(10).sum() eq 55
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
// Sequences/TerminalOperations.kt
|
||||
import usingsequences.*
|
||||
import sequences.*
|
||||
import atomictest.*
|
||||
|
||||
fun main() {
|
||||
|
|
|
@ -8,8 +8,6 @@ files:
|
|||
visible: true
|
||||
- name: src/TerminalOperations.kt
|
||||
visible: true
|
||||
- name: src/NumberSequence1.kt
|
||||
visible: true
|
||||
- name: src/GenerateSequence1.kt
|
||||
visible: true
|
||||
- name: src/GenerateSequence2.kt
|
||||
|
|
|
@ -3,5 +3,5 @@
|
|||
Implement the `School` extension functions `studentInstructors()` and
|
||||
`studentsOf()`. The `studentInstructors()` parameter is a `Student`, and it
|
||||
finds all instructors that have classes with this student. `studentsOf()` takes
|
||||
`Instructor` as a parameter and finds all students that attend classes with
|
||||
this instructor.
|
||||
`Instructor` as a parameter and finds all students that attend classes with this
|
||||
instructor.
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
## Sequences (#3)
|
||||
|
||||
Implement the `School` extension function `averageInstructorRating()` that
|
||||
takes `Instructor` as a parameter and calculates the average rating that the
|
||||
Implement the `School` extension function `averageInstructorRating()` that takes
|
||||
`Instructor` as a parameter and calculates the average rating that the
|
||||
instructor was given by all the students that attended his or her classes. If a
|
||||
student attended several lessons by that instructor, the ratings for individual
|
||||
lessons should be treated separately.
|
||||
|
|
|
@ -10,7 +10,7 @@ fun main() {
|
|||
for (i in ints) { // [2]
|
||||
result += "$i "
|
||||
}
|
||||
result eq "99 3 5 7 11 13 "
|
||||
result eq "99 3 5 7 11 13"
|
||||
|
||||
// "Indexing" into the List:
|
||||
ints[4] eq 11 // [3]
|
||||
|
|
|
@ -20,11 +20,11 @@ fun main() {
|
|||
for (entry in constants) { // [2]
|
||||
s += "${entry.key}=${entry.value}, "
|
||||
}
|
||||
s eq "Pi=3.141, e=2.718, phi=1.618, "
|
||||
s eq "Pi=3.141, e=2.718, phi=1.618,"
|
||||
|
||||
s = ""
|
||||
// Unpack during iteration:
|
||||
for ((key, value) in constants) // [3]
|
||||
s += "$key=$value, "
|
||||
s eq "Pi=3.141, e=2.718, phi=1.618, "
|
||||
s eq "Pi=3.141, e=2.718, phi=1.618,"
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
## Complex Constructors (#1)
|
||||
|
||||
Modify `Alien` to use the "verbose" syntax: make `name` a constructor parameter
|
||||
rather than a property, add the `val` property `myName` and assign `name` value
|
||||
to the property `myName` inside the `init` section.
|
||||
Create an `Alien` class with `name: String` as a constructor parameter. Add a
|
||||
`val` property `myName` and assign `name` to the property `myName` inside the
|
||||
`init` section.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
## Complex Constructors (#2)
|
||||
|
||||
Create a class called `SumChars` that takes `text: String` as a constructor
|
||||
argument. Add an un-initialized property `val sum: Int`. Inside `init`,
|
||||
define a local function `calc()` that sums up the integer values of each
|
||||
of the characters in `text`. Call `calc()` and assign the result to `sum`.
|
||||
parameter. Add an un-initialized property `val sum: Int`. Inside `init`, define
|
||||
a local function `calc()` that sums up the integer values of each of the
|
||||
characters in `text`. Call `calc()` and assign the result to `sum`.
|
||||
|
|
|
@ -8,7 +8,6 @@ interface Computer {
|
|||
|
||||
class Cloud(n: Int): Computer {
|
||||
val list: List<Node> = List(n) { Node(it) }
|
||||
|
||||
override fun calculateAnswer(): Int {
|
||||
return list.sumBy { it.result }
|
||||
}
|
||||
|
@ -19,5 +18,5 @@ data class Node(val result: Int): Computer {
|
|||
}
|
||||
|
||||
fun main() {
|
||||
// Cloud(10).calculateAnswer() eq 45
|
||||
Cloud(10).calculateAnswer() eq 45
|
||||
}
|
|
@ -4,7 +4,10 @@ files:
|
|||
visible: true
|
||||
placeholders:
|
||||
- offset: 126
|
||||
length: 250
|
||||
length: 249
|
||||
placeholder_text: class Cloud
|
||||
- offset: 392
|
||||
length: 33
|
||||
placeholder_text: // Cloud(10).calculateAnswer() eq 45
|
||||
- name: test/Tests.kt
|
||||
visible: false
|
||||
|
|
|
@ -5,6 +5,6 @@ The `data class Node(result: Int)` should also implement `Computer`, and should
|
|||
implement `calculateAnswer()` so it simply returns `result`.
|
||||
|
||||
Write the `Cloud` constructor to take an argument `n` indicating the number of
|
||||
`Node`s in the cloud. Count up to `n` and place each count as the `result`
|
||||
value of the `Node` you are currently creating. Implement `Cloud`s
|
||||
`calculateAnswer()` to return the sum of the `result`s in all the `Node`s.
|
||||
`Node`s in the cloud. Count up to `n` and place each count as the `result` value
|
||||
of the `Node` you are currently creating. Implement `Cloud`s `calculateAnswer()`
|
||||
to return the sum of the `result`s in all the `Node`s.
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
// Interfaces/Task2.kt
|
||||
package interfacesExercise2
|
||||
import atomictest.eq
|
||||
|
||||
interface Pet {
|
||||
fun speak(): String
|
||||
|
@ -19,7 +20,5 @@ class Hamster: Pet {
|
|||
|
||||
fun main() {
|
||||
val pets = listOf(Dog(), Cat(), Hamster())
|
||||
for (pet in pets) {
|
||||
println(pet.speak())
|
||||
}
|
||||
pets.map { it.speak() } eq "[Bark!, Meow!, Squeak!]"
|
||||
}
|
|
@ -3,20 +3,20 @@ files:
|
|||
- name: src/Task.kt
|
||||
visible: true
|
||||
placeholders:
|
||||
- offset: 70
|
||||
- offset: 91
|
||||
length: 19
|
||||
placeholder_text: // TODO
|
||||
- offset: 112
|
||||
- offset: 133
|
||||
length: 30
|
||||
placeholder_text: // TODO
|
||||
- offset: 165
|
||||
- offset: 186
|
||||
length: 30
|
||||
placeholder_text: // TODO
|
||||
- offset: 222
|
||||
- offset: 243
|
||||
length: 32
|
||||
placeholder_text: // TODO
|
||||
- offset: 273
|
||||
length: 93
|
||||
- offset: 294
|
||||
length: 97
|
||||
placeholder_text: // TODO
|
||||
- name: test/Tests.kt
|
||||
visible: false
|
||||
|
|
|
@ -2,6 +2,6 @@
|
|||
|
||||
Define a `Pet` interface with a `speak()` function that returns a `String`.
|
||||
Implement three different `Pet`s: `Dog` which produces `"Bark!"`, `Cat` which
|
||||
produces `"Meow!"` and `Hamster` which produces `"Squeak!"`. In `main()`, create a
|
||||
`List<Pet>` containing all three types of `Pet`. Iterate through the `List` and
|
||||
print the result of `speak()` for each `Pet`.
|
||||
produces `"Meow!"` and `Hamster` which produces `"Squeak!"`. In `main()`, create
|
||||
a `List<Pet>` containing all three types of `Pet`. Use `map()` to produce result
|
||||
of `speak()` for each `Pet`.
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
// Interfaces/Task3.kt
|
||||
package interfacesExercise3
|
||||
import atomictest.eq
|
||||
|
||||
interface Pet {
|
||||
val sound: String
|
||||
|
@ -19,7 +20,5 @@ class Hamster: Pet {
|
|||
|
||||
fun main() {
|
||||
val pets = listOf(Dog(), Cat(), Hamster())
|
||||
for (pet in pets) {
|
||||
println(pet.sound)
|
||||
}
|
||||
pets.map { it.sound } eq "[Bark!, Meow!, Squeak!]"
|
||||
}
|
|
@ -3,20 +3,20 @@ files:
|
|||
- name: src/Task.kt
|
||||
visible: true
|
||||
placeholders:
|
||||
- offset: 70
|
||||
- offset: 91
|
||||
length: 17
|
||||
placeholder_text: // TODO
|
||||
- offset: 110
|
||||
- offset: 131
|
||||
length: 34
|
||||
placeholder_text: // TODO
|
||||
- offset: 167
|
||||
- offset: 188
|
||||
length: 34
|
||||
placeholder_text: // TODO
|
||||
- offset: 228
|
||||
- offset: 249
|
||||
length: 36
|
||||
placeholder_text: // TODO
|
||||
- offset: 283
|
||||
length: 91
|
||||
- offset: 304
|
||||
length: 95
|
||||
placeholder_text: // TODO
|
||||
- name: test/Tests.kt
|
||||
visible: false
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
## Interfaces (#3)
|
||||
|
||||
Define a property `sound` of type `String` inside the `Pet` interface and
|
||||
Define a property `sound` of type `String` inside a `Pet` interface and
|
||||
implement it inside classes to return "Bark!" for `Dog`, "Meow!" for `Cat`, and
|
||||
"Squeak!" for `Hamster`. In `main()`, as in the previous task, create a
|
||||
`List<Pet>` containing all three types of `Pet`. Iterate through the `List` and
|
||||
print the value of `sound` for each `Pet`.
|
||||
`List<Pet>` containing all three types of `Pet`. Use `map()` to
|
||||
produce the value of `sound` for each `Pet`.
|
||||
|
|
|
@ -36,7 +36,7 @@ class House : Cleanable("House") {
|
|||
}
|
||||
|
||||
fun main() {
|
||||
House().clean().trim() eq """
|
||||
House().clean() eq """
|
||||
(((Shelf clean Shelf clean) Closet clean
|
||||
(Toilet clean Sink clean) Bathroom clean
|
||||
) Master Bedroom clean
|
||||
|
|
|
@ -10,20 +10,20 @@ enum class Material {
|
|||
class GardenItem(val name: String) {
|
||||
var material: Material = Plastic
|
||||
constructor(
|
||||
name: String, material: Material // [1]
|
||||
) : this(name) { // [2]
|
||||
this.material = material // [3]
|
||||
name: String, material: Material // [1]
|
||||
) : this(name) { // [2]
|
||||
this.material = material // [3]
|
||||
}
|
||||
constructor(
|
||||
material: Material
|
||||
) : this("Strange Thing", material) // [4]
|
||||
) : this("Strange Thing", material) // [4]
|
||||
override fun toString() = "$material $name"
|
||||
}
|
||||
|
||||
fun main() {
|
||||
GardenItem("Elf").material eq Plastic
|
||||
GardenItem("Snowman").name eq "Snowman"
|
||||
GardenItem("Gazing Ball", Metal) eq // [5]
|
||||
GardenItem("Gazing Ball", Metal) eq // [5]
|
||||
"Metal Gazing Ball"
|
||||
GardenItem(material = Ceramic) eq
|
||||
"Ceramic Strange Thing"
|
||||
|
|
|
@ -3,12 +3,12 @@ package secondaryConstructorsExercise1
|
|||
import atomictest.eq
|
||||
|
||||
data class Flower1(val type: String) {
|
||||
constructor(): this("Daisy")
|
||||
constructor(): this("Daisy")
|
||||
}
|
||||
|
||||
data class Flower2(val type: String = "Daisy")
|
||||
|
||||
fun main() {
|
||||
Flower1().type eq "Daisy"
|
||||
Flower2().type eq "Daisy"
|
||||
Flower1().type eq "Daisy"
|
||||
Flower2().type eq "Daisy"
|
||||
}
|
|
@ -3,14 +3,14 @@ files:
|
|||
- name: src/Task.kt
|
||||
visible: true
|
||||
placeholders:
|
||||
- offset: 138
|
||||
- offset: 136
|
||||
length: 28
|
||||
placeholder_text: // TODO add constructor
|
||||
- offset: 189
|
||||
- offset: 187
|
||||
length: 26
|
||||
placeholder_text: 'val type: String'
|
||||
- offset: 231
|
||||
length: 59
|
||||
- offset: 229
|
||||
length: 55
|
||||
placeholder_text: |-
|
||||
// Flower1().type eq "Daisy"
|
||||
// Flower2().type eq "Daisy"
|
||||
|
|
|
@ -5,5 +5,5 @@ only one property `type` of the type `String`. Add a secondary constructor to
|
|||
the class `Flower1` that takes no arguments and initializes `type` to `Daisy`.
|
||||
Add a default value `Daisy` to the constructor argument of the `Flower2` class.
|
||||
|
||||
Uncomment the code in `main()` to make sure you can now create both classes
|
||||
without constructor arguments.
|
||||
The code in `main()` tests that you can now create both classes without
|
||||
constructor arguments.
|
||||
|
|
|
@ -3,13 +3,13 @@ package secondaryConstructorsExercise2
|
|||
import atomictest.eq
|
||||
|
||||
data class SpaceShip(val name: String) {
|
||||
constructor(shipClass: String, model: Int)
|
||||
: this("$shipClass-$model")
|
||||
constructor(shipClass: String, model: Int)
|
||||
: this("$shipClass-$model")
|
||||
}
|
||||
|
||||
fun main() {
|
||||
SpaceShip("SuperHighSpeedShip") eq
|
||||
"SpaceShip(name=SuperHighSpeedShip)"
|
||||
SpaceShip("MClass", 29321) eq
|
||||
"SpaceShip(name=MClass-29321)"
|
||||
SpaceShip("SuperHighSpeedShip") eq
|
||||
"SpaceShip(name=SuperHighSpeedShip)"
|
||||
SpaceShip("MClass", 29321) eq
|
||||
"SpaceShip(name=MClass-29321)"
|
||||
}
|
|
@ -3,11 +3,11 @@ files:
|
|||
- name: src/Task.kt
|
||||
visible: true
|
||||
placeholders:
|
||||
- offset: 140
|
||||
length: 76
|
||||
- offset: 138
|
||||
length: 74
|
||||
placeholder_text: // TODO add secondary constructor
|
||||
- offset: 315
|
||||
length: 70
|
||||
- offset: 307
|
||||
length: 66
|
||||
placeholder_text: |-
|
||||
// SpaceShip("MClass", 29321) eq
|
||||
// "SpaceShip(name=MClass-29321)"
|
||||
|
|
|
@ -2,5 +2,5 @@
|
|||
|
||||
The starter code contains a `SpaceShip` class with a property `name: String`.
|
||||
Add a secondary constructor that takes two parameters `shipClass` (a `String`)
|
||||
and `model` (an `Int`) and builds a `SpaceShip` object taking
|
||||
`"$shipClass-$model"` as a name.
|
||||
and `model` (an `Int`) and builds a `SpaceShip` object with the name
|
||||
`"$shipClass-$model"`.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
## Secondary Constructors (#3)
|
||||
|
||||
Replace all the constructors in the `GardenItem` class with a single primary
|
||||
Replace all constructors in the `GardenItem` class with a single primary
|
||||
constructor using default arguments.
|
||||
|
|
|
@ -16,5 +16,5 @@ fun main() {
|
|||
team.captain = "Adam"
|
||||
team.captain = "Amanda"
|
||||
team.msg eq "captain <0> to Adam " +
|
||||
"captain Adam to Amanda "
|
||||
"captain Adam to Amanda"
|
||||
}
|
|
@ -7,7 +7,7 @@ private val logger = Logger("AtomicLog.txt")
|
|||
|
||||
fun main() {
|
||||
logger.report("Hello, Atomic Log!")
|
||||
logger.logFile.readText().trim() eq
|
||||
logger.logFile.readText() eq
|
||||
"""Trace: Hello, Atomic Log!
|
||||
Debug: Hello, Atomic Log!
|
||||
Info: Hello, Atomic Log!
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// LoopingAndRanges/Repeat.kt
|
||||
// LoopingAndRanges/RepeatHi.kt
|
||||
|
||||
fun main() {
|
||||
repeat(2) {
|
|
@ -18,5 +18,5 @@ files:
|
|||
visible: true
|
||||
- name: src/HasChar.kt
|
||||
visible: true
|
||||
- name: src/Repeat.kt
|
||||
- name: src/RepeatHi.kt
|
||||
visible: true
|
||||
|
|
|
@ -7,7 +7,7 @@ fun main() {
|
|||
for ((key, value) in map) {
|
||||
result += "$key = $value, "
|
||||
}
|
||||
result eq "1 = one, 2 = two, "
|
||||
result eq "1 = one, 2 = two,"
|
||||
|
||||
result = ""
|
||||
val listOfPairs =
|
||||
|
@ -15,5 +15,5 @@ fun main() {
|
|||
for ((i, s) in listOfPairs) {
|
||||
result += "($i, $s), "
|
||||
}
|
||||
result eq "(1, one), (2, two), "
|
||||
result eq "(1, one), (2, two),"
|
||||
}
|
|
@ -4,7 +4,3 @@ Create a class `Rocket` containing a member function `ignition()` that returns
|
|||
"Liftoff!". Create a function `launch()` that has a nullable `Rocket` parameter.
|
||||
Use a non-null assertion to call `ignition` on `rocket` and return the result.
|
||||
In `main()`, ensure that `launch()` throws an exception if you pass it a `null`.
|
||||
|
||||
<sub> This task doesn't contain automatic tests,
|
||||
so it's always marked as "Correct" when you run "Check".
|
||||
Please compare your solution with the one provided! </sub>
|
||||
|
|
|
@ -5,23 +5,18 @@ import org.junit.Test
|
|||
import util.*
|
||||
import java.lang.reflect.InvocationTargetException
|
||||
import kotlin.reflect.full.createInstance
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
class TestNonNullAssertionsExercise1 {
|
||||
@Test fun testRocket() {
|
||||
unimplementedTest()
|
||||
/*
|
||||
val rocketClass = Rocket::class
|
||||
val rocketInstance = rocketClass.createInstance()
|
||||
val ignitionFunc = loadMemberFunction(rocketClass, "ignition")
|
||||
checkParametersOfMemberFunction(ignitionFunc, listOf())
|
||||
runAndCheckSystemOutput("Wrong output after calling 'rocket.ignition()'", "Liftoff!") {
|
||||
ignitionFunc.call(rocketInstance)
|
||||
}
|
||||
assertEquals("Liftoff!", ignitionFunc.call(rocketInstance), "Wrong result after calling 'rocket.ignition()'")
|
||||
val launchFunc = ::launch
|
||||
checkParametersOfTopLevelFunction(launchFunc, listOf("rocket" to "nonNullAssertionsExercise1.Rocket?"))
|
||||
runAndCheckSystemOutput("Wrong output after calling 'launch(rocket)'", "Liftoff!") {
|
||||
launchFunc.call(rocketInstance)
|
||||
}
|
||||
assertEquals("Liftoff!", launchFunc.call(rocketInstance), "Wrong result after calling 'launch(rocket)'")
|
||||
try {
|
||||
launchFunc.call(null)
|
||||
throw AssertionError("Wrong result after calling 'launch(null)', expected NullPointerException")
|
||||
|
@ -29,6 +24,5 @@ class TestNonNullAssertionsExercise1 {
|
|||
Assert.assertEquals("Wrong result after calling 'launch(null)', expected NullPointerException",
|
||||
e.targetException::class.simpleName, "NullPointerException")
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
|
@ -57,6 +57,13 @@ fun checkSystemOutput(message: String, expected: String, actual: String) {
|
|||
Assert.assertEquals(message, expected.trim().normalizeLineSeparators(), actual.trim().normalizeLineSeparators())
|
||||
}
|
||||
|
||||
inline fun runAndCheckTraceOutput(message: String, expectedOutput: List<String>, action: () -> Unit) {
|
||||
resetTraceContent()
|
||||
action()
|
||||
val traceContent = loadTraceContent()
|
||||
assertEquals(expectedOutput, traceContent, message)
|
||||
}
|
||||
|
||||
fun checkInputOutput(message: String, expectedInputAndOutput: String, action: () -> Unit) {
|
||||
val (inputLines, outputLines) = expectedInputAndOutput
|
||||
.lines()
|
||||
|
|
|
@ -231,11 +231,6 @@ public class TestAllExamples extends AbstractTestExamples {
|
|||
testExample("Programming Basics/Looping & Ranges/Examples/src/ForWithRanges.kt", ForWithRangesKt::main);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRepeat() {
|
||||
testExample("Programming Basics/Looping & Ranges/Examples/src/Repeat.kt", RepeatKt::main);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSumUsingRange() {
|
||||
testExample("Programming Basics/Looping & Ranges/Examples/src/SumUsingRange.kt", SumUsingRangeKt::main);
|
||||
|
@ -246,6 +241,11 @@ public class TestAllExamples extends AbstractTestExamples {
|
|||
testExample("Programming Basics/Looping & Ranges/Examples/src/RepeatThreeTimes.kt", RepeatThreeTimesKt::main);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRepeatHi() {
|
||||
testExample("Programming Basics/Looping & Ranges/Examples/src/RepeatHi.kt", RepeatHiKt::main);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddingIntToChar() {
|
||||
testExample("Programming Basics/Looping & Ranges/Examples/src/AddingIntToChar.kt", AddingIntToCharKt::main);
|
||||
|
@ -1397,7 +1397,7 @@ public class TestAllExamples extends AbstractTestExamples {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testRepeat1() {
|
||||
public void testRepeat() {
|
||||
testExample("Functional Programming/Higher-Order Functions/Examples/src/Repeat.kt", higherorderfunctions.RepeatKt::main);
|
||||
}
|
||||
|
||||
|
@ -1503,7 +1503,7 @@ public class TestAllExamples extends AbstractTestExamples {
|
|||
|
||||
@Test
|
||||
public void testDefineTakeIf() {
|
||||
testExample("Functional Programming/Sequences/Examples/src/DefineTakeIf.kt", usingsequences.DefineTakeIfKt::main);
|
||||
testExample("Functional Programming/Sequences/Examples/src/DefineTakeIf.kt", sequences.DefineTakeIfKt::main);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -1513,7 +1513,7 @@ public class TestAllExamples extends AbstractTestExamples {
|
|||
|
||||
@Test
|
||||
public void testEagerVsLazyEvaluation() {
|
||||
testExample("Functional Programming/Sequences/Examples/src/EagerVsLazyEvaluation.kt", usingsequences.EagerVsLazyEvaluationKt::main);
|
||||
testExample("Functional Programming/Sequences/Examples/src/EagerVsLazyEvaluation.kt", sequences.EagerVsLazyEvaluationKt::main);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -1526,11 +1526,6 @@ public class TestAllExamples extends AbstractTestExamples {
|
|||
testExample("Functional Programming/Sequences/Examples/src/GenerateSequence2.kt", GenerateSequence2Kt::main);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNumberSequence1() {
|
||||
testExample("Functional Programming/Sequences/Examples/src/NumberSequence1.kt", NumberSequence1Kt::main);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoComputationYet() {
|
||||
testExample("Functional Programming/Sequences/Examples/src/NoComputationYet.kt", NoComputationYetKt::main);
|
||||
|
@ -1602,13 +1597,13 @@ public class TestAllExamples extends AbstractTestExamples {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testFoldAndReduce() {
|
||||
testExample("Functional Programming/Folding Lists/Examples/src/FoldAndReduce.kt", FoldAndReduceKt::main);
|
||||
public void testFoldVsForLoop() {
|
||||
testExample("Functional Programming/Folding Lists/Examples/src/FoldVsForLoop.kt", FoldVsForLoopKt::main);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFoldVsForLoop() {
|
||||
testExample("Functional Programming/Folding Lists/Examples/src/FoldVsForLoop.kt", FoldVsForLoopKt::main);
|
||||
public void testReduceAndReduceRight() {
|
||||
testExample("Functional Programming/Folding Lists/Examples/src/ReduceAndReduceRight.kt", ReduceAndReduceRightKt::main);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
Loading…
Reference in New Issue