Skip to content

Add solutions for exercise 6 #24

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 4 additions & 5 deletions src/main/kotlin/exercise6/task1/SimpleGenerics.kt
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ package exercise6.task1
/**
* A binary tree node that holds some value.
*/
private data class TreeNode(val value: Any) {
var left: TreeNode? = null
var right: TreeNode? = null
private data class TreeNode<T>(val value: T) {
var left: TreeNode<T>? = null
var right: TreeNode<T>? = null
}

/**
Expand All @@ -42,8 +42,7 @@ private fun printNodes(): String {

val decisionI = Decision("Do you choose a red or a blue pill?", "Red", "Blue")
val decisionTree = TreeNode(decisionI)
TODO("Uncomment code bellow and make the file compilable")
// return "${genealogyTree.value.name} ${decisionTree.value.answerLeft}"
return "${genealogyTree.value.name} ${decisionTree.value.answerLeft}"
}

fun main() {
Expand Down
9 changes: 4 additions & 5 deletions src/main/kotlin/exercise6/task2/UpperBoundConstraints.kt
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,8 @@ private data class SetIntersection(val size: Int): CostElement {
* nodes. This code is not yet compilable, but it will become compilable as soon as you add an upper bound to the generic
* type.
*/
private fun <T> calculateTreeCost(root: TreeNode<T>): Double {
TODO("Uncomment code bellow and make the file compilable")
// return root.value.cost +
// (root.left?.let { calculateTreeCost(it) } ?: 0.0) +
// (root.right?.let { calculateTreeCost(it) } ?: 0.0)
private fun <T : CostElement> calculateTreeCost(root: TreeNode<T>): Double {
return root.value.cost +
(root.left?.let { calculateTreeCost(it) } ?: 0.0) +
(root.right?.let { calculateTreeCost(it) } ?: 0.0)
}
11 changes: 5 additions & 6 deletions src/main/kotlin/exercise6/task3/UpperBoundConstraintPartTwo.kt
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ private data class SetIntersection<S>(val size: Int, val lowerBound: S?, val upp
* no intersection at all. If the intersection is likely to be not empty, it estimates the intersection size as the mean
* of the set sizes.
*/
private fun <T> estimateIntersectionSize(treeNode: TreeNode<SetIntersection<T>>): Int {
private fun <T : Comparable<T>> estimateIntersectionSize(treeNode: TreeNode<SetIntersection<T>>): Int {
val leftNode = treeNode.left ?: return treeNode.value.size
val rightNode = treeNode.right ?: return treeNode.value.size

Expand All @@ -60,9 +60,8 @@ private fun <T> estimateIntersectionSize(treeNode: TreeNode<SetIntersection<T>>)
return 0
}

TODO("Uncomment code bellow and make the file compilable")
// if (leftNode.value.upperBound < rightNode.value.lowerBound || leftNode.value.lowerBound > rightNode.value.upperBound) {
// return 0
// }
// return (leftNode.value.size + rightNode.value.size)/2
if (leftNode.value.upperBound < rightNode.value.lowerBound || leftNode.value.lowerBound > rightNode.value.upperBound) {
return 0
}
return (leftNode.value.size + rightNode.value.size)/2
}
51 changes: 24 additions & 27 deletions src/main/kotlin/exercise6/task4/UpperBoundConstraintPartThree.kt
Original file line number Diff line number Diff line change
Expand Up @@ -89,29 +89,27 @@ private data class SetIntersection<T: Comparable<T>>(
* no intersection at all. If the intersection is likely to be not empty, it estimates the intersection size as the mean
* of the set sizes.
*/
private fun <T, S> estimateIntersectionSize(treeNode: TreeNode<T>) : Int {
TODO("Uncomment code bellow and make the file compilable")
// val leftNode = treeNode.left ?: return treeNode.value.size
// val rightNode = treeNode.right ?: return treeNode.value.size
//
// if (leftNode.value.lowerBound == null || rightNode.value.lowerBound == null) {
// return 0
// }
// if (leftNode.value.upperBound == null || rightNode.value.upperBound == null) {
// return 0
// }
//
// if (leftNode.value.upperBound!! < rightNode.value.lowerBound!! || leftNode.value.lowerBound!! > rightNode.value.upperBound!!) {
// return 0
// }
// return (leftNode.value.size + rightNode.value.size)/2
private fun <T, S> estimateIntersectionSize(treeNode: TreeNode<T>) : Int where T: Range<S>, T: Measurable, S : Comparable<S>{
val leftNode = treeNode.left ?: return treeNode.value.size
val rightNode = treeNode.right ?: return treeNode.value.size

if (leftNode.value.lowerBound == null || rightNode.value.lowerBound == null) {
return 0
}
if (leftNode.value.upperBound == null || rightNode.value.upperBound == null) {
return 0
}

if (leftNode.value.upperBound!! < rightNode.value.lowerBound!! || leftNode.value.lowerBound!! > rightNode.value.upperBound!!) {
return 0
}
return (leftNode.value.size + rightNode.value.size)/2
}

private fun <T> printTree(treeNode: TreeNode<T>) {
TODO("Uncomment code bellow and make the file compilable")
// println("${treeNode.value} cost:${treeNode.value.cost}")
// treeNode.left?.let { printTree(it) }
// treeNode.right?.let { printTree(it) }
private fun <T : CostElement> printTree(treeNode: TreeNode<T>) {
println("${treeNode.value} cost:${treeNode.value.cost}")
treeNode.left?.let { printTree(it) }
treeNode.right?.let { printTree(it) }
}

/**
Expand Down Expand Up @@ -148,12 +146,11 @@ private fun run() {
it.left = leftNode
it.right = rightNode
}
TODO("Uncomment code bellow and make the file compilable")
// val intersectionSize = estimateIntersectionSize(rootNode)
// println(intersectionSize)
//
// printTree(rootNode)
// printNodes()
val intersectionSize = estimateIntersectionSize(rootNode)
println(intersectionSize)

printTree(rootNode)
printNodes()
}

fun main() {
Expand Down
26 changes: 14 additions & 12 deletions src/main/kotlin/exercise6/taskProjections/task1/Task.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ package exercise6.taskProjections.task1

**/

interface Sender {
fun send(item: Any)
interface Sender<T>{
fun send(item: T)
}

class MailBox(private var box: Any? = null): Sender {
override fun send(item: Any) {
class MailBox <T> (private var box: T? = null): Sender<T> {
override fun send(item: T) {
printCurrentBoxState()
println("Sending the box: $item!")
box = item
Expand All @@ -32,8 +32,8 @@ class MailBox(private var box: Any? = null): Sender {

}

class Postman(private val mailboxes: List<Sender>): Sender {
override fun send(item: Any) {
class Postman<T>(private val mailboxes: List<Sender<T>>): Sender<T> {
override fun send(item: T) {
mailboxes.forEach { it.send(item) }
}

Expand All @@ -45,14 +45,16 @@ open class Postcard(open val origin: String) : Delivery
data class ExpressPostcard(val priceEuro: Int, override val origin: String) : Postcard(origin)

fun main() {
// TODO: This code should became compilable
// val postcardStorage = MailBox<Postcard>()
// val expressPostcardStorage = MailBox<ExpressPostcard>()
val postcardStorage = MailBox<Postcard>()
val expressPostcardStorage = MailBox<ExpressPostcard>()

val expressPostcard = ExpressPostcard(15, "Serbia")
val postcard = Postcard("Germany")

// TODO: add code to create topRatedPostman and juniorPostman.
// The topRatedPostman can send ONLY express postcards
// The juniorPostman can send both regular and express postcards
val topRatedPostman: Postman<ExpressPostcard> = Postman(listOf(expressPostcardStorage))
val juniorPostman: Postman<Postcard> = Postman(listOf(postcardStorage))

topRatedPostman.send(expressPostcard)
juniorPostman.send(expressPostcard)
juniorPostman.send(postcard)
}
29 changes: 17 additions & 12 deletions src/main/kotlin/exercise6/taskProjections/task2/Task.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@ package exercise6.taskProjections.task2
* If you did everything correct, you could not create a method create which accepts nothing and returns T
**/

class Programmer<in T : ProgrammingLanguage>() {
fun learn(language: T) {
println("I learned ${language.name}!")
}
}

interface ProgrammingLanguage {
val name: String
}
Expand All @@ -18,16 +24,15 @@ class JvmLanguage(override val name: String) : ProgrammingLanguage
class BlockBasedLanguage(override val name: String) : ProgrammingLanguage

fun main() {
TODO("Uncomment this code when you finish the task")
// val programmer = Programmer<ProgrammingLanguage>()
//
// val jvmLanguages = listOf(JvmLanguage("Java"), JvmLanguage("Kotlin"))
// jvmLanguages.forEach{ programmer.learn(it) } // OK
//
// val blockBasedLanguages = listOf(BlockBasedLanguage("Scratch"), JvmLanguage("Snap"))
// blockBasedLanguages.forEach{ programmer.learn(it) } // OK
//
// (jvmLanguages + blockBasedLanguages).forEach{ programmer.learn(it) } // OK
//
//// val newLanguage: ProgrammingLanguage = programmer.create() // ERROR
val programmer = Programmer<ProgrammingLanguage>()

val jvmLanguages = listOf(JvmLanguage("Java"), JvmLanguage("Kotlin"))
jvmLanguages.forEach{ programmer.learn(it) } // OK

val blockBasedLanguages = listOf(BlockBasedLanguage("Scratch"), JvmLanguage("Snap"))
blockBasedLanguages.forEach{ programmer.learn(it) } // OK

(jvmLanguages + blockBasedLanguages).forEach{ programmer.learn(it) } // OK

// val newLanguage: ProgrammingLanguage = programmer.create() // ERROR
}
15 changes: 8 additions & 7 deletions src/main/kotlin/exercise6/taskProjections/task3/Task.kt
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,12 @@ class BlockBasedLanguageParser : LanguageParser<BlockBasedLanguage> {
}

fun main() {
TODO("Create a new HashMap and uncomment code bellow")
// parsersHashMap[JvmLanguage::class.java] = JvmLanguageParser()
// parsersHashMap[BlockBasedLanguage::class.java] = BlockBasedLanguageParser()
//
// val scratch = BlockBasedLanguage()
// val foundParser = parsersHashMap[scratch.javaClass]
// foundParser?.parse(scratch)
val parsersHashMap = HashMap<Class<*>, LanguageParser<*>>()

parsersHashMap[JvmLanguage::class.java] = JvmLanguageParser()
parsersHashMap[BlockBasedLanguage::class.java] = BlockBasedLanguageParser()

val scratch = BlockBasedLanguage()
val foundParser = parsersHashMap[scratch.javaClass]
foundParser?.parse(scratch)
}
12 changes: 10 additions & 2 deletions src/main/kotlin/exercise6/taskProjections/task4/Task.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,15 @@ package exercise6.taskProjections.task4
* that accepts two arrays with a generic type of Any and copy elements from the first array to the second one.
**/

fun <Any> copy(arr1 : Array<Any>, arr2 : Array<in Any>) {
require(arr2.size >= arr1.size) {
throw Exception("Second array is shorter than first!")
}

for (i in arr1.indices)
arr2[i] = arr1[i]
}

fun main() {
val ints = arrayOf(1, 2, 3)
val any = Array<Any>(3) { "" }
Expand All @@ -17,8 +26,7 @@ fun main() {
println("_______")
println("_______")

// TODO: uncomment this code
// copy(ints, any)
copy(ints, any)

ints.forEach{ print("$it ") }
println()
Expand Down
39 changes: 29 additions & 10 deletions src/main/kotlin/exercise6/taskProjections/task5/Task.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,46 @@ package exercise6.taskProjections.task5
* Create a new class "Printer", that can accept only T elements and print them
* - add a "print" function that prints item with type T;
*

**/

class Printer<T> {
fun print(element : T) {
println(element)
}
}

/**

* [2]
* Create a new abstract class "Builder" that generates instances of T based on parameter of P type.
* This class cannot produce P and consume T:
* - add an abstract "build" function that accepts P and returns T;
* Create a new class "IntegerBuilder", that implements Builder and can convert String to Int
**/

abstract class Builder<in P, out T> {
abstract fun build(input : P) : T
}

class IntegerBuilder() : Builder<String, Int>() {
override fun build(input: String): Int {
return input.toInt()
}
}

fun main() {
// [1]
// TODO: uncomment me
// val integerPrinter = Printer<Int>()
// val stringPrinter = Printer<String>()
//
// integerPrinter.print(2)
// stringPrinter.print("Bla bla bla")
val integerPrinter = Printer<Int>()
val stringPrinter = Printer<String>()

integerPrinter.print(2)
stringPrinter.print("Bla bla bla")

println("________")

// [2]
// TODO: uncomment me
// val intBuilder = IntegerBuilder()
// val x = intBuilder.build("1")
// println("We build [ $x ]")
val intBuilder = IntegerBuilder()
val x = intBuilder.build("1")
println("We build [ $x ]")
}
34 changes: 16 additions & 18 deletions src/main/kotlin/exercise6/taskProjections/task6/Task.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,22 @@ open class A
class B : A()
class C : A() { fun consume(other: A): C = this }

// TODO: uncomment and fix me
//fun <T, S : R, R> funny(
// source: Iterator<??>,
// target: MutableCollection<??>,
// base: ??,
// how: ??
//) {
// var result: R = base
// for (value in source) {
// result = how(result, value)
// target.add(result)
// }
//}
fun <T, S : R, R> funny(
source: Iterator<T>,
target: MutableCollection<in R>,
base: R,
how: (R, T) -> S
) {
var result: R = base
for (value in source) {
result = how(result, value)
target.add(result)
}
}

fun main() {
// TODO: uncomment me, it should not produce any compilation errors
// val wtf = mutableListOf<A>()
// val src = mapOf(3.14 to B(), 2 to B(), "Hello" to B())
// val c = C()
// funny(src.values.iterator(), wtf, c) { r, t -> r.consume(t) }
val wtf = mutableListOf<A>()
val src = mapOf(3.14 to B(), 2 to B(), "Hello" to B())
val c = C()
funny(src.values.iterator(), wtf, c) { r, t -> r.consume(t) }
}