1
1
Fork 0

Regenerated samples

This commit is contained in:
Svetlana Isakova 2020-12-04 01:01:03 +01:00
parent 7544ee333c
commit f18e5da6d7
64 changed files with 249 additions and 243 deletions

View File

@ -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
}
}

View File

@ -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)
}
}

View File

@ -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.

View File

@ -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`.

View File

@ -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
}

View File

@ -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)
}

View File

@ -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"
}

View File

@ -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

View File

@ -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
}

View File

@ -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.

View File

@ -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
"""

View File

@ -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!"
}

View File

@ -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
}

View File

@ -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

View File

@ -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:

View File

@ -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`.

View File

@ -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
"""
}

View File

@ -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

View File

@ -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.

View File

@ -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)
}

View File

@ -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()

View File

@ -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

View File

@ -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:

View File

@ -1,5 +1,5 @@
// Sequences/DefineTakeIf.kt
package usingsequences
package sequences
import atomictest.eq
fun <T> T.takeIf(

View File

@ -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()

View File

@ -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
}

View File

@ -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."
}

View File

@ -1,6 +1,6 @@
// Sequences/NoComputationYet.kt
import atomictest.eq
import usingsequences.*
import sequences.*
fun main() {
val r = listOf(1, 2, 3, 4)

View File

@ -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
}

View File

@ -1,5 +1,5 @@
// Sequences/TerminalOperations.kt
import usingsequences.*
import sequences.*
import atomictest.*
fun main() {

View File

@ -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

View File

@ -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.

View File

@ -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.

View File

@ -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]

View File

@ -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,"
}

View File

@ -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.

View File

@ -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`.

View File

@ -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
}

View File

@ -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

View File

@ -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.

View File

@ -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!]"
}

View File

@ -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

View File

@ -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`.

View File

@ -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!]"
}

View File

@ -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

View File

@ -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`.

View File

@ -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

View File

@ -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"

View File

@ -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"
}

View File

@ -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"

View File

@ -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.

View File

@ -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)"
}

View File

@ -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)"

View File

@ -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"`.

View File

@ -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.

View File

@ -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"
}

View File

@ -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!

View File

@ -1,4 +1,4 @@
// LoopingAndRanges/Repeat.kt
// LoopingAndRanges/RepeatHi.kt
fun main() {
repeat(2) {

View File

@ -18,5 +18,5 @@ files:
visible: true
- name: src/HasChar.kt
visible: true
- name: src/Repeat.kt
- name: src/RepeatHi.kt
visible: true

View File

@ -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),"
}

View File

@ -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>

View File

@ -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")
}
*/
}
}

View File

@ -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()

View File

@ -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