From abd63a217b6ba3204272575301158f13cf71176d Mon Sep 17 00:00:00 2001 From: Svetlana Isakova Date: Wed, 5 Feb 2020 19:33:00 +0100 Subject: [PATCH] Regenerated project, added placeholders for exercises --- .../Helper Functions/Exercise 2/task.md | 2 +- .../Exercise 1/src/GameElements.kt | 43 ----- .../Abstract Classes/Exercise 1/src/Maze.kt | 75 -------- .../Abstract Classes/Exercise 1/src/MazeEx.kt | 18 -- .../Abstract Classes/Exercise 1/src/Robot.kt | 67 ------- .../Abstract Classes/Exercise 1/src/Task.kt | 3 + .../Exercise 1/task-info.yaml | 14 +- .../Abstract Classes/Exercise 1/test/Tests.kt | 123 +----------- .../Abstract Classes/Exercise 2/src/Task.kt | 3 + .../Exercise 2/task-info.yaml | 6 + .../Abstract Classes/Exercise 2/task.md | 67 +++++++ .../Abstract Classes/Exercise 2/test/Tests.kt | 11 ++ .../Abstract Classes/Exercise 3/src/Task.kt | 3 + .../Exercise 3/task-info.yaml | 6 + .../Abstract Classes/Exercise 3/task.md | 75 ++++++++ .../Abstract Classes/Exercise 3/test/Tests.kt | 11 ++ .../Abstract Classes/lesson-info.yaml | 2 + .../Examples/src/Players2.kt | 27 --- .../Examples/src/Room2.kt | 17 -- .../Examples/task-info.yaml | 8 - .../Exercise 4/src/GameElements.kt | 41 ---- .../Exercise 4/task-info.yaml | 35 ---- .../Exercise 4/task.md | 14 -- .../Exercise 4/test/Tests.kt | 26 --- .../lesson-info.yaml | 1 - .../Examples/src/ClassDelegEx1.kt | 35 +++- .../Examples/src/CompanionFactory.kt | 1 - .../Examples/src/ObjectCounter.kt | 1 - .../Examples/src/ObjectProperty.kt | 1 - .../Exercise 4/src/GameElements.kt | 24 --- .../Exercise 4/src/Maze.kt | 94 --------- .../Exercise 4/task-info.yaml | 17 -- .../Complex Constructors/Exercise 4/task.md | 13 -- .../Exercise 4/test/Tests.kt | 61 ------ .../Complex Constructors/lesson-info.yaml | 1 - .../Composition/Exercise 1/src/Task.kt | 3 + .../Composition/Exercise 1/task-info.yaml | 6 + .../Composition/Exercise 1/task.md | 60 ++++++ .../Composition/Exercise 1/test/Tests.kt | 11 ++ .../Composition/Exercise 2/src/Task.kt | 3 + .../Composition/Exercise 2/task-info.yaml | 6 + .../Composition/Exercise 2/task.md | 70 +++++++ .../Composition/Exercise 2/test/Tests.kt | 11 ++ .../Composition/Exercise 3/src/Task.kt | 3 + .../Composition/Exercise 3/task-info.yaml | 6 + .../Composition/Exercise 3/task.md | 102 ++++++++++ .../Composition/Exercise 3/test/Tests.kt | 11 ++ .../Composition/lesson-info.yaml | 3 + .../Extensibility/Examples/src/Doors3.kt | 32 ---- .../Examples/src/ExploreMaze2.kt | 3 +- .../Examples/src/ExploreMaze3.kt | 7 - .../Extensibility/Examples/src/Players2.kt | 98 ++++++++++ .../Extensibility/Examples/src/Players3.kt | 63 ------- .../Extensibility/Examples/src/Room2.kt | 33 ++++ .../Extensibility/Examples/src/Room3.kt | 6 - .../Examples/src/Stage2.kt | 56 +++--- .../Extensibility/Examples/src/Urge3.kt | 14 -- .../Extensibility/Examples/src/View2.kt | 19 ++ .../Extensibility/Examples/src/View3.kt | 30 --- .../Extensibility/Examples/task-info.yaml | 14 +- .../Exercise 1/src/Task.kt | 3 + .../Exercise 1/task-info.yaml | 6 + .../Exercise 1/task.md | 94 +++++++++ .../Exercise 1/test/Tests.kt | 11 ++ .../Exercise 2/src/Task.kt | 3 + .../Exercise 2/task-info.yaml | 6 + .../Exercise 2/task.md | 81 ++++++++ .../Exercise 2/test/Tests.kt | 11 ++ .../Exercise 3/src/Task.kt | 3 + .../Exercise 3/task-info.yaml | 6 + .../Exercise 3/task.md | 52 +++++ .../Exercise 3/test/Tests.kt | 11 ++ .../Inheritance & Extensions/lesson-info.yaml | 3 + .../Inheritance/Exercise 4/src/Bomb.kt | 67 ------- .../Exercise 4/src/GameElements.kt | 49 ----- .../Inheritance/Exercise 4/src/Maze.kt | 75 -------- .../Inheritance/Exercise 4/task-info.yaml | 16 -- .../Inheritance/Exercise 4/task.md | 8 - .../Inheritance/Exercise 4/test/Tests.kt | 178 ------------------ .../Inheritance/lesson-info.yaml | 1 - .../Interfaces/Exercise 2/task.md | 6 +- .../Interfaces/Exercise 3/task.md | 8 +- .../Interfaces/Exercise 4/src/GameElements.kt | 17 -- .../Interfaces/Exercise 4/src/GameMatrix.kt | 91 --------- .../Interfaces/Exercise 4/task-info.yaml | 17 -- .../Interfaces/Exercise 4/task.md | 12 -- .../Interfaces/Exercise 4/test/Tests.kt | 92 --------- .../Interfaces/lesson-info.yaml | 1 - .../Examples/src/ExploreMaze3.kt | 20 ++ .../Examples/src/Players3.kt | 148 +++++++++++++++ .../Examples/src/Room3.kt | 35 ++++ .../Examples/src/Stage3.kt | 55 +++--- .../Examples/task-info.yaml | 10 + .../OO Design, Revisited/Examples/task.md | 3 + .../OO Design, Revisited}/lesson-info.yaml | 0 .../Examples/src/Doors.kt | 9 +- .../Examples/src/ExploreMaze.kt | 4 +- .../Examples/src/MazeView.kt | 18 ++ .../Examples/src/Players.kt | 24 ++- .../Examples/src/RobotMaze.kt | 22 ++- .../Examples/src/Room.kt | 15 +- .../Examples/src/Stage.kt | 28 +-- .../Examples/src/Urge.kt | 6 +- .../Examples/src/View.kt | 20 +- .../Examples/task-info.yaml | 2 + .../Polymorphism/Exercise 1/src/Task.kt | 3 + .../Polymorphism/Exercise 1/task-info.yaml | 6 + .../Polymorphism/Exercise 1/task.md | 33 ++++ .../Polymorphism/Exercise 1/test/Tests.kt | 11 ++ .../Polymorphism/Exercise 2/src/Task.kt | 3 + .../Polymorphism/Exercise 2/task-info.yaml | 6 + .../Polymorphism/Exercise 2/task.md | 164 ++++++++++++++++ .../Polymorphism/Exercise 2/test/Tests.kt | 11 ++ .../Polymorphism/Exercise 3/src/Task.kt | 3 + .../Polymorphism/Exercise 3/task-info.yaml | 6 + .../Polymorphism/Exercise 3/task.md | 50 +++++ .../Polymorphism/Exercise 3/test/Tests.kt | 11 ++ .../Polymorphism/lesson-info.yaml | 3 + .../Upcasting/Exercise 1/src/Task.kt | 3 + .../Upcasting/Exercise 1/task-info.yaml | 6 + .../Upcasting/Exercise 1/task.md | 64 +++++++ .../Upcasting/Exercise 1/test/Tests.kt | 11 ++ .../Upcasting/Exercise 2/src/Task.kt | 3 + .../Upcasting/Exercise 2/task-info.yaml | 6 + .../Upcasting/Exercise 2/task.md | 76 ++++++++ .../Upcasting/Exercise 2/test/Tests.kt | 11 ++ .../Upcasting/Exercise 3/src/Task.kt | 3 + .../Upcasting/Exercise 3/task-info.yaml | 6 + .../Upcasting/Exercise 3/task.md | 73 +++++++ .../Upcasting/Exercise 3/test/Tests.kt | 11 ++ .../Upcasting/lesson-info.yaml | 3 + Object-Oriented Programming/section-info.yaml | 2 +- Power Tools/section-info.yaml | 1 - .../Examples/src/Computation.kt | 0 .../Examples/src/DestructuringEx1.kt | 22 +++ .../Examples/src/DestructuringEx2.kt | 23 +++ .../Examples/src/DestructuringEx3.kt | 14 ++ .../Examples/src/ForLoop.kt | 0 .../Examples/src/PairDestructuring.kt | 0 .../Examples/src/Pairs.kt | 0 .../Examples/src/Tuple.kt | 0 .../Examples/task-info.yaml | 6 + .../Examples/task.md | 0 .../Exercise 1/src/Task.kt | 3 + .../Exercise 1/task-info.yaml | 6 + .../Exercise 1/task.md | 39 ++++ .../Exercise 1/test/Tests.kt | 11 ++ .../Exercise 2/src/Task.kt | 3 + .../Exercise 2/task-info.yaml | 6 + .../Exercise 2/task.md | 39 ++++ .../Exercise 2/test/Tests.kt | 11 ++ .../Exercise 3/src/Task.kt | 3 + .../Exercise 3/task-info.yaml | 6 + .../Exercise 3/task.md | 25 +++ .../Exercise 3/test/Tests.kt | 11 ++ .../lesson-info.yaml | 5 + Usability/section-info.yaml | 1 + util/test/TestAllExamples.java | 140 +++++--------- util/test/TestAllExercises.kt | 61 ++++-- 159 files changed, 2262 insertions(+), 1725 deletions(-) delete mode 100644 Object-Oriented Programming/Abstract Classes/Exercise 1/src/GameElements.kt delete mode 100644 Object-Oriented Programming/Abstract Classes/Exercise 1/src/Maze.kt delete mode 100644 Object-Oriented Programming/Abstract Classes/Exercise 1/src/MazeEx.kt delete mode 100644 Object-Oriented Programming/Abstract Classes/Exercise 1/src/Robot.kt create mode 100644 Object-Oriented Programming/Abstract Classes/Exercise 1/src/Task.kt create mode 100644 Object-Oriented Programming/Abstract Classes/Exercise 2/src/Task.kt create mode 100644 Object-Oriented Programming/Abstract Classes/Exercise 2/task-info.yaml create mode 100644 Object-Oriented Programming/Abstract Classes/Exercise 2/task.md create mode 100644 Object-Oriented Programming/Abstract Classes/Exercise 2/test/Tests.kt create mode 100644 Object-Oriented Programming/Abstract Classes/Exercise 3/src/Task.kt create mode 100644 Object-Oriented Programming/Abstract Classes/Exercise 3/task-info.yaml create mode 100644 Object-Oriented Programming/Abstract Classes/Exercise 3/task.md create mode 100644 Object-Oriented Programming/Abstract Classes/Exercise 3/test/Tests.kt delete mode 100644 Object-Oriented Programming/Base Class Initialization/Examples/src/Players2.kt delete mode 100644 Object-Oriented Programming/Base Class Initialization/Examples/src/Room2.kt delete mode 100644 Object-Oriented Programming/Base Class Initialization/Exercise 4/src/GameElements.kt delete mode 100644 Object-Oriented Programming/Base Class Initialization/Exercise 4/task-info.yaml delete mode 100644 Object-Oriented Programming/Base Class Initialization/Exercise 4/task.md delete mode 100644 Object-Oriented Programming/Base Class Initialization/Exercise 4/test/Tests.kt delete mode 100644 Object-Oriented Programming/Complex Constructors/Exercise 4/src/GameElements.kt delete mode 100644 Object-Oriented Programming/Complex Constructors/Exercise 4/src/Maze.kt delete mode 100644 Object-Oriented Programming/Complex Constructors/Exercise 4/task-info.yaml delete mode 100644 Object-Oriented Programming/Complex Constructors/Exercise 4/task.md delete mode 100644 Object-Oriented Programming/Complex Constructors/Exercise 4/test/Tests.kt create mode 100644 Object-Oriented Programming/Composition/Exercise 1/src/Task.kt create mode 100644 Object-Oriented Programming/Composition/Exercise 1/task-info.yaml create mode 100644 Object-Oriented Programming/Composition/Exercise 1/task.md create mode 100644 Object-Oriented Programming/Composition/Exercise 1/test/Tests.kt create mode 100644 Object-Oriented Programming/Composition/Exercise 2/src/Task.kt create mode 100644 Object-Oriented Programming/Composition/Exercise 2/task-info.yaml create mode 100644 Object-Oriented Programming/Composition/Exercise 2/task.md create mode 100644 Object-Oriented Programming/Composition/Exercise 2/test/Tests.kt create mode 100644 Object-Oriented Programming/Composition/Exercise 3/src/Task.kt create mode 100644 Object-Oriented Programming/Composition/Exercise 3/task-info.yaml create mode 100644 Object-Oriented Programming/Composition/Exercise 3/task.md create mode 100644 Object-Oriented Programming/Composition/Exercise 3/test/Tests.kt delete mode 100644 Object-Oriented Programming/Extensibility/Examples/src/Doors3.kt rename Object-Oriented Programming/{Base Class Initialization => Extensibility}/Examples/src/ExploreMaze2.kt (94%) delete mode 100644 Object-Oriented Programming/Extensibility/Examples/src/ExploreMaze3.kt create mode 100644 Object-Oriented Programming/Extensibility/Examples/src/Players2.kt delete mode 100644 Object-Oriented Programming/Extensibility/Examples/src/Players3.kt create mode 100644 Object-Oriented Programming/Extensibility/Examples/src/Room2.kt delete mode 100644 Object-Oriented Programming/Extensibility/Examples/src/Room3.kt rename Object-Oriented Programming/{Base Class Initialization => Extensibility}/Examples/src/Stage2.kt (56%) delete mode 100644 Object-Oriented Programming/Extensibility/Examples/src/Urge3.kt create mode 100644 Object-Oriented Programming/Extensibility/Examples/src/View2.kt delete mode 100644 Object-Oriented Programming/Extensibility/Examples/src/View3.kt create mode 100644 Object-Oriented Programming/Inheritance & Extensions/Exercise 1/src/Task.kt create mode 100644 Object-Oriented Programming/Inheritance & Extensions/Exercise 1/task-info.yaml create mode 100644 Object-Oriented Programming/Inheritance & Extensions/Exercise 1/task.md create mode 100644 Object-Oriented Programming/Inheritance & Extensions/Exercise 1/test/Tests.kt create mode 100644 Object-Oriented Programming/Inheritance & Extensions/Exercise 2/src/Task.kt create mode 100644 Object-Oriented Programming/Inheritance & Extensions/Exercise 2/task-info.yaml create mode 100644 Object-Oriented Programming/Inheritance & Extensions/Exercise 2/task.md create mode 100644 Object-Oriented Programming/Inheritance & Extensions/Exercise 2/test/Tests.kt create mode 100644 Object-Oriented Programming/Inheritance & Extensions/Exercise 3/src/Task.kt create mode 100644 Object-Oriented Programming/Inheritance & Extensions/Exercise 3/task-info.yaml create mode 100644 Object-Oriented Programming/Inheritance & Extensions/Exercise 3/task.md create mode 100644 Object-Oriented Programming/Inheritance & Extensions/Exercise 3/test/Tests.kt delete mode 100644 Object-Oriented Programming/Inheritance/Exercise 4/src/Bomb.kt delete mode 100644 Object-Oriented Programming/Inheritance/Exercise 4/src/GameElements.kt delete mode 100644 Object-Oriented Programming/Inheritance/Exercise 4/src/Maze.kt delete mode 100644 Object-Oriented Programming/Inheritance/Exercise 4/task-info.yaml delete mode 100644 Object-Oriented Programming/Inheritance/Exercise 4/task.md delete mode 100644 Object-Oriented Programming/Inheritance/Exercise 4/test/Tests.kt delete mode 100644 Object-Oriented Programming/Interfaces/Exercise 4/src/GameElements.kt delete mode 100644 Object-Oriented Programming/Interfaces/Exercise 4/src/GameMatrix.kt delete mode 100644 Object-Oriented Programming/Interfaces/Exercise 4/task-info.yaml delete mode 100644 Object-Oriented Programming/Interfaces/Exercise 4/task.md delete mode 100644 Object-Oriented Programming/Interfaces/Exercise 4/test/Tests.kt create mode 100644 Object-Oriented Programming/OO Design, Revisited/Examples/src/ExploreMaze3.kt create mode 100644 Object-Oriented Programming/OO Design, Revisited/Examples/src/Players3.kt create mode 100644 Object-Oriented Programming/OO Design, Revisited/Examples/src/Room3.kt rename Object-Oriented Programming/{Extensibility => OO Design, Revisited}/Examples/src/Stage3.kt (54%) create mode 100644 Object-Oriented Programming/OO Design, Revisited/Examples/task-info.yaml create mode 100644 Object-Oriented Programming/OO Design, Revisited/Examples/task.md rename {Power Tools/Destructuring Declarations => Object-Oriented Programming/OO Design, Revisited}/lesson-info.yaml (100%) create mode 100644 Object-Oriented Programming/Object-Oriented Design/Examples/src/MazeView.kt create mode 100644 Object-Oriented Programming/Polymorphism/Exercise 1/src/Task.kt create mode 100644 Object-Oriented Programming/Polymorphism/Exercise 1/task-info.yaml create mode 100644 Object-Oriented Programming/Polymorphism/Exercise 1/task.md create mode 100644 Object-Oriented Programming/Polymorphism/Exercise 1/test/Tests.kt create mode 100644 Object-Oriented Programming/Polymorphism/Exercise 2/src/Task.kt create mode 100644 Object-Oriented Programming/Polymorphism/Exercise 2/task-info.yaml create mode 100644 Object-Oriented Programming/Polymorphism/Exercise 2/task.md create mode 100644 Object-Oriented Programming/Polymorphism/Exercise 2/test/Tests.kt create mode 100644 Object-Oriented Programming/Polymorphism/Exercise 3/src/Task.kt create mode 100644 Object-Oriented Programming/Polymorphism/Exercise 3/task-info.yaml create mode 100644 Object-Oriented Programming/Polymorphism/Exercise 3/task.md create mode 100644 Object-Oriented Programming/Polymorphism/Exercise 3/test/Tests.kt create mode 100644 Object-Oriented Programming/Upcasting/Exercise 1/src/Task.kt create mode 100644 Object-Oriented Programming/Upcasting/Exercise 1/task-info.yaml create mode 100644 Object-Oriented Programming/Upcasting/Exercise 1/task.md create mode 100644 Object-Oriented Programming/Upcasting/Exercise 1/test/Tests.kt create mode 100644 Object-Oriented Programming/Upcasting/Exercise 2/src/Task.kt create mode 100644 Object-Oriented Programming/Upcasting/Exercise 2/task-info.yaml create mode 100644 Object-Oriented Programming/Upcasting/Exercise 2/task.md create mode 100644 Object-Oriented Programming/Upcasting/Exercise 2/test/Tests.kt create mode 100644 Object-Oriented Programming/Upcasting/Exercise 3/src/Task.kt create mode 100644 Object-Oriented Programming/Upcasting/Exercise 3/task-info.yaml create mode 100644 Object-Oriented Programming/Upcasting/Exercise 3/task.md create mode 100644 Object-Oriented Programming/Upcasting/Exercise 3/test/Tests.kt rename {Power Tools => Usability}/Destructuring Declarations/Examples/src/Computation.kt (100%) create mode 100644 Usability/Destructuring Declarations/Examples/src/DestructuringEx1.kt create mode 100644 Usability/Destructuring Declarations/Examples/src/DestructuringEx2.kt create mode 100644 Usability/Destructuring Declarations/Examples/src/DestructuringEx3.kt rename {Power Tools => Usability}/Destructuring Declarations/Examples/src/ForLoop.kt (100%) rename {Power Tools => Usability}/Destructuring Declarations/Examples/src/PairDestructuring.kt (100%) rename {Power Tools => Usability}/Destructuring Declarations/Examples/src/Pairs.kt (100%) rename {Power Tools => Usability}/Destructuring Declarations/Examples/src/Tuple.kt (100%) rename {Power Tools => Usability}/Destructuring Declarations/Examples/task-info.yaml (60%) rename {Power Tools => Usability}/Destructuring Declarations/Examples/task.md (100%) create mode 100644 Usability/Destructuring Declarations/Exercise 1/src/Task.kt create mode 100644 Usability/Destructuring Declarations/Exercise 1/task-info.yaml create mode 100644 Usability/Destructuring Declarations/Exercise 1/task.md create mode 100644 Usability/Destructuring Declarations/Exercise 1/test/Tests.kt create mode 100644 Usability/Destructuring Declarations/Exercise 2/src/Task.kt create mode 100644 Usability/Destructuring Declarations/Exercise 2/task-info.yaml create mode 100644 Usability/Destructuring Declarations/Exercise 2/task.md create mode 100644 Usability/Destructuring Declarations/Exercise 2/test/Tests.kt create mode 100644 Usability/Destructuring Declarations/Exercise 3/src/Task.kt create mode 100644 Usability/Destructuring Declarations/Exercise 3/task-info.yaml create mode 100644 Usability/Destructuring Declarations/Exercise 3/task.md create mode 100644 Usability/Destructuring Declarations/Exercise 3/test/Tests.kt create mode 100644 Usability/Destructuring Declarations/lesson-info.yaml diff --git a/Functional Programming/Helper Functions/Exercise 2/task.md b/Functional Programming/Helper Functions/Exercise 2/task.md index e65aa0c5..9b1eaff9 100644 --- a/Functional Programming/Helper Functions/Exercise 2/task.md +++ b/Functional Programming/Helper Functions/Exercise 2/task.md @@ -1,5 +1,5 @@ ## Helper Functions (#2) Write a function `oddWithout1` that creates an infinite sequence of odd numbers -that do not contain the digit `1`. In `main`, display to the console the sum of +that do not contain the digit `1`. In `main`, display to the console the sum of the first 20 elements of this sequence. \ No newline at end of file diff --git a/Object-Oriented Programming/Abstract Classes/Exercise 1/src/GameElements.kt b/Object-Oriented Programming/Abstract Classes/Exercise 1/src/GameElements.kt deleted file mode 100644 index 365792d2..00000000 --- a/Object-Oriented Programming/Abstract Classes/Exercise 1/src/GameElements.kt +++ /dev/null @@ -1,43 +0,0 @@ -package abstractClassesExercise1 - -interface GameElement { - val symbol: Char - val sharesCell: Boolean - fun play(maze: Maze) -} - -abstract class StaticElement( - override val sharesCell: Boolean -) : GameElement { - override fun play(maze: Maze) { - // Default implementation: do nothing - } -} - -class Wall : StaticElement(sharesCell = false) { - override val symbol get() = '#' -} - -class Food : StaticElement(sharesCell = true) { - override val symbol get() = '.' -} - -abstract class MobileElement : GameElement { - override val sharesCell: Boolean - get() = true - - abstract fun move(move: Move, maze: Maze): Cell? - - override fun toString() = symbol.toString() -} - -enum class Move { - UP, RIGHT, DOWN, LEFT, WAIT -} - -fun createGameElement(char: Char?): GameElement? = when (char) { - '#' -> Wall() - '.' -> Food() - 'R' -> Robot() - else -> null -} \ No newline at end of file diff --git a/Object-Oriented Programming/Abstract Classes/Exercise 1/src/Maze.kt b/Object-Oriented Programming/Abstract Classes/Exercise 1/src/Maze.kt deleted file mode 100644 index a68b44d6..00000000 --- a/Object-Oriented Programming/Abstract Classes/Exercise 1/src/Maze.kt +++ /dev/null @@ -1,75 +0,0 @@ -package abstractClassesExercise1 - -data class Cell(val x: Int, val y: Int) - -interface Maze { - val width: Int - val height: Int - fun all(): Set - fun allIn(cell: Cell): Set - fun cell(element: GameElement): Cell? - fun add(element: GameElement, cell: Cell) - fun remove(element: GameElement) -} - -class MazeImpl( - representation: String -) : Maze { - override val width: Int - override val height: Int - - private val elementMap: List>> - private val cellMap = mutableMapOf() - - init { - val lines = representation.lines() - height = lines.size - width = lines.maxBy { it.length }?.length ?: 0 - elementMap = List(height) { - List(width) { mutableSetOf() } - } - for (y in 0 until height) { - for (x in 0 until width) { - val ch = lines.getOrNull(y)?.getOrNull(x) - val element = createGameElement(ch) - if (element != null) { - add(element, Cell(x, y)) - } - } - } - } - - private fun elements(cell: Cell): MutableSet { - return elementMap[cell.y][cell.x] - } - - override fun all(): Set { - return cellMap.keys.toSet() - } - - override fun allIn(cell: Cell): Set { - return elements(cell) - } - - override fun cell(element: GameElement): Cell? { - return cellMap[element] - } - - override fun add(element: GameElement, cell: Cell) { - elements(cell) += element - cellMap[element] = cell - } - - override fun remove(element: GameElement) { - val cell = cell(element) ?: return - elements(cell) -= element - cellMap.remove(element) - } - - override fun toString() = - elementMap.joinToString("\n") { row -> - row.joinToString("") { elements -> - "${elements.lastOrNull()?.symbol ?: ' '}" - }.trimEnd() - } -} \ No newline at end of file diff --git a/Object-Oriented Programming/Abstract Classes/Exercise 1/src/MazeEx.kt b/Object-Oriented Programming/Abstract Classes/Exercise 1/src/MazeEx.kt deleted file mode 100644 index 1cf837cd..00000000 --- a/Object-Oriented Programming/Abstract Classes/Exercise 1/src/MazeEx.kt +++ /dev/null @@ -1,18 +0,0 @@ -package abstractClassesExercise1 - -fun Maze.isPassable(cell: Cell): Boolean { - if (cell.x !in (0 until width) || cell.y !in (0 until height)) { - return false - } - val cellOccupants = allIn(cell) - return cellOccupants.all { it.sharesCell } -} - -fun Cell.applyMove(move: Move): Cell = - when (move) { - Move.WAIT -> Cell(x, y) - Move.UP -> Cell(x, y - 1) - Move.DOWN -> Cell(x, y + 1) - Move.RIGHT -> Cell(x + 1, y) - Move.LEFT -> Cell(x - 1, y) - } \ No newline at end of file diff --git a/Object-Oriented Programming/Abstract Classes/Exercise 1/src/Robot.kt b/Object-Oriented Programming/Abstract Classes/Exercise 1/src/Robot.kt deleted file mode 100644 index 53db0335..00000000 --- a/Object-Oriented Programming/Abstract Classes/Exercise 1/src/Robot.kt +++ /dev/null @@ -1,67 +0,0 @@ -package abstractClassesExercise1 - -import atomictest.eq - -class Robot : MobileElement() { - - private var eatenFoodItems: Int = 0 - - override val symbol: Char - get() = 'R' - - override fun play(maze: Maze) { - val cell = maze.cell(this) ?: return - val cellElements = maze.allIn(cell) - cellElements - .filterIsInstance() - .forEach { food -> - eatenFoodItems++ - maze.remove(food) - } - } - - override fun move(move: Move, maze: Maze): Cell? { - val currentCell = maze.cell(this) ?: return null - val newCell = currentCell.applyMove(move) - if (!maze.isPassable(newCell)) return null - return newCell - } -} - -fun main() { - val mapRepresentation = """ - ##### - # # - # ## - """.trimIndent() - val maze = MazeImpl(mapRepresentation) - maze.toString() eq mapRepresentation - - val robot = Robot() - - fun updateRobotCell(cell: Cell?) { - if (cell != null) { - maze.remove(robot) - maze.add(robot, cell) - } - } - - updateRobotCell(Cell(x = 2, y = 1)) - maze.toString() eq """ - ##### - # R # - # ## - """.trimIndent() - - - updateRobotCell(robot.move(Move.DOWN, maze)) - maze.toString() eq """ - ##### - # # - # R## - """.trimIndent() - - // The right move is impossible: - val cell = robot.move(Move.RIGHT, maze) - cell eq null -} \ No newline at end of file diff --git a/Object-Oriented Programming/Abstract Classes/Exercise 1/src/Task.kt b/Object-Oriented Programming/Abstract Classes/Exercise 1/src/Task.kt new file mode 100644 index 00000000..73e1edb5 --- /dev/null +++ b/Object-Oriented Programming/Abstract Classes/Exercise 1/src/Task.kt @@ -0,0 +1,3 @@ +package abstractClassesExercise1 + +// type your solution here \ No newline at end of file diff --git a/Object-Oriented Programming/Abstract Classes/Exercise 1/task-info.yaml b/Object-Oriented Programming/Abstract Classes/Exercise 1/task-info.yaml index 4f673050..7ad1b827 100644 --- a/Object-Oriented Programming/Abstract Classes/Exercise 1/task-info.yaml +++ b/Object-Oriented Programming/Abstract Classes/Exercise 1/task-info.yaml @@ -1,18 +1,6 @@ type: edu files: -- name: src/GameElements.kt - visible: true -- name: src/Maze.kt +- name: src/Task.kt visible: true - name: test/Tests.kt visible: false -- name: src/MazeEx.kt - visible: true -- name: src/Robot.kt - visible: true - placeholders: - - offset: 483 - length: 160 - placeholder_text: TODO() -feedback_link: | - https://docs.google.com/forms/d/e/1FAIpQLSdkaliSwYkjiV21bZl0yP-In2g5p17sAQCfaGjyHx_QYMWTiQ/viewform?usp=pp_url&entry.189755027=Object-Oriented+Programming+%2F+Abstract+Classes+%2F+Exercise1 diff --git a/Object-Oriented Programming/Abstract Classes/Exercise 1/test/Tests.kt b/Object-Oriented Programming/Abstract Classes/Exercise 1/test/Tests.kt index a6283888..e1ad4133 100644 --- a/Object-Oriented Programming/Abstract Classes/Exercise 1/test/Tests.kt +++ b/Object-Oriented Programming/Abstract Classes/Exercise 1/test/Tests.kt @@ -1,128 +1,11 @@ package abstractClassesExercise1 -import abstractClassesExercise1.Move.* import org.junit.Assert -import org.junit.FixMethodOrder import org.junit.Test -import org.junit.runners.MethodSorters -import util.TIMEOUT -@FixMethodOrder(MethodSorters.NAME_ASCENDING) class TestAbstractClassesExercise1 { - private fun checkMove( - move: Move, - initial: String, - expected: String - ) { - val maze = MazeImpl(initial.trimIndent()) - val robot = maze.all().filterIsInstance().single() - val cell = robot.move(move, maze) - if (cell != null) { - maze.remove(robot) - maze.add(robot, cell) + @Test fun testSolution() { + //TODO: implement your test here + Assert.assertTrue("Tests not implemented for the task", false) } - Assert.assertEquals( - "Wrong result for\n$initial", - expected.trimIndent(), - maze.toString() - ) - } - - private fun checkImpossibleMove( - move: Move, - initial: String - ) { - val maze = MazeImpl(initial.trimIndent()) - val robot = maze.all().filterIsInstance().single() - val cell = robot.move(move, maze) - - Assert.assertNull( - "The $move move should be impossible for \n$initial", - cell - ) - } - - @Test(timeout = TIMEOUT) - fun testRight() { - checkMove( - RIGHT, - initial = """ - ##### - # # - # R # - # # - #####""", - expected = """ - ##### - # # - # R# - # # - #####""") - } - - @Test(timeout = TIMEOUT) - fun testLeft() { - checkMove( - LEFT, - initial = """ - ##### - # # - # R # - # # - #####""", - expected = """ - ##### - # # - #R # - # # - #####""") - } - - @Test(timeout = TIMEOUT) - fun testUp() { - checkMove( - UP, - initial = """ - ##### - # # - # R # - # # - #####""", - expected = """ - ##### - # R # - # # - # # - #####""") - } - - @Test(timeout = TIMEOUT) - fun testDown() { - checkMove( - DOWN, - initial = """ - ##### - # # - # R # - # # - #####""", - expected = """ - ##### - # # - # # - # R # - #####""") - } - - @Test(timeout = TIMEOUT) - fun testImpossibleMoves() { - listOf(RIGHT, LEFT, UP, DOWN).forEach { - checkImpossibleMove( - it, - initial = """ - ### - #R# - ###""") - } - } } \ No newline at end of file diff --git a/Object-Oriented Programming/Abstract Classes/Exercise 2/src/Task.kt b/Object-Oriented Programming/Abstract Classes/Exercise 2/src/Task.kt new file mode 100644 index 00000000..d87140f4 --- /dev/null +++ b/Object-Oriented Programming/Abstract Classes/Exercise 2/src/Task.kt @@ -0,0 +1,3 @@ +package abstractClassesExercise2 + +// type your solution here \ No newline at end of file diff --git a/Object-Oriented Programming/Abstract Classes/Exercise 2/task-info.yaml b/Object-Oriented Programming/Abstract Classes/Exercise 2/task-info.yaml new file mode 100644 index 00000000..7ad1b827 --- /dev/null +++ b/Object-Oriented Programming/Abstract Classes/Exercise 2/task-info.yaml @@ -0,0 +1,6 @@ +type: edu +files: +- name: src/Task.kt + visible: true +- name: test/Tests.kt + visible: false diff --git a/Object-Oriented Programming/Abstract Classes/Exercise 2/task.md b/Object-Oriented Programming/Abstract Classes/Exercise 2/task.md new file mode 100644 index 00000000..1cd5c47c --- /dev/null +++ b/Object-Oriented Programming/Abstract Classes/Exercise 2/task.md @@ -0,0 +1,67 @@ +## Abstract Classes (#2) + +Make an `enum` called `Note` with values `A`-`G`. Create an `abstract` class +`Instrument` that takes a `val` class argument `name: String` which holds the +name of the class. Add an `abstract` member function `play(n: Note)`. + +Now inherit `Wind`, `Percussion` and `Stringed` from `Instrument`, overriding +`play()` in each case to use `atomictest.Trace` to show the class name, then +`blow` for `Wind`, `strike` for `Percussion`, and `pluck` for `Stringed`, and +finally the `Note` being played. + +Add a function `tune()` that takes an `Instrument` parameter and plays that +`Instrument` using `Note.C`. + +In `main()`, create an `orchestra` which is a `List` containing an +instance of each type of `Instrument`. Call `tune()` for each `Instrument` in +the `orchestra`, and validate the results using `Trace`. + +```kotlin +// Abstract/AbsExercise2.kt +package abstractclasses2 +import atomictest.* + +private val trace = Trace() + +enum class Note { + A, B, C, D, E, F, G +} + +abstract class Instrument(val name: String) { + abstract fun play(n: Note) +} + +open class Wind : Instrument("Wind") { + override fun play(n: Note) { + trace("$name blow $n") + } +} + +class Percussion : Instrument("Percussion") { + override fun play(n: Note) { + trace("$name strike $n") + } +} + +class Stringed : Instrument("Stringed") { + override fun play(n: Note) { + trace("$name pluck $n") + } +} + +fun tune(i: Instrument) = i.play(Note.C) + +fun main() { + val orchestra = listOf( + Wind(), + Percussion(), + Stringed() + ) + orchestra.forEach { tune(it) } + trace eq """ + Wind blow C + Percussion strike C + Stringed pluck C + """ +} +``` \ No newline at end of file diff --git a/Object-Oriented Programming/Abstract Classes/Exercise 2/test/Tests.kt b/Object-Oriented Programming/Abstract Classes/Exercise 2/test/Tests.kt new file mode 100644 index 00000000..82c92446 --- /dev/null +++ b/Object-Oriented Programming/Abstract Classes/Exercise 2/test/Tests.kt @@ -0,0 +1,11 @@ +package abstractClassesExercise2 + +import org.junit.Assert +import org.junit.Test + +class TestAbstractClassesExercise2 { + @Test fun testSolution() { + //TODO: implement your test here + Assert.assertTrue("Tests not implemented for the task", false) + } +} \ No newline at end of file diff --git a/Object-Oriented Programming/Abstract Classes/Exercise 3/src/Task.kt b/Object-Oriented Programming/Abstract Classes/Exercise 3/src/Task.kt new file mode 100644 index 00000000..8b15cd4e --- /dev/null +++ b/Object-Oriented Programming/Abstract Classes/Exercise 3/src/Task.kt @@ -0,0 +1,3 @@ +package abstractClassesExercise3 + +// type your solution here \ No newline at end of file diff --git a/Object-Oriented Programming/Abstract Classes/Exercise 3/task-info.yaml b/Object-Oriented Programming/Abstract Classes/Exercise 3/task-info.yaml new file mode 100644 index 00000000..7ad1b827 --- /dev/null +++ b/Object-Oriented Programming/Abstract Classes/Exercise 3/task-info.yaml @@ -0,0 +1,6 @@ +type: edu +files: +- name: src/Task.kt + visible: true +- name: test/Tests.kt + visible: false diff --git a/Object-Oriented Programming/Abstract Classes/Exercise 3/task.md b/Object-Oriented Programming/Abstract Classes/Exercise 3/task.md new file mode 100644 index 00000000..d29ce401 --- /dev/null +++ b/Object-Oriented Programming/Abstract Classes/Exercise 3/task.md @@ -0,0 +1,75 @@ +## Abstract Classes (#3) + +Add classes to the previous example: `Bowed` inherits from `Stringed` and uses +`bow` instead of `plucked` in the output, while `Brass` and `Reed` inherit +from `Wind`. `Brass` and `Reed` do not override `play()`. Make the necessary +modifications to allow each class to accept a `String` argument containing the +class name. + +```kotlin +// Abstract/AbsExercise3.kt +package abstractclasses3 +import atomictest.* + +private val trace = Trace() + +enum class Note { + A, B, C, D, E, F, G +} + +abstract class Instrument(val name: String) { + abstract fun play(n: Note) +} + +open class Wind(name: String? = null) : + Instrument(name ?: "Wind") { + override fun play(n: Note) { + trace("$name blow $n") + } +} + +open class Percussion(name: String? = null) : + Instrument(name ?: "Percussion") { + override fun play(n: Note) { + trace("$name strike $n") + } +} + +open class Stringed(name: String? = null) : + Instrument(name ?: "Stringed") { + override fun play(n: Note) { + trace("$name pluck $n") + } +} + +class Bowed : Stringed("Bowed") { + override fun play(n: Note) { + trace("$name bow $n") + } +} + +class Brass : Wind("Brass") +class Reed : Wind("Reed") + +fun tune(i: Instrument) = i.play(Note.C) + +fun main() { + val orchestra = listOf( + Wind(), + Percussion(), + Stringed(), + Bowed(), + Brass(), + Reed() + ) + orchestra.forEach { tune(it) } + trace eq """ + Wind blow C + Percussion strike C + Stringed pluck C + Bowed bow C + Brass blow C + Reed blow C + """ +} +``` \ No newline at end of file diff --git a/Object-Oriented Programming/Abstract Classes/Exercise 3/test/Tests.kt b/Object-Oriented Programming/Abstract Classes/Exercise 3/test/Tests.kt new file mode 100644 index 00000000..37cb8358 --- /dev/null +++ b/Object-Oriented Programming/Abstract Classes/Exercise 3/test/Tests.kt @@ -0,0 +1,11 @@ +package abstractClassesExercise3 + +import org.junit.Assert +import org.junit.Test + +class TestAbstractClassesExercise3 { + @Test fun testSolution() { + //TODO: implement your test here + Assert.assertTrue("Tests not implemented for the task", false) + } +} \ No newline at end of file diff --git a/Object-Oriented Programming/Abstract Classes/lesson-info.yaml b/Object-Oriented Programming/Abstract Classes/lesson-info.yaml index 8da8df52..c9fb967a 100644 --- a/Object-Oriented Programming/Abstract Classes/lesson-info.yaml +++ b/Object-Oriented Programming/Abstract Classes/lesson-info.yaml @@ -1,3 +1,5 @@ content: - Examples - Exercise 1 +- Exercise 2 +- Exercise 3 diff --git a/Object-Oriented Programming/Base Class Initialization/Examples/src/Players2.kt b/Object-Oriented Programming/Base Class Initialization/Examples/src/Players2.kt deleted file mode 100644 index e2a1ada5..00000000 --- a/Object-Oriented Programming/Base Class Initialization/Examples/src/Players2.kt +++ /dev/null @@ -1,27 +0,0 @@ -// RobotExplorer2/Players2.kt -package robotexplorer2 - -/* -open class Player(val symbol: Char) { - override fun toString() = symbol.toString() -} - -class Wall : Player('#') -class Food : Player('.') -class Empty : Player('_') -class Edge : Player('/') -class EndGame : Player('!') - -class Robot(var room: Room) : Player('R') { - fun move(urge: Urge) { - room = room.doors.open(urge).enter(this) - } -} - -class Teleport( - val target: Char -) : Player('T') { - var originRoom = Room() - var targetRoom = Room() - override fun toString() = target.toString() -}*/ diff --git a/Object-Oriented Programming/Base Class Initialization/Examples/src/Room2.kt b/Object-Oriented Programming/Base Class Initialization/Examples/src/Room2.kt deleted file mode 100644 index 24e8dfc3..00000000 --- a/Object-Oriented Programming/Base Class Initialization/Examples/src/Room2.kt +++ /dev/null @@ -1,17 +0,0 @@ -// RobotExplorer2/Room2.kt -package robotexplorer2 - -/* -class Room(var player: Player = Empty()) { - val doors = Doors() - fun enter(robot: Robot): Room { - when (val p = player) { - is Wall, is Edge -> return robot.room - is Teleport -> return p.targetRoom - is EndGame -> return Room(EndGame()) - is Food -> player = Empty() // Eat food - is Empty -> {} - } - return this // Enter new room - } -}*/ diff --git a/Object-Oriented Programming/Base Class Initialization/Examples/task-info.yaml b/Object-Oriented Programming/Base Class Initialization/Examples/task-info.yaml index eacf1ebd..046bd645 100644 --- a/Object-Oriented Programming/Base Class Initialization/Examples/task-info.yaml +++ b/Object-Oriented Programming/Base Class Initialization/Examples/task-info.yaml @@ -8,14 +8,6 @@ files: visible: true - name: src/NoArgConstructor.kt visible: true -- name: src/Players2.kt - visible: true -- name: src/ExploreMaze2.kt - visible: true -- name: src/Stage2.kt - visible: true -- name: src/Room2.kt - visible: true - name: src/BCIExercise1.kt visible: true - name: src/BCIExercise2.kt diff --git a/Object-Oriented Programming/Base Class Initialization/Exercise 4/src/GameElements.kt b/Object-Oriented Programming/Base Class Initialization/Exercise 4/src/GameElements.kt deleted file mode 100644 index 7b10772b..00000000 --- a/Object-Oriented Programming/Base Class Initialization/Exercise 4/src/GameElements.kt +++ /dev/null @@ -1,41 +0,0 @@ -package baseClassInitializationExercise4 - -import atomictest.eq - -interface Maze - -interface GameElement { - val symbol: Char - val sharesCell: Boolean - - fun play(maze: Maze) -} - -open class StaticElement( - override val symbol: Char, - override val sharesCell: Boolean -) : GameElement { - override fun play(maze: Maze) { - // Default implementation: do nothing - } -} - -class Wall : StaticElement('#', sharesCell = false) - -class Food : StaticElement('.', sharesCell = true) - -fun main() { - val wall = Wall() - wall.symbol eq '#' - wall.sharesCell eq false - - val food = Food() - food.symbol eq '.' - food.sharesCell eq true - - // Wall and Food should extend StaticElement - val elements: List = listOf(wall, food) - elements.forEach { - (it is StaticElement) eq true - } -} \ No newline at end of file diff --git a/Object-Oriented Programming/Base Class Initialization/Exercise 4/task-info.yaml b/Object-Oriented Programming/Base Class Initialization/Exercise 4/task-info.yaml deleted file mode 100644 index 222cc122..00000000 --- a/Object-Oriented Programming/Base Class Initialization/Exercise 4/task-info.yaml +++ /dev/null @@ -1,35 +0,0 @@ -type: edu -files: -- name: src/GameElements.kt - visible: true - placeholders: - - offset: 380 - length: 38 - placeholder_text: |- - GameElement { - - override val symbol = '#' - - override val sharesCell = false - - override fun play(maze: Maze) { - // Default implementation: do nothing - } - } - - offset: 433 - length: 37 - placeholder_text: |- - GameElement { - - override val symbol = '.' - - override val sharesCell = true - - override fun play(maze: Maze) { - // Default implementation: do nothing - } - } -- name: test/Tests.kt - visible: false -feedback_link: | - https://docs.google.com/forms/d/e/1FAIpQLSdkaliSwYkjiV21bZl0yP-In2g5p17sAQCfaGjyHx_QYMWTiQ/viewform?usp=pp_url&entry.189755027=Object-Oriented+Programming+%2F+Base+Class+Initialization+%2F+Exercise1 diff --git a/Object-Oriented Programming/Base Class Initialization/Exercise 4/task.md b/Object-Oriented Programming/Base Class Initialization/Exercise 4/task.md deleted file mode 100644 index 4ab86f4e..00000000 --- a/Object-Oriented Programming/Base Class Initialization/Exercise 4/task.md +++ /dev/null @@ -1,14 +0,0 @@ -## Base Class Initialization (#1) - -Change the implementations of `Wall` and `Food` classes, so that they extended -the `StaticElement` class instead of implementing `GameElement` interface -directly. Pass the corresponding values for `symbol` and `sharesCell` -properties as function arguments. Note that you no longer need to provide -implementation of `play()` function: the trivial implementation is -inherited from the base class. - -The `sharesCell` property specifies whether a mobile element like `Robot` or -`Monster` can step at the same cell. For instance, a robot can be on the same -cell with food or bomb (in this case food is eaten or bomb is exploded), but it -can't share the cell with the wall. The wall occupies the whole cell and -doesn't allow any movement to this cell. \ No newline at end of file diff --git a/Object-Oriented Programming/Base Class Initialization/Exercise 4/test/Tests.kt b/Object-Oriented Programming/Base Class Initialization/Exercise 4/test/Tests.kt deleted file mode 100644 index adc31fc5..00000000 --- a/Object-Oriented Programming/Base Class Initialization/Exercise 4/test/Tests.kt +++ /dev/null @@ -1,26 +0,0 @@ -package baseClassInitializationExercise4 - -import org.junit.Assert -import org.junit.FixMethodOrder -import org.junit.Test -import org.junit.runners.MethodSorters -import util.TIMEOUT - -@FixMethodOrder(MethodSorters.NAME_ASCENDING) -class TestBaseClassInitializationExercise4 { - @Test(timeout = TIMEOUT) - fun test1Sample() { - val wall = Wall() - Assert.assertEquals("Wrong value for wall.symbol", '#', wall.symbol) - Assert.assertEquals("Wrong value for wall.sharesCell", false, wall.sharesCell) - - val food = Food() - Assert.assertEquals("Wrong value for food.symbol", '.', food.symbol) - Assert.assertEquals("Wrong value for food.sharesCell", true, food.sharesCell) - - val elements: List = listOf(wall, food) - Assert.assertTrue("Wall and Food should extend StaticElement", elements.all { - (it is StaticElement) - }) - } -} \ No newline at end of file diff --git a/Object-Oriented Programming/Base Class Initialization/lesson-info.yaml b/Object-Oriented Programming/Base Class Initialization/lesson-info.yaml index 19662b24..c9fb967a 100644 --- a/Object-Oriented Programming/Base Class Initialization/lesson-info.yaml +++ b/Object-Oriented Programming/Base Class Initialization/lesson-info.yaml @@ -3,4 +3,3 @@ content: - Exercise 1 - Exercise 2 - Exercise 3 -- Exercise 4 diff --git a/Object-Oriented Programming/Class Delegation/Examples/src/ClassDelegEx1.kt b/Object-Oriented Programming/Class Delegation/Examples/src/ClassDelegEx1.kt index 85a7d047..cb88218b 100644 --- a/Object-Oriented Programming/Class Delegation/Examples/src/ClassDelegEx1.kt +++ b/Object-Oriented Programming/Class Delegation/Examples/src/ClassDelegEx1.kt @@ -1,9 +1,42 @@ // ClassDelegation/ClassDelegEx1.kt package classdelegationex1 +import usefullibrary.* import atomictest.* private val trace = Trace() +class MyClass { + fun g() = trace("g()") + fun h() = trace("h()") +} + +fun useMyClass(mc: MyClass) { + mc.g() + mc.h() +} + +class MyClassAdaptedForLib( + val field: MyClass +) : LibType { + override fun f1() = field.h() + override fun f2() = field.g() +} + +fun adapt(mc: MyClass) = + MyClassAdaptedForLib(mc) + fun main() { - trace eq "" + val library = UsefulLibrary() + val mc = adapt(MyClass()) + library.utility1(mc) + library.utility2(mc) + useMyClass(mc.field) + trace eq """ + h() + g() + g() + h() + g() + h() + """ } \ No newline at end of file diff --git a/Object-Oriented Programming/Companion Objects/Examples/src/CompanionFactory.kt b/Object-Oriented Programming/Companion Objects/Examples/src/CompanionFactory.kt index 8a79b0d3..4f53fe4a 100644 --- a/Object-Oriented Programming/Companion Objects/Examples/src/CompanionFactory.kt +++ b/Object-Oriented Programming/Companion Objects/Examples/src/CompanionFactory.kt @@ -5,7 +5,6 @@ import atomictest.eq class Numbered2 private constructor(private val id: Int) { override fun toString(): String = "#$id" - companion object Factory { private var n = 0 fun create(size: Int): List { diff --git a/Object-Oriented Programming/Companion Objects/Examples/src/ObjectCounter.kt b/Object-Oriented Programming/Companion Objects/Examples/src/ObjectCounter.kt index 4b71aa41..0b49881d 100644 --- a/Object-Oriented Programming/Companion Objects/Examples/src/ObjectCounter.kt +++ b/Object-Oriented Programming/Companion Objects/Examples/src/ObjectCounter.kt @@ -5,7 +5,6 @@ class Numbered { companion object { private var count = 0 } - private val id = count++ override fun toString() = "#$id" } diff --git a/Object-Oriented Programming/Companion Objects/Examples/src/ObjectProperty.kt b/Object-Oriented Programming/Companion Objects/Examples/src/ObjectProperty.kt index cf2102fa..6da29067 100644 --- a/Object-Oriented Programming/Companion Objects/Examples/src/ObjectProperty.kt +++ b/Object-Oriented Programming/Companion Objects/Examples/src/ObjectProperty.kt @@ -5,7 +5,6 @@ class WithObjectProperty { companion object { private var n: Int = 0 // Only one } - fun increment(): Int { n += 1 return n diff --git a/Object-Oriented Programming/Complex Constructors/Exercise 4/src/GameElements.kt b/Object-Oriented Programming/Complex Constructors/Exercise 4/src/GameElements.kt deleted file mode 100644 index 6fbc2771..00000000 --- a/Object-Oriented Programming/Complex Constructors/Exercise 4/src/GameElements.kt +++ /dev/null @@ -1,24 +0,0 @@ -package complexConstructorsExercise4 - -interface GameElement { - val symbol: Char -} - -class Robot : GameElement { - override val symbol get() = 'R' -} - -class Wall : GameElement { - override val symbol get() = '#' -} - -class Food : GameElement { - override val symbol get() = '.' -} - -fun createGameElement(char: Char?): GameElement? = when (char) { - '#' -> Wall() - '.' -> Food() - 'R' -> Robot() - else -> null -} \ No newline at end of file diff --git a/Object-Oriented Programming/Complex Constructors/Exercise 4/src/Maze.kt b/Object-Oriented Programming/Complex Constructors/Exercise 4/src/Maze.kt deleted file mode 100644 index 0b1ee9ea..00000000 --- a/Object-Oriented Programming/Complex Constructors/Exercise 4/src/Maze.kt +++ /dev/null @@ -1,94 +0,0 @@ -package complexConstructorsExercise4 - -import atomictest.eq - -data class Cell(val x: Int, val y: Int) - -interface Maze { - val width: Int - val height: Int - fun all(): Set - fun allIn(cell: Cell): Set - fun cell(element: GameElement): Cell? - fun add(element: GameElement, cell: Cell) - fun remove(element: GameElement) -} - -class MazeImpl( - representation: String -) : Maze { - override val width: Int - override val height: Int - - private val elementMap: List>> - private val cellMap = mutableMapOf() - - init { - val lines = representation.lines() - height = lines.size - width = lines.maxBy { it.length }?.length ?: 0 - elementMap = List(height) { - List(width) { mutableSetOf() } - } - for (y in 0 until height) { - for (x in 0 until width) { - val ch = lines.getOrNull(y)?.getOrNull(x) - val element = createGameElement(ch) - if (element != null) { - add(element, Cell(x, y)) - } - } - } - } - - private fun elements(cell: Cell): MutableSet { - return elementMap[cell.y][cell.x] - } - - override fun all(): Set { - return cellMap.keys.toSet() - } - - override fun allIn(cell: Cell): Set { - return elements(cell) - } - - override fun cell(element: GameElement): Cell? { - return cellMap[element] - } - - override fun add(element: GameElement, cell: Cell) { - elements(cell) += element - cellMap[element] = cell - } - - override fun remove(element: GameElement) { - val cell = cell(element) ?: return - elements(cell) -= element - cellMap.remove(element) - } - - override fun toString() = - elementMap.joinToString("\n") { row -> - row.joinToString("") { elements -> - "${elements.lastOrNull()?.symbol ?: ' '}" - }.trimEnd() - } -} - -fun main() { - val mazeRepresentation = """ - ### - # - #R # - - #### - """.trimIndent() - val matrix = MazeImpl(mazeRepresentation) - // trim whitespaces at the end of each line - // to have equal representation - matrix - .toString().lines() - .joinToString("\n") { it.trimEnd() } eq - mazeRepresentation -} \ No newline at end of file diff --git a/Object-Oriented Programming/Complex Constructors/Exercise 4/task-info.yaml b/Object-Oriented Programming/Complex Constructors/Exercise 4/task-info.yaml deleted file mode 100644 index 0ed90427..00000000 --- a/Object-Oriented Programming/Complex Constructors/Exercise 4/task-info.yaml +++ /dev/null @@ -1,17 +0,0 @@ -type: edu -files: -- name: src/GameElements.kt - visible: true -- name: test/Tests.kt - visible: false -- name: src/Maze.kt - visible: true - placeholders: - - offset: 658 - length: 38 - placeholder_text: 0 // TODO - - offset: 789 - length: 244 - placeholder_text: // TODO -feedback_link: | - https://docs.google.com/forms/d/e/1FAIpQLSdkaliSwYkjiV21bZl0yP-In2g5p17sAQCfaGjyHx_QYMWTiQ/viewform?usp=pp_url&entry.189755027=Object-Oriented+Programming+%2F+Complex+Constructors+%2F+Exercise1 diff --git a/Object-Oriented Programming/Complex Constructors/Exercise 4/task.md b/Object-Oriented Programming/Complex Constructors/Exercise 4/task.md deleted file mode 100644 index 0862d33e..00000000 --- a/Object-Oriented Programming/Complex Constructors/Exercise 4/task.md +++ /dev/null @@ -1,13 +0,0 @@ -## Complex Constructors (#1) - -Modify the primary constructor of the `MazeImpl` class to -initialize a maze contents using only the maze representation in a string. -Calculate `width` and `height` properties based on the maze representation. -Use the auxiliary function `createGameElement()` (defined in `GameElements.kt`) -to create an element by using a given character. - -For a start, you can reuse the implementation given in the atom text. -Note, however, that only one element is stored in a cell there, and in a real -game several elements can be stored in one cell. Also, the maze representation -with empty cells at the end of lines isn't supported in the implementation -in the book. Fix this problem. \ No newline at end of file diff --git a/Object-Oriented Programming/Complex Constructors/Exercise 4/test/Tests.kt b/Object-Oriented Programming/Complex Constructors/Exercise 4/test/Tests.kt deleted file mode 100644 index 35702d1d..00000000 --- a/Object-Oriented Programming/Complex Constructors/Exercise 4/test/Tests.kt +++ /dev/null @@ -1,61 +0,0 @@ -package complexConstructorsExercise4 - -import org.junit.Assert -import org.junit.FixMethodOrder -import org.junit.Test -import org.junit.runners.MethodSorters -import util.TIMEOUT - -@FixMethodOrder(MethodSorters.NAME_ASCENDING) -class TestComplexConstructorsExercise4 { - @Test(timeout = TIMEOUT) - fun test1Sample() { - val mazeRepresentation = """ - ### - # - #R # - - #### - """.trimIndent() - - val matrix = MazeImpl(mazeRepresentation) - Assert.assertEquals("Wrong result for the sample:", mazeRepresentation, - matrix.toString().lines().joinToString("\n") { it.trimEnd() }) - } - - private fun checkMaze(width: Int, height: Int, maze: String) { - val matrix = MazeImpl(maze) - Assert.assertEquals("Wrong result for the maze:", maze, - matrix.toString().lines().joinToString("\n") { it.trimEnd() }) - } - - @Test(timeout = TIMEOUT) - fun test2() = checkMaze(4, 3, """ - - # - - """.trimIndent()) - - @Test(timeout = TIMEOUT) - fun test3() = checkMaze(4, 3, """ - #### - #R. - ## - """.trimIndent()) - - @Test(timeout = TIMEOUT) - fun test4() = checkMaze(4, 3, """ - . ## - - # R - """.trimIndent()) - - @Test(timeout = TIMEOUT) - fun test5() = checkMaze(5, 5, """ - . - R - - ## - .# - """.trimIndent()) -} \ No newline at end of file diff --git a/Object-Oriented Programming/Complex Constructors/lesson-info.yaml b/Object-Oriented Programming/Complex Constructors/lesson-info.yaml index 19662b24..c9fb967a 100644 --- a/Object-Oriented Programming/Complex Constructors/lesson-info.yaml +++ b/Object-Oriented Programming/Complex Constructors/lesson-info.yaml @@ -3,4 +3,3 @@ content: - Exercise 1 - Exercise 2 - Exercise 3 -- Exercise 4 diff --git a/Object-Oriented Programming/Composition/Exercise 1/src/Task.kt b/Object-Oriented Programming/Composition/Exercise 1/src/Task.kt new file mode 100644 index 00000000..e230084f --- /dev/null +++ b/Object-Oriented Programming/Composition/Exercise 1/src/Task.kt @@ -0,0 +1,3 @@ +package compositionExercise1 + +// type your solution here \ No newline at end of file diff --git a/Object-Oriented Programming/Composition/Exercise 1/task-info.yaml b/Object-Oriented Programming/Composition/Exercise 1/task-info.yaml new file mode 100644 index 00000000..7ad1b827 --- /dev/null +++ b/Object-Oriented Programming/Composition/Exercise 1/task-info.yaml @@ -0,0 +1,6 @@ +type: edu +files: +- name: src/Task.kt + visible: true +- name: test/Tests.kt + visible: false diff --git a/Object-Oriented Programming/Composition/Exercise 1/task.md b/Object-Oriented Programming/Composition/Exercise 1/task.md new file mode 100644 index 00000000..462b7da5 --- /dev/null +++ b/Object-Oriented Programming/Composition/Exercise 1/task.md @@ -0,0 +1,60 @@ +## Composition (#1) + +In `Car.kt`, add a `service()` member function to `Engine` and add a call to +this function in `main()`. + +```kotlin +// Composition/CompositionExercise1.kt +package compositionex1 +import atomictest.* + +private val trace = Trace() + +class Engine { + fun start() = trace("Engine start") + fun stop() = trace("Engine stop") + fun service() = trace("Engine service") +} + +class Wheel { + fun inflate(psi: Int) = + trace("Wheel inflate($psi)") +} + +class Window(val side: String) { + fun rollUp() = + trace("$side Window roll up") + fun rollDown() = + trace("$side Window roll down") +} + +class Door(val side: String) { + val window = Window(side) + fun open() = trace("$side Door open") + fun close() = trace("$side Door close") +} + +class Car { + val engine = Engine() + val wheel = List(4) { Wheel() } + // Two door: + val leftDoor = Door("left") + val rightDoor = Door("right") +} + +fun main() { + val car = Car() + car.leftDoor.open() + car.rightDoor.window.rollUp() + car.wheel[0].inflate(72) + car.engine.start() + car.engine.service() + trace eq """ + left Door open + right Window roll up + Wheel inflate(72) + Engine start + Engine service + """ +} +``` \ No newline at end of file diff --git a/Object-Oriented Programming/Composition/Exercise 1/test/Tests.kt b/Object-Oriented Programming/Composition/Exercise 1/test/Tests.kt new file mode 100644 index 00000000..e0d93e79 --- /dev/null +++ b/Object-Oriented Programming/Composition/Exercise 1/test/Tests.kt @@ -0,0 +1,11 @@ +package compositionExercise1 + +import org.junit.Assert +import org.junit.Test + +class TestCompositionExercise1 { + @Test fun testSolution() { + //TODO: implement your test here + Assert.assertTrue("Tests not implemented for the task", false) + } +} \ No newline at end of file diff --git a/Object-Oriented Programming/Composition/Exercise 2/src/Task.kt b/Object-Oriented Programming/Composition/Exercise 2/src/Task.kt new file mode 100644 index 00000000..01240c28 --- /dev/null +++ b/Object-Oriented Programming/Composition/Exercise 2/src/Task.kt @@ -0,0 +1,3 @@ +package compositionExercise2 + +// type your solution here \ No newline at end of file diff --git a/Object-Oriented Programming/Composition/Exercise 2/task-info.yaml b/Object-Oriented Programming/Composition/Exercise 2/task-info.yaml new file mode 100644 index 00000000..7ad1b827 --- /dev/null +++ b/Object-Oriented Programming/Composition/Exercise 2/task-info.yaml @@ -0,0 +1,6 @@ +type: edu +files: +- name: src/Task.kt + visible: true +- name: test/Tests.kt + visible: false diff --git a/Object-Oriented Programming/Composition/Exercise 2/task.md b/Object-Oriented Programming/Composition/Exercise 2/task.md new file mode 100644 index 00000000..4c3ed947 --- /dev/null +++ b/Object-Oriented Programming/Composition/Exercise 2/task.md @@ -0,0 +1,70 @@ +## Composition (#2) + +Modify `House3.kt` to replace all the `interface`s with classes, and add a +`name` property to each. Using the same form, add `Bedroom` and `Bathroom` +classes, and a `List` and `List` to `House`. Create a +`House` named "Our House", with `Kitchen`s called "Main" and "Guest". Add +`Bathroom`s called "Master", "Shared", and "Guest". Add `Bedroom`s called +"Master", "Son", "Daughter", and "Guest". Use `atomictest.Trace` to capture all +the class names and `name` properties as the `House` is constructed. Also +notice the order of construction. + +```kotlin +// Composition/CompositionExercise2.kt +package compositionex2 +import atomictest.* + +private val trace = Trace() + +open class Building(val name: String) { + init { trace("Building: $name") } +} + +class Kitchen(val name: String) { + init { trace("Kitchen: $name") } +} + +class Bedroom(val name: String) { + init { trace("Bedroom: $name") } +} + +class Bathroom(val name: String) { + init { trace("Bathroom: $name") } +} + +class House(name: String) : Building(name) { + val kitchens = listOf( + Kitchen("Main"), + Kitchen("Guest") + ) + val bathrooms = listOf( + Bathroom("Master"), + Bathroom("Shared"), + Bathroom("Guest") + ) + val bedrooms = listOf( + Bedroom("Master"), + Bedroom("Son"), + Bedroom("Daughter"), + Bedroom("Guest") + ) + init { trace("House: $name") } +} + +fun main() { + House("Our House") + trace eq """ + Building: Our House + Kitchen: Main + Kitchen: Guest + Bathroom: Master + Bathroom: Shared + Bathroom: Guest + Bedroom: Master + Bedroom: Son + Bedroom: Daughter + Bedroom: Guest + House: Our House + """ +} +``` \ No newline at end of file diff --git a/Object-Oriented Programming/Composition/Exercise 2/test/Tests.kt b/Object-Oriented Programming/Composition/Exercise 2/test/Tests.kt new file mode 100644 index 00000000..9cb53347 --- /dev/null +++ b/Object-Oriented Programming/Composition/Exercise 2/test/Tests.kt @@ -0,0 +1,11 @@ +package compositionExercise2 + +import org.junit.Assert +import org.junit.Test + +class TestCompositionExercise2 { + @Test fun testSolution() { + //TODO: implement your test here + Assert.assertTrue("Tests not implemented for the task", false) + } +} \ No newline at end of file diff --git a/Object-Oriented Programming/Composition/Exercise 3/src/Task.kt b/Object-Oriented Programming/Composition/Exercise 3/src/Task.kt new file mode 100644 index 00000000..70d5e2fd --- /dev/null +++ b/Object-Oriented Programming/Composition/Exercise 3/src/Task.kt @@ -0,0 +1,3 @@ +package compositionExercise3 + +// type your solution here \ No newline at end of file diff --git a/Object-Oriented Programming/Composition/Exercise 3/task-info.yaml b/Object-Oriented Programming/Composition/Exercise 3/task-info.yaml new file mode 100644 index 00000000..7ad1b827 --- /dev/null +++ b/Object-Oriented Programming/Composition/Exercise 3/task-info.yaml @@ -0,0 +1,6 @@ +type: edu +files: +- name: src/Task.kt + visible: true +- name: test/Tests.kt + visible: false diff --git a/Object-Oriented Programming/Composition/Exercise 3/task.md b/Object-Oriented Programming/Composition/Exercise 3/task.md new file mode 100644 index 00000000..6894393c --- /dev/null +++ b/Object-Oriented Programming/Composition/Exercise 3/task.md @@ -0,0 +1,102 @@ +## Composition (#3) + +The starter code provides: + +```kotlin +interface DataBase { + fun write(key: String, value: String) + fun read(key: String): String +} +``` + +The starter code also provides `class Holder(val db: DataBase)`. `Holder` uses +composition by containing a `DataBase`. `Holder` contains a `test()` function +which is used in `main()` to test three different `DataBase` classes, which +you write: + +- `NonRelational`, implemented with a `mutableListOf>()` +- `InMemory`, implemented with a `mutableMapOf()` +- `Mock`, implemented with two `String` `var`s. + +Write these classes so they pass the tests given in `main()`. + +```kotlin +// Composition/CompositionExercise3.kt +package compositionex3 +import atomictest.* + +private val trace = Trace() + +interface DataBase { + fun write(key: String, value: String) + fun read(key: String): String +} + +class NonRelational : DataBase { + private val db = + mutableListOf>() + override fun write( + key: String, value: String + ) { + db.add(Pair(key, value)) + } + override fun read(key: String) = + db.first { it.first == key }.second +} + +class InMemory : DataBase { + private val db = + mutableMapOf() + override fun write( + key: String, value: String + ) { + db[key] = value + } + override fun read(key: String) = + db[key] ?: "" +} + +class Mock : DataBase { + private var k = "" + private var v = "" + override fun write( + key: String, value: String + ) { k = key; v = value } + override fun read(key: String) = v +} + +class Holder(val db: DataBase) { + fun store(k: String, v: String) = + db.write(k, v) + fun fetch(k: String) = db.read(k) + private val data = """ + color: purple + dog: husky + art: deco + """.trimIndent().lines() + .map { it.split(": ") } + fun test() { + for(line in data) { + store(line[0], line[1]) + trace(fetch(line[0])) + } + } +} + +fun main() { + Holder(NonRelational()).test() + Holder(InMemory()).test() + Holder(Mock()).test() + trace eq """ + purple + husky + deco + purple + husky + deco + purple + husky + deco + """ +} +``` \ No newline at end of file diff --git a/Object-Oriented Programming/Composition/Exercise 3/test/Tests.kt b/Object-Oriented Programming/Composition/Exercise 3/test/Tests.kt new file mode 100644 index 00000000..20d592fb --- /dev/null +++ b/Object-Oriented Programming/Composition/Exercise 3/test/Tests.kt @@ -0,0 +1,11 @@ +package compositionExercise3 + +import org.junit.Assert +import org.junit.Test + +class TestCompositionExercise3 { + @Test fun testSolution() { + //TODO: implement your test here + Assert.assertTrue("Tests not implemented for the task", false) + } +} \ No newline at end of file diff --git a/Object-Oriented Programming/Composition/lesson-info.yaml b/Object-Oriented Programming/Composition/lesson-info.yaml index d8e63b88..c9fb967a 100644 --- a/Object-Oriented Programming/Composition/lesson-info.yaml +++ b/Object-Oriented Programming/Composition/lesson-info.yaml @@ -1,2 +1,5 @@ content: - Examples +- Exercise 1 +- Exercise 2 +- Exercise 3 diff --git a/Object-Oriented Programming/Extensibility/Examples/src/Doors3.kt b/Object-Oriented Programming/Extensibility/Examples/src/Doors3.kt deleted file mode 100644 index a66491d7..00000000 --- a/Object-Oriented Programming/Extensibility/Examples/src/Doors3.kt +++ /dev/null @@ -1,32 +0,0 @@ -// RobotExplorer3/Doors3.kt -package robotexplorer3 -import robotexplorer3.Player.* -import robotexplorer3.Urge.* - -val edge = Room(Edge()) - -class Doors { - private var north: Room = edge - private var south: Room = edge - private var east: Room = edge - private var west: Room = edge - fun open(urge: Urge): Room = - when (urge) { - North -> north - South -> south - East -> east - West -> west - } - fun connect( - row: Int, col: Int, - rooms: Map, Room> - ) { - fun link(toRow: Int, toCol: Int) = - rooms.getOrDefault( - Pair(toRow, toCol), edge) - north = link(row - 1, col) - south = link(row + 1, col) - east = link(row, col + 1) - west = link(row, col - 1) - } -} \ No newline at end of file diff --git a/Object-Oriented Programming/Base Class Initialization/Examples/src/ExploreMaze2.kt b/Object-Oriented Programming/Extensibility/Examples/src/ExploreMaze2.kt similarity index 94% rename from Object-Oriented Programming/Base Class Initialization/Examples/src/ExploreMaze2.kt rename to Object-Oriented Programming/Extensibility/Examples/src/ExploreMaze2.kt index c24d1e42..e8b15678 100644 --- a/Object-Oriented Programming/Base Class Initialization/Examples/src/ExploreMaze2.kt +++ b/Object-Oriented Programming/Extensibility/Examples/src/ExploreMaze2.kt @@ -2,7 +2,6 @@ package robotexplorer2 import robotmaze.* -/* fun main() { Stage(stringMaze).run(solution) -}*/ +} \ No newline at end of file diff --git a/Object-Oriented Programming/Extensibility/Examples/src/ExploreMaze3.kt b/Object-Oriented Programming/Extensibility/Examples/src/ExploreMaze3.kt deleted file mode 100644 index 12bc9b87..00000000 --- a/Object-Oriented Programming/Extensibility/Examples/src/ExploreMaze3.kt +++ /dev/null @@ -1,7 +0,0 @@ -// RobotExplorer3/ExploreMaze3.kt -package robotexplorer3 -import robotmaze.* - -fun main() { - Stage(stringMaze).run(solution) -} \ No newline at end of file diff --git a/Object-Oriented Programming/Extensibility/Examples/src/Players2.kt b/Object-Oriented Programming/Extensibility/Examples/src/Players2.kt new file mode 100644 index 00000000..f011f585 --- /dev/null +++ b/Object-Oriented Programming/Extensibility/Examples/src/Players2.kt @@ -0,0 +1,98 @@ +// RobotExplorer2/Players2.kt +package robotexplorer2 +import robotexplorer1.Urge + +interface Player { + val symbol: Char + val room: Room + fun id() = symbol.toString() + fun interact(robot: Robot): Room +} + +class Void() : Player { + override val symbol = '~' + override val room: Room + get() = throw IllegalAccessException() + override fun interact(robot: Robot) = + robot.room // Stay in old room +} + +class Wall(override val room: Room) : Player { + override val symbol = '#' + override fun interact(robot: Robot) = + robot.room // Stay in old room +} + +class Food(override val room: Room) : Player { + override val symbol = '.' + override fun interact(robot: Robot): Room { + robot.energy++ + room.player = Empty(room) + return room // Move into new room + } +} + +class Empty( + override val room: Room +) : Player { + override val symbol = '_' + // Move into new room: + override fun interact(robot: Robot) = room +} + +class EndGame( + override val room: Room +) : Player { + override val symbol = '!' + override fun interact(robot: Robot) = + Room(EndGame(room)) +} + +class Robot( + override var room: Room +) : Player { + override val symbol = 'R' + var energy = 0 + // Shouldn't happen: + override fun interact(robot: Robot) = + throw IllegalAccessException() + fun move(urge: Urge) { + val nextRoom = room.doors.open(urge) + room = nextRoom.player.interact(this) + } +} + +class Teleport( + val target: Char, override val room: Room +) : Player { + override val symbol = 'T' + var targetRoom = Room() + override fun id() = target.toString() + override fun interact(robot: Robot) = + targetRoom +} + +class Bomb(override val room: Room) : Player { + override val symbol = '*' + override fun interact(robot: Robot): Room { + robot.energy = 0 // Bomb erases energy + room.player = Empty(room) + return room + } +} + +fun factory(ch: Char): Room { + val room = Room() + when (ch) { + 'R' -> {} // Handled in Stage + '#' -> room.player = Wall(room) + '.' -> room.player = Food(room) + '_' -> room.player = Empty(room) + '!' -> room.player = EndGame(room) + '*' -> room.player = Bomb(room) + in 'a'..'z' -> + room.player = Teleport(ch, room) + else -> throw IllegalStateException("$ch") + } + return room +} \ No newline at end of file diff --git a/Object-Oriented Programming/Extensibility/Examples/src/Players3.kt b/Object-Oriented Programming/Extensibility/Examples/src/Players3.kt deleted file mode 100644 index 70ef5b3b..00000000 --- a/Object-Oriented Programming/Extensibility/Examples/src/Players3.kt +++ /dev/null @@ -1,63 +0,0 @@ -// RobotExplorer3/Players3.kt -package robotexplorer3 - -abstract class Player(val symbol: Char) { - override fun toString() = symbol.toString() - abstract fun - interact(robot: Robot, room: Room): Room -} - -class Wall : Player('#') { - override fun - interact(robot: Robot, room: Room) = - robot.room -} - -class Food : Player('.') { - override fun - interact(robot: Robot, room: Room): Room { - room.player = Empty() - return room - } -} - -class Empty : Player('_') { - override fun - interact(robot: Robot, room: Room) = - room -} - -class Edge : Player('/') { - override fun - interact(robot: Robot, room: Room) = - robot.room -} - -class EndGame : Player('!') { - override fun - interact(robot: Robot, room: Room) = - Room(EndGame()) -} - - -class Robot(var room: Room) : Player('R') { - override fun // Shouldn't happen - interact(robot: Robot, room: Room) = - throw IllegalAccessException() - fun move(urge: Urge) { - val nextRoom: Room = room.doors.open(urge) - room = nextRoom.player - .interact(this, nextRoom) - } -} - -class Teleport( - val target: Char -) : Player('T') { - var originRoom = Room() - var targetRoom = Room() - override fun toString() = target.toString() - override fun - interact(robot: Robot, room: Room) = - targetRoom -} \ No newline at end of file diff --git a/Object-Oriented Programming/Extensibility/Examples/src/Room2.kt b/Object-Oriented Programming/Extensibility/Examples/src/Room2.kt new file mode 100644 index 00000000..4043fdaf --- /dev/null +++ b/Object-Oriented Programming/Extensibility/Examples/src/Room2.kt @@ -0,0 +1,33 @@ +// RobotExplorer2/Room2.kt +package robotexplorer2 +import robotexplorer1.Urge +import robotexplorer1.Urge.* + +class Room(var player: Player = Void()) { + val doors = Doors() +} + +private val edge = Room() + +class Doors { + private val doors = mutableMapOf( + North to edge, + South to edge, + East to edge, + West to edge + ) + fun open(urge: Urge): Room = + doors.getOrDefault(urge, edge) + fun connect( + row: Int, col: Int, + rooms: Map, Room> + ) { + fun link(toRow: Int, toCol: Int) = + rooms.getOrDefault( + Pair(toRow, toCol), edge) + doors[North] = link(row - 1, col) + doors[South] = link(row + 1, col) + doors[East] = link(row, col + 1) + doors[West] = link(row, col - 1) + } +} \ No newline at end of file diff --git a/Object-Oriented Programming/Extensibility/Examples/src/Room3.kt b/Object-Oriented Programming/Extensibility/Examples/src/Room3.kt deleted file mode 100644 index 2e55f72b..00000000 --- a/Object-Oriented Programming/Extensibility/Examples/src/Room3.kt +++ /dev/null @@ -1,6 +0,0 @@ -// RobotExplorer3/Room3.kt -package robotexplorer3 - -class Room(var player: Player = Empty()) { - val doors = Doors() -} \ No newline at end of file diff --git a/Object-Oriented Programming/Base Class Initialization/Examples/src/Stage2.kt b/Object-Oriented Programming/Extensibility/Examples/src/Stage2.kt similarity index 56% rename from Object-Oriented Programming/Base Class Initialization/Examples/src/Stage2.kt rename to Object-Oriented Programming/Extensibility/Examples/src/Stage2.kt index 9f46a3a0..f03ce372 100644 --- a/Object-Oriented Programming/Base Class Initialization/Examples/src/Stage2.kt +++ b/Object-Oriented Programming/Extensibility/Examples/src/Stage2.kt @@ -1,36 +1,26 @@ // RobotExplorer2/Stage2.kt package robotexplorer2 +import robotexplorer1.urge -/* class Stage(val maze: String) { val robot = Robot(Room()) val rooms = mutableMapOf, Room>() - private val view = View(this) - val lines = maze.split("\n") - private fun factory(ch: Char): Room { - val room = Room() - when (ch) { - 'R' -> robot.room = room - '#' -> room.player = Wall() - '.' -> room.player = Food() - '_' -> room.player = Empty() - '/' -> room.player = Edge() - '!' -> room.player = EndGame() - else -> { - val teleport = Teleport(ch) - teleport.originRoom = room - room.player = teleport - } - } - return room + private inner class Adapt : Adapter { + override fun height() = + maze.lines().size + 3 + override fun textView() = mazeView() } - // Construct it with the 'Builder' pattern: - init { + private val view = View(Adapt()) + val lines = maze.split("\n") + init { // The 'Builder' pattern: // Step 1: Create rooms with players: lines.withIndex().forEach { (row, line) -> line.withIndex().forEach { (col, ch) -> - rooms[Pair(row, col)] = factory(ch) + val room = factory(ch) + rooms[Pair(row, col)] = room + if(ch == robot.symbol) + robot.room = room } } // Step 2: Connect the doors @@ -48,8 +38,8 @@ class Stage(val maze: String) { it.target }.zipWithNext() for((a, b) in teleportPairs) { - a.targetRoom = b.originRoom - b.targetRoom = a.originRoom + a.targetRoom = b.room + b.targetRoom = a.room } } fun run(solution: String) { @@ -61,4 +51,20 @@ class Stage(val maze: String) { view.show() } } -}*/ +} + +fun Stage.mazeView(): String { + var result = "" + var currentRow = 0 + rooms.forEach { (pair, room) -> + val row = pair.first + if (row != currentRow) { + result += "\n" + currentRow = row + } + result += if (room == robot.room) + robot.id() else room.player.id() + } + return result + + "\n\nEnergy: ${robot.energy}\n" +} \ No newline at end of file diff --git a/Object-Oriented Programming/Extensibility/Examples/src/Urge3.kt b/Object-Oriented Programming/Extensibility/Examples/src/Urge3.kt deleted file mode 100644 index 227cbb18..00000000 --- a/Object-Oriented Programming/Extensibility/Examples/src/Urge3.kt +++ /dev/null @@ -1,14 +0,0 @@ -// RobotExplorer3/Urge3.kt -package robotexplorer3 -import robotexplorer3.Urge.* - -enum class Urge { North, South, East, West } - -fun urge(urgeChar: Char): Urge = - when (urgeChar) { - 'n' -> North - 's' -> South - 'e' -> East - 'w' -> West - else -> West - } \ No newline at end of file diff --git a/Object-Oriented Programming/Extensibility/Examples/src/View2.kt b/Object-Oriented Programming/Extensibility/Examples/src/View2.kt new file mode 100644 index 00000000..54e7f5e7 --- /dev/null +++ b/Object-Oriented Programming/Extensibility/Examples/src/View2.kt @@ -0,0 +1,19 @@ +// RobotExplorer2/View2.kt +package robotexplorer2 + +interface Adapter { + fun height(): Int + fun textView(): String +} + +class View(val adapter: Adapter) { + // Start an ANSI terminal control string: + private val ansiTerm = "\u001B[" + fun clear() = + print("${ansiTerm}${adapter.height()}T") + fun show() { + print("${ansiTerm}0;0H") // Cursor home + println(adapter.textView()) + Thread.sleep(300L) // Pause + } +} \ No newline at end of file diff --git a/Object-Oriented Programming/Extensibility/Examples/src/View3.kt b/Object-Oriented Programming/Extensibility/Examples/src/View3.kt deleted file mode 100644 index 34855095..00000000 --- a/Object-Oriented Programming/Extensibility/Examples/src/View3.kt +++ /dev/null @@ -1,30 +0,0 @@ -// RobotExplorer3/View3.kt -package robotexplorer3 - -class View(private val stage: Stage) { - // Start an ANSI terminal control string: - private val ansiTerm = "\u001B[" - fun clear() { - val size = stage.maze.lines().size + 3 - print("${ansiTerm}${size}T") - } - private fun mazeView(): String { - var result = "" - var currentRow = 0 - stage.rooms.forEach { (pair, room) -> - val row = pair.first - if (row != currentRow) { - result += "\n" - currentRow = row - } - result += if (room == stage.robot.room) - "${stage.robot}" else "${room.player}" - } - return result + "\n\n\n" - } - fun show() { - print("${ansiTerm}0;0H") // Cursor home - println(mazeView()) - Thread.sleep(300L) // Pause - } -} \ No newline at end of file diff --git a/Object-Oriented Programming/Extensibility/Examples/task-info.yaml b/Object-Oriented Programming/Extensibility/Examples/task-info.yaml index 285760a5..dcd494a2 100644 --- a/Object-Oriented Programming/Extensibility/Examples/task-info.yaml +++ b/Object-Oriented Programming/Extensibility/Examples/task-info.yaml @@ -1,18 +1,14 @@ type: theory files: -- name: src/Players3.kt +- name: src/Players2.kt visible: true -- name: src/Room3.kt +- name: src/ExploreMaze2.kt visible: true -- name: src/Stage3.kt +- name: src/Room2.kt visible: true -- name: src/ExploreMaze3.kt +- name: src/Stage2.kt visible: true -- name: src/Urge3.kt - visible: true -- name: src/Doors3.kt - visible: true -- name: src/View3.kt +- name: src/View2.kt visible: true - name: src/ExtensibilityEx1.kt visible: true diff --git a/Object-Oriented Programming/Inheritance & Extensions/Exercise 1/src/Task.kt b/Object-Oriented Programming/Inheritance & Extensions/Exercise 1/src/Task.kt new file mode 100644 index 00000000..ef9a20af --- /dev/null +++ b/Object-Oriented Programming/Inheritance & Extensions/Exercise 1/src/Task.kt @@ -0,0 +1,3 @@ +package inheritanceAndExtensionsExercise1 + +// type your solution here \ No newline at end of file diff --git a/Object-Oriented Programming/Inheritance & Extensions/Exercise 1/task-info.yaml b/Object-Oriented Programming/Inheritance & Extensions/Exercise 1/task-info.yaml new file mode 100644 index 00000000..7ad1b827 --- /dev/null +++ b/Object-Oriented Programming/Inheritance & Extensions/Exercise 1/task-info.yaml @@ -0,0 +1,6 @@ +type: edu +files: +- name: src/Task.kt + visible: true +- name: test/Tests.kt + visible: false diff --git a/Object-Oriented Programming/Inheritance & Extensions/Exercise 1/task.md b/Object-Oriented Programming/Inheritance & Extensions/Exercise 1/task.md new file mode 100644 index 00000000..e15abb63 --- /dev/null +++ b/Object-Oriented Programming/Inheritance & Extensions/Exercise 1/task.md @@ -0,0 +1,94 @@ +## Inheritance & Extensions (#1) + +Following `AdjustTemp.kt`, add two extension functions `openWindow()` and +`fan()` as ways of cooling. Add a class `DeltaTemperature2` where the extension +functions are instead member functions, and an overloaded `adjust()` function +which takes a `DeltaTemperature2`. Which approach seems better, or are they +about the same? + +```kotlin +// InheritanceExtensions/InhExtensionsEx1.kt +package inheritanceextensionsex1 + +import atomictest.* + +val trace = Trace() + +class DeltaTemperature( + val current: Double, + val target: Double +) + +fun DeltaTemperature.heat() { + if (current < target) + trace("heating to $target ") +} + +fun DeltaTemperature.cool() { + if (current > target) + trace("cooling to $target ") +} + +fun DeltaTemperature.openWindow() { + if (current > target) + trace("cooling to $target") +} + +fun DeltaTemperature.fan() { + if (current > target) + trace("cooling to $target ") +} + +class DeltaTemperature2( + val current: Double, + val target: Double +) { + fun heat() { + if (current < target) + trace("heating to $target ") + } + fun cool() { + if (current > target) + trace("cooling to $target ") + } + fun openWindow() { + if (current > target) + trace("cooling to $target") + } + fun fan() { + if (current > target) + trace("cooling to $target ") + } +} + +fun adjust(deltaT: DeltaTemperature) { + deltaT.heat() + deltaT.cool() + deltaT.openWindow() + deltaT.fan() +} + +fun adjust(deltaT: DeltaTemperature2) { + deltaT.heat() + deltaT.cool() + deltaT.openWindow() + deltaT.fan() +} + +fun main() { + adjust(DeltaTemperature(60.0, 70.0)) + adjust(DeltaTemperature(80.0, 60.0)) + adjust(DeltaTemperature2(60.0, 70.0)) + adjust(DeltaTemperature2(80.0, 60.0)) + trace eq """ + heating to 70.0 + cooling to 60.0 + cooling to 60.0 + cooling to 60.0 + heating to 70.0 + cooling to 60.0 + cooling to 60.0 + cooling to 60.0 + """ +} +``` \ No newline at end of file diff --git a/Object-Oriented Programming/Inheritance & Extensions/Exercise 1/test/Tests.kt b/Object-Oriented Programming/Inheritance & Extensions/Exercise 1/test/Tests.kt new file mode 100644 index 00000000..7dfa45b1 --- /dev/null +++ b/Object-Oriented Programming/Inheritance & Extensions/Exercise 1/test/Tests.kt @@ -0,0 +1,11 @@ +package inheritanceAndExtensionsExercise1 + +import org.junit.Assert +import org.junit.Test + +class TestInheritanceAndExtensionsExercise1 { + @Test fun testSolution() { + //TODO: implement your test here + Assert.assertTrue("Tests not implemented for the task", false) + } +} \ No newline at end of file diff --git a/Object-Oriented Programming/Inheritance & Extensions/Exercise 2/src/Task.kt b/Object-Oriented Programming/Inheritance & Extensions/Exercise 2/src/Task.kt new file mode 100644 index 00000000..bab5c65b --- /dev/null +++ b/Object-Oriented Programming/Inheritance & Extensions/Exercise 2/src/Task.kt @@ -0,0 +1,3 @@ +package inheritanceAndExtensionsExercise2 + +// type your solution here \ No newline at end of file diff --git a/Object-Oriented Programming/Inheritance & Extensions/Exercise 2/task-info.yaml b/Object-Oriented Programming/Inheritance & Extensions/Exercise 2/task-info.yaml new file mode 100644 index 00000000..7ad1b827 --- /dev/null +++ b/Object-Oriented Programming/Inheritance & Extensions/Exercise 2/task-info.yaml @@ -0,0 +1,6 @@ +type: edu +files: +- name: src/Task.kt + visible: true +- name: test/Tests.kt + visible: false diff --git a/Object-Oriented Programming/Inheritance & Extensions/Exercise 2/task.md b/Object-Oriented Programming/Inheritance & Extensions/Exercise 2/task.md new file mode 100644 index 00000000..75243e56 --- /dev/null +++ b/Object-Oriented Programming/Inheritance & Extensions/Exercise 2/task.md @@ -0,0 +1,81 @@ +## Inheritance & Extensions (#2) + +Refactor `BatteryPet2.kt` to improve the design: + +- In `Pet`, add an open function `settle()` which calls `trace("")` +- In `Pet`, add an open function `feed()` which calls `energy.replenish()` +- In `Dog`, override `settle()` to call `trace("Sitting...") +- You no longer need `Dog.sit()` +- Change `playWithDog(dog: Dog)` to `playWithPet(pet: Pet)` +- Add a `CatFood` type of `Energy`, and define the associated `Cat` class +- In `main()`, test all types of `Pet` + +```kotlin +// InheritanceExtensions/InhExtensionsEx2.kt +package inheritanceextensionsex2 +import atomictest.* + +private val trace = Trace() + +interface Energy { + fun replenish() = trace("Fill Bowl") +} + +open class Pet(open val energy: Energy) { + open fun speak() = trace("") + open fun settle() = trace("") + open fun feed() = energy.replenish() +} + +class DogFood : Energy + +open class Dog : Pet(DogFood()) { + override fun speak() = trace("Bark!") + override fun settle() = trace("Sitting...") +} + +class CatFood : Energy + +open class Cat : Pet(CatFood()) { + override fun speak() = trace("Meow!") + override fun settle() = + trace("In my basket...") +} + +class Batteries : Energy { + override fun replenish() = + trace("Change batteries") +} + +class ToyDog: Dog() { + override val energy = Batteries() +} + +fun play(pet: Pet) = pet.speak() + +fun playWithPet(pet: Pet) { + play(pet) + pet.settle() + pet.energy.replenish() +} + +fun main() { + val dog1 = Dog() + val dog2 = ToyDog() + val cat = Cat() + playWithPet(dog1) + playWithPet(dog2) + playWithPet(cat) + trace eq """ + Bark! + Sitting... + Fill Bowl + Bark! + Sitting... + Change batteries + Meow! + In my basket... + Fill Bowl + """ +} +``` \ No newline at end of file diff --git a/Object-Oriented Programming/Inheritance & Extensions/Exercise 2/test/Tests.kt b/Object-Oriented Programming/Inheritance & Extensions/Exercise 2/test/Tests.kt new file mode 100644 index 00000000..234be73c --- /dev/null +++ b/Object-Oriented Programming/Inheritance & Extensions/Exercise 2/test/Tests.kt @@ -0,0 +1,11 @@ +package inheritanceAndExtensionsExercise2 + +import org.junit.Assert +import org.junit.Test + +class TestInheritanceAndExtensionsExercise2 { + @Test fun testSolution() { + //TODO: implement your test here + Assert.assertTrue("Tests not implemented for the task", false) + } +} \ No newline at end of file diff --git a/Object-Oriented Programming/Inheritance & Extensions/Exercise 3/src/Task.kt b/Object-Oriented Programming/Inheritance & Extensions/Exercise 3/src/Task.kt new file mode 100644 index 00000000..606f022a --- /dev/null +++ b/Object-Oriented Programming/Inheritance & Extensions/Exercise 3/src/Task.kt @@ -0,0 +1,3 @@ +package inheritanceAndExtensionsExercise3 + +// type your solution here \ No newline at end of file diff --git a/Object-Oriented Programming/Inheritance & Extensions/Exercise 3/task-info.yaml b/Object-Oriented Programming/Inheritance & Extensions/Exercise 3/task-info.yaml new file mode 100644 index 00000000..7ad1b827 --- /dev/null +++ b/Object-Oriented Programming/Inheritance & Extensions/Exercise 3/task-info.yaml @@ -0,0 +1,6 @@ +type: edu +files: +- name: src/Task.kt + visible: true +- name: test/Tests.kt + visible: false diff --git a/Object-Oriented Programming/Inheritance & Extensions/Exercise 3/task.md b/Object-Oriented Programming/Inheritance & Extensions/Exercise 3/task.md new file mode 100644 index 00000000..6678de55 --- /dev/null +++ b/Object-Oriented Programming/Inheritance & Extensions/Exercise 3/task.md @@ -0,0 +1,52 @@ +## Inheritance & Extensions (#3) + +Starting with `Adapter.kt` and `ComposeAdapter.kt`, create a function which +dynamically adapts an object, accepting a `MyClass` and returning a +`MyClassAdaptedForLib`. Is it possible to use the inheritance approach in +`Adapter.kt`, or are you forced to use composition? (We'll revisit this issue +in [Class Delegation]). + +```kotlin +// InheritanceExtensions/InhExtensionsEx3.kt +package inheritanceextensionsex3 +import usefullibrary.* +import atomictest.* + +private val trace = Trace() + +class MyClass { + fun g() = trace("g()") + fun h() = trace("h()") +} + +fun useMyClass(mc: MyClass) { + mc.g() + mc.h() +} + +class MyClassAdaptedForLib( + val field: MyClass +) : LibType { + override fun f1() = field.h() + override fun f2() = field.g() +} + +fun adapt(mc: MyClass) = + MyClassAdaptedForLib(mc) + +fun main() { + val library = UsefulLibrary() + val mc = adapt(MyClass()) + library.utility1(mc) + library.utility2(mc) + useMyClass(mc.field) + trace eq """ + h() + g() + g() + h() + g() + h() + """ +} +``` \ No newline at end of file diff --git a/Object-Oriented Programming/Inheritance & Extensions/Exercise 3/test/Tests.kt b/Object-Oriented Programming/Inheritance & Extensions/Exercise 3/test/Tests.kt new file mode 100644 index 00000000..06c6bc65 --- /dev/null +++ b/Object-Oriented Programming/Inheritance & Extensions/Exercise 3/test/Tests.kt @@ -0,0 +1,11 @@ +package inheritanceAndExtensionsExercise3 + +import org.junit.Assert +import org.junit.Test + +class TestInheritanceAndExtensionsExercise3 { + @Test fun testSolution() { + //TODO: implement your test here + Assert.assertTrue("Tests not implemented for the task", false) + } +} \ No newline at end of file diff --git a/Object-Oriented Programming/Inheritance & Extensions/lesson-info.yaml b/Object-Oriented Programming/Inheritance & Extensions/lesson-info.yaml index d8e63b88..c9fb967a 100644 --- a/Object-Oriented Programming/Inheritance & Extensions/lesson-info.yaml +++ b/Object-Oriented Programming/Inheritance & Extensions/lesson-info.yaml @@ -1,2 +1,5 @@ content: - Examples +- Exercise 1 +- Exercise 2 +- Exercise 3 diff --git a/Object-Oriented Programming/Inheritance/Exercise 4/src/Bomb.kt b/Object-Oriented Programming/Inheritance/Exercise 4/src/Bomb.kt deleted file mode 100644 index 04655888..00000000 --- a/Object-Oriented Programming/Inheritance/Exercise 4/src/Bomb.kt +++ /dev/null @@ -1,67 +0,0 @@ -package inheritanceExercise4 - -import atomictest.eq -import kotlin.math.pow -import kotlin.math.sqrt - -class Bomb( - private val diameter: Int -) : StaticElement() { - override val symbol get() = '0' + diameter - - override fun play(maze: Maze) { - val bombCell = maze.cell(this) ?: return - maze.all().forEach { element -> - val cell = maze.cell(element) - if (cell != null && - isCloseToBomb(cell, bombCell)) { - maze.remove(element) - } - } - } - - private fun isCloseToBomb(cell: Cell, bombCell: Cell) = - 2 * distance(cell, bombCell) < diameter + 0.0000001 - - private fun distance(from: Cell, to: Cell): Double { - fun sqr(i: Int) = i.toDouble().pow(2) - return sqrt(sqr(from.x - to.x) + sqr(from.y - to.y)) - } -} - -fun main() { - val representation = """ - ########### - #.........# - #.........# - #.........# - #....4....# - #.........# - #.........# - #.........# - ########### - """.trimIndent() - val maze = MazeImpl(representation) - maze.toString() eq representation - - val bombCell = Cell(x = 5, y = 4) - // Adding a robot to the 'bomb' cell should trigger the bomb - val robot = Robot() - maze.add(robot, bombCell) - - val bomb = maze.allIn(bombCell) - .filterIsInstance().single() - bomb.play(maze) - - maze.toString() eq """ - ########### - #.........# - #.... ....# - #... ...# - #.. ..# - #... ...# - #.... ....# - #.........# - ########### - """.trimIndent() -} \ No newline at end of file diff --git a/Object-Oriented Programming/Inheritance/Exercise 4/src/GameElements.kt b/Object-Oriented Programming/Inheritance/Exercise 4/src/GameElements.kt deleted file mode 100644 index 09dbd579..00000000 --- a/Object-Oriented Programming/Inheritance/Exercise 4/src/GameElements.kt +++ /dev/null @@ -1,49 +0,0 @@ -package inheritanceExercise4 - -interface GameElement { - val symbol: Char - fun play(maze: Maze) -} - -open class StaticElement : GameElement { - override fun play(maze: Maze) { - // Default implementation: do nothing - } - - override val symbol: Char - get() = ' ' -} - -class Wall : StaticElement() { - override val symbol get() = '#' -} - -class Food : StaticElement() { - override val symbol get() = '.' -} - -class Robot : GameElement { - private var eatenFoodItems: Int = 0 - - override val symbol: Char - get() = 'R' - - override fun play(maze: Maze) { - val cell = maze.cell(this) ?: return - val cellElements = maze.allIn(cell) - cellElements - .filterIsInstance() - .forEach { food -> - eatenFoodItems++ - maze.remove(food) - } - } -} - -fun createGameElement(char: Char?): GameElement? = when (char) { - '#' -> Wall() - '.' -> Food() - 'R' -> Robot() - in '0'..'9' -> Bomb(char!! - '0') - else -> null -} \ No newline at end of file diff --git a/Object-Oriented Programming/Inheritance/Exercise 4/src/Maze.kt b/Object-Oriented Programming/Inheritance/Exercise 4/src/Maze.kt deleted file mode 100644 index 79614adc..00000000 --- a/Object-Oriented Programming/Inheritance/Exercise 4/src/Maze.kt +++ /dev/null @@ -1,75 +0,0 @@ -package inheritanceExercise4 - -data class Cell(val x: Int, val y: Int) - -interface Maze { - val width: Int - val height: Int - fun all(): Set - fun allIn(cell: Cell): Set - fun cell(element: GameElement): Cell? - fun add(element: GameElement, cell: Cell) - fun remove(element: GameElement) -} - -class MazeImpl( - representation: String -) : Maze { - override val width: Int - override val height: Int - - private val elementMap: List>> - private val cellMap = mutableMapOf() - - init { - val lines = representation.lines() - height = lines.size - width = lines.maxBy { it.length }?.length ?: 0 - elementMap = List(height) { - List(width) { mutableSetOf() } - } - for (y in 0 until height) { - for (x in 0 until width) { - val ch = lines.getOrNull(y)?.getOrNull(x) - val element = createGameElement(ch) - if (element != null) { - add(element, Cell(x, y)) - } - } - } - } - - private fun elements(cell: Cell): MutableSet { - return elementMap[cell.y][cell.x] - } - - override fun all(): Set { - return cellMap.keys.toSet() - } - - override fun allIn(cell: Cell): Set { - return elements(cell) - } - - override fun cell(element: GameElement): Cell? { - return cellMap[element] - } - - override fun add(element: GameElement, cell: Cell) { - elements(cell) += element - cellMap[element] = cell - } - - override fun remove(element: GameElement) { - val cell = cell(element) ?: return - elements(cell) -= element - cellMap.remove(element) - } - - override fun toString() = - elementMap.joinToString("\n") { row -> - row.joinToString("") { elements -> - "${elements.lastOrNull()?.symbol ?: ' '}" - }.trimEnd() - } -} \ No newline at end of file diff --git a/Object-Oriented Programming/Inheritance/Exercise 4/task-info.yaml b/Object-Oriented Programming/Inheritance/Exercise 4/task-info.yaml deleted file mode 100644 index 4d1f1b7c..00000000 --- a/Object-Oriented Programming/Inheritance/Exercise 4/task-info.yaml +++ /dev/null @@ -1,16 +0,0 @@ -type: edu -files: -- name: src/Bomb.kt - visible: true - placeholders: - - offset: 245 - length: 222 - placeholder_text: TODO() -- name: src/GameElements.kt - visible: true -- name: src/Maze.kt - visible: true -- name: test/Tests.kt - visible: false -feedback_link: | - https://docs.google.com/forms/d/e/1FAIpQLSdkaliSwYkjiV21bZl0yP-In2g5p17sAQCfaGjyHx_QYMWTiQ/viewform?usp=pp_url&entry.189755027=Object-Oriented+Programming+%2F+Inheritance+%2F+Exercise1 diff --git a/Object-Oriented Programming/Inheritance/Exercise 4/task.md b/Object-Oriented Programming/Inheritance/Exercise 4/task.md deleted file mode 100644 index 2756138d..00000000 --- a/Object-Oriented Programming/Inheritance/Exercise 4/task.md +++ /dev/null @@ -1,8 +0,0 @@ -## Inheritance (#1) - -Implement a more powerful version of the bomb: the one with a diameter of -the explosion. All the cells that are close enough to the bomb must be destroyed. -The bomb should explode when any mobile element steps into the same cell. - -Use the provided auxiliary function `isCloseToBomb()` to check whether -an element is close enough to the bomb to be destroyed. \ No newline at end of file diff --git a/Object-Oriented Programming/Inheritance/Exercise 4/test/Tests.kt b/Object-Oriented Programming/Inheritance/Exercise 4/test/Tests.kt deleted file mode 100644 index da8f19ed..00000000 --- a/Object-Oriented Programming/Inheritance/Exercise 4/test/Tests.kt +++ /dev/null @@ -1,178 +0,0 @@ -package inheritanceExercise4 - -import org.junit.Assert -import org.junit.FixMethodOrder -import org.junit.Test -import org.junit.runners.MethodSorters -import util.TIMEOUT - -@FixMethodOrder(MethodSorters.NAME_ASCENDING) -class TestInheritanceExercise4 { - private fun checkMaze( - bombCell: Cell, - mazeRepresentation: String, - afterDestroy: String, - prefixMessage: String? = null - ) { - val maze = MazeImpl(mazeRepresentation) - val robot = Robot() - maze.add(robot, bombCell) - val bomb = maze.allIn(bombCell) - .filterIsInstance().single() - bomb.play(maze) - - Assert.assertEquals("${prefixMessage ?: ""} " + - "Wrong result after exploding a bomb for the following maze:\n$mazeRepresentation", - afterDestroy, - maze.toString()) - } - - @Test(timeout = TIMEOUT) - fun test1Sample() = checkMaze(Cell(5, 4), - """ - ########### - #.........# - #.........# - #.........# - #....4....# - #.........# - #.........# - #.........# - ########### - """.trimIndent(), - """ - ########### - #.........# - #.... ....# - #... ...# - #.. ..# - #... ...# - #.... ....# - #.........# - ########### - """.trimIndent() - ) - - @Test(timeout = TIMEOUT) - fun test2() = checkMaze(Cell(5, 4), - """ - ########### - #.........# - #.........# - #.........# - #....1....# - #.........# - #.........# - #.........# - ########### - """.trimIndent(), - """ - ########### - #.........# - #.........# - #.........# - #.... ....# - #.........# - #.........# - #.........# - ########### - """.trimIndent() - ) - - @Test(timeout = TIMEOUT) - fun test3() = checkMaze(Cell(5, 4), - """ - ########### - #.........# - #.........# - #.........# - #....2....# - #.........# - #.........# - #.........# - ########### - """.trimIndent(), - """ - ########### - #.........# - #.........# - #.... ....# - #... ...# - #.... ....# - #.........# - #.........# - ########### - """.trimIndent() - ) - - @Test(timeout = TIMEOUT) - fun test4() = checkMaze(Cell(5, 4), - """ - ########### - #.........# - #.........# - #.........# - #....3....# - #.........# - #.........# - #.........# - ########### - """.trimIndent(), - """ - ########### - #.........# - #.........# - #... ...# - #... ...# - #... ...# - #.........# - #.........# - ########### - """.trimIndent() - ) - - @Test(timeout = TIMEOUT) - fun test5() = checkMaze(Cell(5, 4), - """ - ########### - #.........# - #.........# - #.........# - #....5....# - #.........# - #.........# - #.........# - ########### - """.trimIndent(), - """ - ########### - #.........# - #... ...# - #.. ..# - #.. ..# - #.. ..# - #... ...# - #.........# - ########### - """.trimIndent() - ) - - @Test(timeout = TIMEOUT) - fun test6() = checkMaze(Cell(2, 2), - """ - ##### - ##### - # 3## - ##### - ##### - """.trimIndent(), - """ - ##### - # # - # # - # # - ##### - """.trimIndent(), - "Walls should also be exploded" - ) -} \ No newline at end of file diff --git a/Object-Oriented Programming/Inheritance/lesson-info.yaml b/Object-Oriented Programming/Inheritance/lesson-info.yaml index 19662b24..c9fb967a 100644 --- a/Object-Oriented Programming/Inheritance/lesson-info.yaml +++ b/Object-Oriented Programming/Inheritance/lesson-info.yaml @@ -3,4 +3,3 @@ content: - Exercise 1 - Exercise 2 - Exercise 3 -- Exercise 4 diff --git a/Object-Oriented Programming/Interfaces/Exercise 2/task.md b/Object-Oriented Programming/Interfaces/Exercise 2/task.md index 48b96642..486fbd5a 100644 --- a/Object-Oriented Programming/Interfaces/Exercise 2/task.md +++ b/Object-Oriented Programming/Interfaces/Exercise 2/task.md @@ -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!"`. Create a `List` -containing all three types of `Pet`. Iterate through the `List` and call -`speak()` for each `Pet`. \ No newline at end of file +produces `"Meow!"` and `Hamster` which produces `"Squeak!"`. Create a +`List` containing all three types of `Pet`. Iterate through the `List` and +call `speak()` for each `Pet`. \ No newline at end of file diff --git a/Object-Oriented Programming/Interfaces/Exercise 3/task.md b/Object-Oriented Programming/Interfaces/Exercise 3/task.md index 79c78851..dc50f596 100644 --- a/Object-Oriented Programming/Interfaces/Exercise 3/task.md +++ b/Object-Oriented Programming/Interfaces/Exercise 3/task.md @@ -1,6 +1,6 @@ ## Interfaces (#3) -Modify the previous exercise so that each `Pet` contains a `String` -`description` property, which produces `dog`, `cat`, and `hamster`, -appropriately. Use this property in `speak()` for each class. For example, -`Dog.speak()` produces `"dog Bark!"`. \ No newline at end of file +Modify the previous exercise so each `Pet` contains a `String` `description` +property, which produces `dog`, `cat`, and `hamster`, appropriately. Use this +property in `speak()` for each class. For example, `Dog.speak()` produces `"dog +Bark!"`. \ No newline at end of file diff --git a/Object-Oriented Programming/Interfaces/Exercise 4/src/GameElements.kt b/Object-Oriented Programming/Interfaces/Exercise 4/src/GameElements.kt deleted file mode 100644 index f32862ae..00000000 --- a/Object-Oriented Programming/Interfaces/Exercise 4/src/GameElements.kt +++ /dev/null @@ -1,17 +0,0 @@ -package interfacesExercise4 - -interface GameElement { - val symbol: Char -} - -class Robot : GameElement { - override val symbol get() = 'R' -} - -class Wall : GameElement { - override val symbol get() = '#' -} - -class Food : GameElement { - override val symbol get() = '.' -} \ No newline at end of file diff --git a/Object-Oriented Programming/Interfaces/Exercise 4/src/GameMatrix.kt b/Object-Oriented Programming/Interfaces/Exercise 4/src/GameMatrix.kt deleted file mode 100644 index 1bd1d692..00000000 --- a/Object-Oriented Programming/Interfaces/Exercise 4/src/GameMatrix.kt +++ /dev/null @@ -1,91 +0,0 @@ -package interfacesExercise4 - -import atomictest.eq - -data class Cell(val x: Int, val y: Int) - -interface Maze { - val width: Int - val height: Int - fun all(): Set - fun allIn(cell: Cell): Set - fun cell(element: GameElement): Cell? - fun add(element: GameElement, cell: Cell) - fun remove(element: GameElement) -} - -class MazeImpl( - override val width: Int, - override val height: Int -) : Maze { - private val elementMap = List(height) { - List(width) { mutableSetOf() } - } - private val cellMap = mutableMapOf() - - private fun elementsIn(cell: Cell): MutableSet { - return elementMap[cell.y][cell.x] - } - - override fun all(): Set { - return cellMap.keys.toSet() - } - - override fun allIn(cell: Cell): Set { - return elementsIn(cell) - } - - override fun cell(element: GameElement): Cell? { - return cellMap[element] - } - - override fun add(element: GameElement, cell: Cell) { - elementsIn(cell) += element - cellMap[element] = cell - } - - override fun remove(element: GameElement) { - val cell = cell(element) ?: return - elementsIn(cell) -= element - cellMap.remove(element) - } - - override fun toString() = - elementMap.joinToString("\n") { row -> - row.joinToString("") { elements -> - // As we can't display several elements on the one cell - // as one character, for simplicity - // we display only the last element - "${elements.lastOrNull()?.symbol ?: ' '}" - }.trimEnd() - } -} - -fun main() { - val maze = MazeImpl(width = 4, height = 5) - maze.add(Robot(), Cell(x = 1, y = 2)) - - val food = Food() - maze.add(food, Cell(x = 2, y = 3)) - for (y in 0..4) { - maze.add(Wall(), Cell(0, y)) - maze.add(Wall(), Cell(3, y)) - } - for (x in 1..2) { - maze.add(Wall(), Cell(x, 0)) - maze.add(Wall(), Cell(x, 4)) - } - maze.toString() eq - """ - #### - # # - #R # - # .# - #### - """.trimIndent() - maze.allIn(Cell(1, 2)).singleOrNull()?.symbol eq 'R' - maze.allIn(Cell(2, 3)).singleOrNull()?.symbol eq '.' - - maze.remove(food) - maze.allIn(Cell(2, 3)) eq emptySet() -} \ No newline at end of file diff --git a/Object-Oriented Programming/Interfaces/Exercise 4/task-info.yaml b/Object-Oriented Programming/Interfaces/Exercise 4/task-info.yaml deleted file mode 100644 index 197bf295..00000000 --- a/Object-Oriented Programming/Interfaces/Exercise 4/task-info.yaml +++ /dev/null @@ -1,17 +0,0 @@ -type: edu -files: -- name: src/GameMatrix.kt - visible: true - placeholders: - - offset: 986 - length: 55 - placeholder_text: TODO() - - offset: 1097 - length: 94 - placeholder_text: TODO() -- name: src/GameElements.kt - visible: true -- name: test/Tests.kt - visible: false -feedback_link: | - https://docs.google.com/forms/d/e/1FAIpQLSdkaliSwYkjiV21bZl0yP-In2g5p17sAQCfaGjyHx_QYMWTiQ/viewform?usp=pp_url&entry.189755027=Object-Oriented+Programming+%2F+Interfaces+%2F+Exercise1 diff --git a/Object-Oriented Programming/Interfaces/Exercise 4/task.md b/Object-Oriented Programming/Interfaces/Exercise 4/task.md deleted file mode 100644 index 0db2630e..00000000 --- a/Object-Oriented Programming/Interfaces/Exercise 4/task.md +++ /dev/null @@ -1,12 +0,0 @@ -## Interfaces (#1) - -The `MazeImpl` class implements the `Maze` interface. It stores game elements -in a "table" of the size `height * width`, which is implemented as a `List` of -`List`s, where the outer `List` is of `height` size and each inner `List` is of -`width` size. Each cell holds a set of `GameElement`s. `MazeImpl` also keeps a -record of the `Cell`s of all the elements by storing a `cellMap` `Map` -which has `GameElement` keys and `Cell` values. - -Your task is to implement the `add(GameElement, Cell)` and -`remove(GameElement, Cell)` functions that add and remove `GameElement`s -at a given `Cell`. \ No newline at end of file diff --git a/Object-Oriented Programming/Interfaces/Exercise 4/test/Tests.kt b/Object-Oriented Programming/Interfaces/Exercise 4/test/Tests.kt deleted file mode 100644 index 6ea231e9..00000000 --- a/Object-Oriented Programming/Interfaces/Exercise 4/test/Tests.kt +++ /dev/null @@ -1,92 +0,0 @@ -package interfacesExercise4 - -import org.junit.Assert -import org.junit.FixMethodOrder -import org.junit.Test -import org.junit.runners.MethodSorters -import util.TIMEOUT - -@FixMethodOrder(MethodSorters.NAME_ASCENDING) -class TestInterfacesExercise4 { - @Test(timeout = TIMEOUT) - fun test1Sample() { - val matrix = MazeImpl(width = 4, height = 5) - matrix.add(Robot(), Cell(x = 1, y = 2)) - matrix.add(Food(), Cell(x = 2, y = 3)) - for (i in 0..4) { - matrix.add(Wall(), Cell(0, i)) - matrix.add(Wall(), Cell(3, i)) - } - for (i in 1..2) { - matrix.add(Wall(), Cell(i, 0)) - matrix.add(Wall(), Cell(i, 4)) - } - Assert.assertEquals("Wrong result for the sample:", - """ - #### - # # - #R # - # .# - #### - """.trimIndent(), - matrix.toString()) - Assert.assertEquals("Wrong result for the sample. In Cell(1, 2) should be Robot", - 'R', matrix.allIn(Cell(1, 2)).singleOrNull()?.symbol) - } - - private fun createGameElement(char: Char): GameElement? = when (char) { - '#' -> Wall() - '.' -> Food() - 'R' -> Robot() - else -> null - } - - private fun checkMaze(maze: String) { - val lines = maze.lines().filter { it.isNotEmpty() } - val height = lines.size - val lengths = lines.map { it.length } - val width = lengths.first() - - val matrix = MazeImpl(width, height) - for (y in 0 until height) { - for (x in 0 until width) { - val ch = lines[y][x] - val element = createGameElement(ch) - if (element != null) { - matrix.add(element, Cell(x, y)) - } - } - } - Assert.assertEquals("Wrong result for the maze:", - maze, - matrix.toString()) - } - - @Test(timeout = TIMEOUT) - fun test2() = checkMaze(""" - #### - #### - #### - """.trimIndent()) - - @Test(timeout = TIMEOUT) - fun test3() = checkMaze(""" - #### - #R.# - #### - """.trimIndent()) - - @Test(timeout = TIMEOUT) - fun test4() = checkMaze(""" - . ## - # - # R - """.trimIndent()) - - @Test(timeout = TIMEOUT) - fun test5() = checkMaze(""" - .... - .... - ...R - """.trimIndent()) -} \ No newline at end of file diff --git a/Object-Oriented Programming/Interfaces/lesson-info.yaml b/Object-Oriented Programming/Interfaces/lesson-info.yaml index 19662b24..c9fb967a 100644 --- a/Object-Oriented Programming/Interfaces/lesson-info.yaml +++ b/Object-Oriented Programming/Interfaces/lesson-info.yaml @@ -3,4 +3,3 @@ content: - Exercise 1 - Exercise 2 - Exercise 3 -- Exercise 4 diff --git a/Object-Oriented Programming/OO Design, Revisited/Examples/src/ExploreMaze3.kt b/Object-Oriented Programming/OO Design, Revisited/Examples/src/ExploreMaze3.kt new file mode 100644 index 00000000..ffe5eac2 --- /dev/null +++ b/Object-Oriented Programming/OO Design, Revisited/Examples/src/ExploreMaze3.kt @@ -0,0 +1,20 @@ +// RobotExplorer3/ExploreMaze3.kt +package robotexplorer3 +import robotmaze.* + +fun testFactory(maze: String) { + println(Player.prototypes.map { + it::class.simpleName + }) + val lines = maze.split("\n") + lines.withIndex().forEach { (row, line) -> + line.withIndex().forEach { (col, ch) -> + println(Player.factory(ch)) + } + } +} + +fun main() { + // testFactory(stringMaze) + Stage(stringMaze).run(solution) +} \ No newline at end of file diff --git a/Object-Oriented Programming/OO Design, Revisited/Examples/src/Players3.kt b/Object-Oriented Programming/OO Design, Revisited/Examples/src/Players3.kt new file mode 100644 index 00000000..61dc5834 --- /dev/null +++ b/Object-Oriented Programming/OO Design, Revisited/Examples/src/Players3.kt @@ -0,0 +1,148 @@ +// RobotExplorer3/Players3.kt +package robotexplorer3 +import robotexplorer1.Urge +import kotlin.reflect.full.createInstance + +sealed class Player { + abstract val symbol: Char + abstract val room: Room + open fun id() = symbol.toString() + override fun toString() = + "${this::class.simpleName} ${id()}" + open class Result( + val success: Boolean, + val room: Room + ) + class Success(room: Room): + Result(true, room) + object Fail: Result(false, Room()) + abstract fun makePlayer(room: Room): Player + open fun create(ch: Char): Result { + if (ch == symbol) { + val room = Room() + room.player = makePlayer(room) + return Success(room) + } + return Fail + } + companion object { + val prototypes: List = + Player::class.sealedSubclasses.map { + it.createInstance() + } + fun factory(ch: Char): Room = + prototypes.map { it.create(ch) } + .first { it.success }.room + } + abstract fun interact(robot: Robot): Room +} + +class Void() : Player() { + override val symbol = '~' + override val room: Room + get() = throw IllegalAccessException() + override fun makePlayer(room: Room) = + Void() + override fun interact(robot: Robot) = + robot.room // Stay in old room +} + +class Wall( + override val room: Room = Room() +) : Player() { + override val symbol = '#' + override fun makePlayer(room: Room) = + Wall(room) + override fun interact(robot: Robot) = + robot.room // Stay in old room +} + +class Food( + override val room: Room = Room() +) : Player() { + override val symbol = '.' + override fun makePlayer(room: Room) = + Food(room) + override fun interact(robot: Robot): Room { + robot.energy++ // Consume food + room.player = Empty(room) // Remove food + return room // Move into new room + } +} + +class Empty( + override val room: Room = Room() +) : Player() { + override val symbol = '_' + override fun makePlayer(room: Room) = + Empty(room) + // Move into new room: + override fun interact(robot: Robot) = room +} + +class EndGame( + override val room: Room = Room() +) : Player() { + override val symbol = '!' + override fun makePlayer(room: Room) = + EndGame(room) + override fun interact(robot: Robot) = + Room(EndGame(room)) +} + +class Robot( + override var room: Room = Room() +) : Player() { + override val symbol = 'R' + var energy = 0 + override fun makePlayer(room: Room) = + Robot(room) + override fun create(ch: Char) = + if (ch == symbol) + Success(Room()) + else Fail + // Shouldn't happen: + override fun interact(robot: Robot) = + throw IllegalAccessException() + fun move(urge: Urge) { + val nextRoom = room.doors.open(urge) + room = nextRoom.player.interact(this) + } +} + +class Teleport( + val target: Char = 'Z', + override val room: Room = Room() +) : Player() { + override val symbol = 'T' + var targetRoom = Room() + override fun id() = target.toString() + override fun toString() = + "${this::class.simpleName} " + + "$symbol: $target $targetRoom" + override fun makePlayer(room: Room) = + throw IllegalStateException() + override fun create(ch: Char): Result { + if (ch in 'a'..'z') { + val room = Room() + room.player = Teleport(ch, room) + return Success(room) + } + return Fail + } + override fun interact(robot: Robot) = + targetRoom +} + +class Bomb( + override val room: Room = Room() +) : Player() { + override val symbol = '*' + override fun makePlayer(room: Room) = + Bomb(room) + override fun interact(robot: Robot): Room { + robot.energy = 0 // Bomb erases energy + room.player = Empty(room) + return room + } +} \ No newline at end of file diff --git a/Object-Oriented Programming/OO Design, Revisited/Examples/src/Room3.kt b/Object-Oriented Programming/OO Design, Revisited/Examples/src/Room3.kt new file mode 100644 index 00000000..48099716 --- /dev/null +++ b/Object-Oriented Programming/OO Design, Revisited/Examples/src/Room3.kt @@ -0,0 +1,35 @@ +// RobotExplorer3/Room3.kt +package robotexplorer3 +import robotexplorer1.Urge +import robotexplorer1.Urge.* + +class Room(var player: Player = Void()) { + val doors = Doors() + override fun toString() = "Room($player)" + companion object { + val edge = Room() + } +} + +class Doors { + private val doors = mutableMapOf( + North to Room.edge, + South to Room.edge, + East to Room.edge, + West to Room.edge + ) + fun open(urge: Urge): Room = + doors.getOrDefault(urge, Room.edge) + fun connect( + row: Int, col: Int, + rooms: Map, Room> + ) { + fun link(toRow: Int, toCol: Int) = + rooms.getOrDefault( + Pair(toRow, toCol), Room.edge) + doors[North] = link(row - 1, col) + doors[South] = link(row + 1, col) + doors[East] = link(row, col + 1) + doors[West] = link(row, col - 1) + } +} \ No newline at end of file diff --git a/Object-Oriented Programming/Extensibility/Examples/src/Stage3.kt b/Object-Oriented Programming/OO Design, Revisited/Examples/src/Stage3.kt similarity index 54% rename from Object-Oriented Programming/Extensibility/Examples/src/Stage3.kt rename to Object-Oriented Programming/OO Design, Revisited/Examples/src/Stage3.kt index f56151d6..67045fbb 100644 --- a/Object-Oriented Programming/Extensibility/Examples/src/Stage3.kt +++ b/Object-Oriented Programming/OO Design, Revisited/Examples/src/Stage3.kt @@ -1,35 +1,28 @@ // RobotExplorer3/Stage3.kt package robotexplorer3 +import robotexplorer1.urge +import robotexplorer2.Adapter +import robotexplorer2.View class Stage(val maze: String) { val robot = Robot(Room()) val rooms = mutableMapOf, Room>() - private val view = View(this) - val lines = maze.split("\n") - private fun factory(ch: Char): Room { - val room = Room() - when (ch) { - 'R' -> robot.room = room - '#' -> room.player = Wall() - '.' -> room.player = Food() - '_' -> room.player = Empty() - '/' -> room.player = Edge() - '!' -> room.player = EndGame() - else -> { - val teleport = Teleport(ch) - teleport.originRoom = room - room.player = teleport - } - } - return room + private inner class Adapt : Adapter { + override fun height() = + maze.lines().size + 3 + override fun textView() = mazeView() } - // Construct it with the 'Builder' pattern: - init { + private val view = View(Adapt()) + val lines = maze.split("\n") + init { // The 'Builder' pattern: // Step 1: Create rooms with players: lines.withIndex().forEach { (row, line) -> line.withIndex().forEach { (col, ch) -> - rooms[Pair(row, col)] = factory(ch) + val room = Player.factory(ch) + rooms[Pair(row, col)] = room + if(ch == robot.symbol) + robot.room = room } } // Step 2: Connect the doors @@ -47,8 +40,8 @@ class Stage(val maze: String) { it.target }.zipWithNext() for((a, b) in teleportPairs) { - a.targetRoom = b.originRoom - b.targetRoom = a.originRoom + a.targetRoom = b.room + b.targetRoom = a.room } } fun run(solution: String) { @@ -60,4 +53,20 @@ class Stage(val maze: String) { view.show() } } +} + +fun Stage.mazeView(): String { + var result = "" + var currentRow = 0 + rooms.forEach { (pair, room) -> + val row = pair.first + if (row != currentRow) { + result += "\n" + currentRow = row + } + result += if (room == robot.room) + robot.id() else room.player.id() + } + return result + + "\n\nEnergy: ${robot.energy}\n" } \ No newline at end of file diff --git a/Object-Oriented Programming/OO Design, Revisited/Examples/task-info.yaml b/Object-Oriented Programming/OO Design, Revisited/Examples/task-info.yaml new file mode 100644 index 00000000..c0abeb09 --- /dev/null +++ b/Object-Oriented Programming/OO Design, Revisited/Examples/task-info.yaml @@ -0,0 +1,10 @@ +type: theory +files: +- name: src/Players3.kt + visible: true +- name: src/ExploreMaze3.kt + visible: true +- name: src/Room3.kt + visible: true +- name: src/Stage3.kt + visible: true diff --git a/Object-Oriented Programming/OO Design, Revisited/Examples/task.md b/Object-Oriented Programming/OO Design, Revisited/Examples/task.md new file mode 100644 index 00000000..a6d0df0a --- /dev/null +++ b/Object-Oriented Programming/OO Design, Revisited/Examples/task.md @@ -0,0 +1,3 @@ +## OO Design, Revisited + +Examples accompanying the atom. \ No newline at end of file diff --git a/Power Tools/Destructuring Declarations/lesson-info.yaml b/Object-Oriented Programming/OO Design, Revisited/lesson-info.yaml similarity index 100% rename from Power Tools/Destructuring Declarations/lesson-info.yaml rename to Object-Oriented Programming/OO Design, Revisited/lesson-info.yaml diff --git a/Object-Oriented Programming/Object-Oriented Design/Examples/src/Doors.kt b/Object-Oriented Programming/Object-Oriented Design/Examples/src/Doors.kt index 5d1f7ddb..f5d39c99 100644 --- a/Object-Oriented Programming/Object-Oriented Design/Examples/src/Doors.kt +++ b/Object-Oriented Programming/Object-Oriented Design/Examples/src/Doors.kt @@ -1,9 +1,8 @@ -// ObjectOrientedDesign/Doors.kt -package robotexplorer -import robotexplorer.Player.* -import robotexplorer.Urge.* +// RobotExplorer1/Doors.kt +package robotexplorer1 +import robotexplorer1.Urge.* -val edge = Room(Edge) +val edge = Room() class Doors { private var north: Room = edge diff --git a/Object-Oriented Programming/Object-Oriented Design/Examples/src/ExploreMaze.kt b/Object-Oriented Programming/Object-Oriented Design/Examples/src/ExploreMaze.kt index 29dca45c..a42dd682 100644 --- a/Object-Oriented Programming/Object-Oriented Design/Examples/src/ExploreMaze.kt +++ b/Object-Oriented Programming/Object-Oriented Design/Examples/src/ExploreMaze.kt @@ -1,5 +1,5 @@ -// ObjectOrientedDesign/ExploreMaze.kt -package robotexplorer +// RobotExplorer1/ExploreMaze.kt +package robotexplorer1 import robotmaze.* fun main() { diff --git a/Object-Oriented Programming/Object-Oriented Design/Examples/src/MazeView.kt b/Object-Oriented Programming/Object-Oriented Design/Examples/src/MazeView.kt new file mode 100644 index 00000000..6f0f102e --- /dev/null +++ b/Object-Oriented Programming/Object-Oriented Design/Examples/src/MazeView.kt @@ -0,0 +1,18 @@ +// RobotExplorer1/MazeView.kt +package robotexplorer1 + +fun Stage.mazeView(): String { + var result = "" + var currentRow = 0 + rooms.forEach { (pair, room) -> + val row = pair.first + if (row != currentRow) { + result += "\n" + currentRow = row + } + result += if (room == robot.room) + "$robot" else "${room.player}" + } + return result + + "\n\nEnergy: ${robot.energy}\n" +} \ No newline at end of file diff --git a/Object-Oriented Programming/Object-Oriented Design/Examples/src/Players.kt b/Object-Oriented Programming/Object-Oriented Design/Examples/src/Players.kt index 8351dabf..b3ac9d40 100644 --- a/Object-Oriented Programming/Object-Oriented Design/Examples/src/Players.kt +++ b/Object-Oriented Programming/Object-Oriented Design/Examples/src/Players.kt @@ -1,7 +1,9 @@ -// ObjectOrientedDesign/Players.kt -package robotexplorer +// RobotExplorer1/Players.kt +package robotexplorer1 class Robot(var room: Room) { + val symbol = 'R' + var energy = 0 fun move(urge: Urge) { // Get a reference to the Room you've // been urged to go to, and see what @@ -9,14 +11,14 @@ class Robot(var room: Room) { // Point robot to returned Room: room = room.doors.open(urge).enter(this) } - override fun toString() = "R" + override fun toString() = symbol.toString() } enum class Player(val symbol: Char) { Wall('#'), Food('.'), Empty('_'), - Edge('/'), + Void('~'), EndGame('!'); override fun toString() = symbol.toString() } @@ -25,4 +27,18 @@ class Teleport(val target: Char) { var originRoom = Room() var targetRoom = Room() override fun toString() = target.toString() +} + +fun factory(ch: Char): Room { + val room = Room() + Player.values().forEach { + if (ch == it.symbol) { + room.player = it + return room + } + } + val teleport = Teleport(ch) + room.player = teleport + teleport.originRoom = room + return room } \ No newline at end of file diff --git a/Object-Oriented Programming/Object-Oriented Design/Examples/src/RobotMaze.kt b/Object-Oriented Programming/Object-Oriented Design/Examples/src/RobotMaze.kt index 64b83535..30a6712a 100644 --- a/Object-Oriented Programming/Object-Oriented Design/Examples/src/RobotMaze.kt +++ b/Object-Oriented Programming/Object-Oriented Design/Examples/src/RobotMaze.kt @@ -1,4 +1,4 @@ -// ObjectOrientedDesign/RobotMaze.kt +// RobotExplorer1/RobotMaze.kt package robotmaze val stringMaze = """ @@ -16,4 +16,22 @@ eeeeeeeeee wwwwwwww eeennnwwwwwsseeeeeen ww -""".trim() \ No newline at end of file +""".trim() + +//val stringMaze = """ +//a_...#...__#_......._c +//R_...#...__#_..#.d..__ +//###################### +//a_......._b#c......._b +//###################### +//!_e_.....__#_d_....._e +//""".trim() +// +//val solution = """ +//eeeenwwww +//eeeeeeeeee +//wwwwwwwww +//wwwwwwwwseneese +//eeeeeeee +//ww +//""".trim() \ No newline at end of file diff --git a/Object-Oriented Programming/Object-Oriented Design/Examples/src/Room.kt b/Object-Oriented Programming/Object-Oriented Design/Examples/src/Room.kt index 203d3e96..85f9772d 100644 --- a/Object-Oriented Programming/Object-Oriented Design/Examples/src/Room.kt +++ b/Object-Oriented Programming/Object-Oriented Design/Examples/src/Room.kt @@ -1,16 +1,19 @@ -// ObjectOrientedDesign/Room.kt -package robotexplorer -import robotexplorer.Player.* +// RobotExplorer1/Room.kt +package robotexplorer1 +import robotexplorer1.Player.* -class Room(var player: Any = Empty) { +class Room(var player: Any = Void) { val doors = Doors() fun enter(robot: Robot): Room { when (val p = player) { // Stay in original room: - Wall, Edge -> return robot.room + Wall, Void -> return robot.room is Teleport -> return p.targetRoom EndGame -> return Room(EndGame) - Food -> player = Empty // Eat food + Food -> { + robot.energy++ // Eat food + player = Empty + } Empty -> {} } return this // Enter new room diff --git a/Object-Oriented Programming/Object-Oriented Design/Examples/src/Stage.kt b/Object-Oriented Programming/Object-Oriented Design/Examples/src/Stage.kt index 0d7b718b..35148ec5 100644 --- a/Object-Oriented Programming/Object-Oriented Design/Examples/src/Stage.kt +++ b/Object-Oriented Programming/Object-Oriented Design/Examples/src/Stage.kt @@ -1,5 +1,5 @@ -// ObjectOrientedDesign/Stage.kt -package robotexplorer +// RobotExplorer1/Stage.kt +package robotexplorer1 class Stage(val maze: String) { val robot = Robot(Room()) @@ -7,29 +7,15 @@ class Stage(val maze: String) { mutableMapOf, Room>() private val view = View(this) val lines = maze.split("\n") - private fun factory(ch: Char): Room { - val room = Room() - if(ch == 'R') { - robot.room = room - return room - } - Player.values().forEach { - if (ch == it.symbol) { - room.player = it - return room - } - } - val teleport = Teleport(ch) - room.player = teleport - teleport.originRoom = room - return room - } - // Construct it with the 'Builder' pattern: + // Create using the 'Builder' pattern: fun build(): Stage { // Step 1: Create rooms with players: lines.withIndex().forEach { (row, line) -> line.withIndex().forEach { (col, ch) -> - rooms[Pair(row, col)] = factory(ch) + val room = factory(ch) + rooms[Pair(row, col)] = room + if(ch == robot.symbol) + robot.room = room } } // Step 2: Connect the doors diff --git a/Object-Oriented Programming/Object-Oriented Design/Examples/src/Urge.kt b/Object-Oriented Programming/Object-Oriented Design/Examples/src/Urge.kt index f955649c..c509c0e6 100644 --- a/Object-Oriented Programming/Object-Oriented Design/Examples/src/Urge.kt +++ b/Object-Oriented Programming/Object-Oriented Design/Examples/src/Urge.kt @@ -1,6 +1,6 @@ -// ObjectOrientedDesign/Urge.kt -package robotexplorer -import robotexplorer.Urge.* +// RobotExplorer1/Urge.kt +package robotexplorer1 +import robotexplorer1.Urge.* enum class Urge { North, South, East, West } diff --git a/Object-Oriented Programming/Object-Oriented Design/Examples/src/View.kt b/Object-Oriented Programming/Object-Oriented Design/Examples/src/View.kt index 98d083dd..4b6ee4f3 100644 --- a/Object-Oriented Programming/Object-Oriented Design/Examples/src/View.kt +++ b/Object-Oriented Programming/Object-Oriented Design/Examples/src/View.kt @@ -1,5 +1,5 @@ -// ObjectOrientedDesign/View.kt -package robotexplorer +// RobotExplorer1/View.kt +package robotexplorer1 class View(private val stage: Stage) { // Start an ANSI terminal control string: @@ -8,23 +8,9 @@ class View(private val stage: Stage) { val size = stage.maze.lines().size + 3 print("${ansiTerm}${size}T") } - private fun mazeView(): String { - var result = "" - var currentRow = 0 - stage.rooms.forEach { (pair, room) -> - val row = pair.first - if (row != currentRow) { - result += "\n" - currentRow = row - } - result += if (room == stage.robot.room) - "${stage.robot}" else "${room.player}" - } - return result + "\n\n\n" - } fun show() { print("${ansiTerm}0;0H") // Cursor home - println(mazeView()) + println(stage.mazeView()) Thread.sleep(300L) // Pause } } \ No newline at end of file diff --git a/Object-Oriented Programming/Object-Oriented Design/Examples/task-info.yaml b/Object-Oriented Programming/Object-Oriented Design/Examples/task-info.yaml index 1d7686d5..581029f6 100644 --- a/Object-Oriented Programming/Object-Oriented Design/Examples/task-info.yaml +++ b/Object-Oriented Programming/Object-Oriented Design/Examples/task-info.yaml @@ -14,5 +14,7 @@ files: visible: true - name: src/Stage.kt visible: true +- name: src/MazeView.kt + visible: true - name: src/View.kt visible: true diff --git a/Object-Oriented Programming/Polymorphism/Exercise 1/src/Task.kt b/Object-Oriented Programming/Polymorphism/Exercise 1/src/Task.kt new file mode 100644 index 00000000..a2ec1a49 --- /dev/null +++ b/Object-Oriented Programming/Polymorphism/Exercise 1/src/Task.kt @@ -0,0 +1,3 @@ +package polymorphismExercise1 + +// type your solution here \ No newline at end of file diff --git a/Object-Oriented Programming/Polymorphism/Exercise 1/task-info.yaml b/Object-Oriented Programming/Polymorphism/Exercise 1/task-info.yaml new file mode 100644 index 00000000..7ad1b827 --- /dev/null +++ b/Object-Oriented Programming/Polymorphism/Exercise 1/task-info.yaml @@ -0,0 +1,6 @@ +type: edu +files: +- name: src/Task.kt + visible: true +- name: test/Tests.kt + visible: false diff --git a/Object-Oriented Programming/Polymorphism/Exercise 1/task.md b/Object-Oriented Programming/Polymorphism/Exercise 1/task.md new file mode 100644 index 00000000..841a0887 --- /dev/null +++ b/Object-Oriented Programming/Polymorphism/Exercise 1/task.md @@ -0,0 +1,33 @@ +## Polymorphism (#1) + +Add `Hamster` (which says "Squeak!") to `Pet.kt`. + +```kotlin +// Polymorphism/PolyExercise1.kt +package polymorphismex1 +import atomictest.eq + +open class Pet { + open fun speak() = "Pet" +} + +class Dog : Pet() { + override fun speak() = "Bark!" +} + +class Cat : Pet() { + override fun speak() = "Meow" +} + +class Hamster : Pet() { + override fun speak() = "Squeak!" +} + +fun talk(pet: Pet) = pet.speak() + +fun main() { + talk(Dog()) eq "Bark!" + talk(Cat()) eq "Meow" + talk(Hamster()) eq "Squeak!" +} +``` \ No newline at end of file diff --git a/Object-Oriented Programming/Polymorphism/Exercise 1/test/Tests.kt b/Object-Oriented Programming/Polymorphism/Exercise 1/test/Tests.kt new file mode 100644 index 00000000..a95175cc --- /dev/null +++ b/Object-Oriented Programming/Polymorphism/Exercise 1/test/Tests.kt @@ -0,0 +1,11 @@ +package polymorphismExercise1 + +import org.junit.Assert +import org.junit.Test + +class TestPolymorphismExercise1 { + @Test fun testSolution() { + //TODO: implement your test here + Assert.assertTrue("Tests not implemented for the task", false) + } +} \ No newline at end of file diff --git a/Object-Oriented Programming/Polymorphism/Exercise 2/src/Task.kt b/Object-Oriented Programming/Polymorphism/Exercise 2/src/Task.kt new file mode 100644 index 00000000..4858d888 --- /dev/null +++ b/Object-Oriented Programming/Polymorphism/Exercise 2/src/Task.kt @@ -0,0 +1,3 @@ +package polymorphismExercise2 + +// type your solution here \ No newline at end of file diff --git a/Object-Oriented Programming/Polymorphism/Exercise 2/task-info.yaml b/Object-Oriented Programming/Polymorphism/Exercise 2/task-info.yaml new file mode 100644 index 00000000..7ad1b827 --- /dev/null +++ b/Object-Oriented Programming/Polymorphism/Exercise 2/task-info.yaml @@ -0,0 +1,6 @@ +type: edu +files: +- name: src/Task.kt + visible: true +- name: test/Tests.kt + visible: false diff --git a/Object-Oriented Programming/Polymorphism/Exercise 2/task.md b/Object-Oriented Programming/Polymorphism/Exercise 2/task.md new file mode 100644 index 00000000..6f95f192 --- /dev/null +++ b/Object-Oriented Programming/Polymorphism/Exercise 2/task.md @@ -0,0 +1,164 @@ +## Polymorphism (#2) + +Add `Wizard`, which implements `Magician`, and `Goblin` which implements +`Fighter`, to `FantasyGame.kt`. In `main()`, create and test a `Wizard` named +"Max" and a `Goblin` named "Gorbag." + +```kotlin +// Polymorphism/PolyExercise2.kt +package polymorphismex2 +import atomictest.* + +private val trace = Trace() + +interface Character { + val name: String + val type: String + fun skills(): String + fun play() = "$name $type: ${skills()}" +} + +interface Magician { + fun skills() = "Magic" +} + +interface Fighter { + fun skills() = "Fighting" +} + +interface Flyer { + fun skills() = "Flying" +} + +open class Elf(override val name: String) : + Character, Magician, Flyer { + override val type = "Elf" + override fun skills() = + super.skills() + ", " + + super.skills() +} + +class FightingElf(name: String) : + Elf(name), Fighter { + override val type = "FightingElf" + override fun skills() = + super.skills() + ", " + + super.skills() +} + +class Warrior(override val name: String) : + Character, Fighter { + override val type = "Warrior" + override fun skills() = super.skills() +} + +class Dragon(override val name: String) : + Character, Magician, Flyer { + override val type = "Dragon" + override fun skills() = + super.skills() + ", " + + super.skills() +} + +class Wizard(override val name: String) : + Character, Magician { + override val type = "Wizard" + override fun skills() = super.skills() +} + +class Goblin(override val name: String) : + Character, Fighter { + override val type = "Goblin" + override fun skills() = super.skills() +} + +fun match(c1: Character, c2: Character) = + trace("${c1.play()} -> ${c2.play()}") + +fun main() { + val characters: List = listOf( + Elf("Titania"), + FightingElf("Legolas"), + Warrior("Conan"), + Dragon("Puff"), + Wizard("Max"), + Goblin("Gorbag") + ) + characters.forEach { c1 -> + characters.filter { it != c1 } + .forEach { c2 -> match(c1, c2) } + } + trace eq """ + Titania Elf: Magic, Flying -> + Legolas FightingElf: + Magic, Flying, Fighting + Titania Elf: Magic, Flying -> + Conan Warrior: Fighting + Titania Elf: Magic, Flying -> + Puff Dragon: Magic, Flying + Titania Elf: Magic, Flying -> + Max Wizard: Magic + Titania Elf: Magic, Flying -> + Gorbag Goblin: Fighting + Legolas FightingElf: + Magic, Flying, Fighting -> + Titania Elf: Magic, Flying + Legolas FightingElf: + Magic, Flying, Fighting -> + Conan Warrior: Fighting + Legolas FightingElf: + Magic, Flying, Fighting -> + Puff Dragon: Magic, Flying + Legolas FightingElf: + Magic, Flying, Fighting -> + Max Wizard: Magic + Legolas FightingElf: + Magic, Flying, Fighting -> + Gorbag Goblin: Fighting + Conan Warrior: Fighting -> + Titania Elf: Magic, Flying + Conan Warrior: Fighting -> + Legolas FightingElf: + Magic, Flying, Fighting + Conan Warrior: Fighting -> + Puff Dragon: Magic, Flying + Conan Warrior: Fighting -> + Max Wizard: Magic + Conan Warrior: Fighting -> + Gorbag Goblin: Fighting + Puff Dragon: Magic, Flying -> + Titania Elf: Magic, Flying + Puff Dragon: Magic, Flying -> + Legolas FightingElf: + Magic, Flying, Fighting + Puff Dragon: Magic, Flying -> + Conan Warrior: Fighting + Puff Dragon: Magic, Flying -> + Max Wizard: Magic + Puff Dragon: Magic, Flying -> + Gorbag Goblin: Fighting + Max Wizard: Magic -> + Titania Elf: Magic, Flying + Max Wizard: Magic -> + Legolas FightingElf: + Magic, Flying, Fighting + Max Wizard: Magic -> + Conan Warrior: Fighting + Max Wizard: Magic -> + Puff Dragon: Magic, Flying + Max Wizard: Magic -> + Gorbag Goblin: Fighting + Gorbag Goblin: Fighting -> + Titania Elf: Magic, Flying + Gorbag Goblin: Fighting -> + Legolas FightingElf: + Magic, Flying, Fighting + Gorbag Goblin: Fighting -> + Conan Warrior: Fighting + Gorbag Goblin: Fighting -> + Puff Dragon: Magic, Flying + Gorbag Goblin: Fighting -> + Max Wizard: Magic + """ +} +``` \ No newline at end of file diff --git a/Object-Oriented Programming/Polymorphism/Exercise 2/test/Tests.kt b/Object-Oriented Programming/Polymorphism/Exercise 2/test/Tests.kt new file mode 100644 index 00000000..df8c3b1e --- /dev/null +++ b/Object-Oriented Programming/Polymorphism/Exercise 2/test/Tests.kt @@ -0,0 +1,11 @@ +package polymorphismExercise2 + +import org.junit.Assert +import org.junit.Test + +class TestPolymorphismExercise2 { + @Test fun testSolution() { + //TODO: implement your test here + Assert.assertTrue("Tests not implemented for the task", false) + } +} \ No newline at end of file diff --git a/Object-Oriented Programming/Polymorphism/Exercise 3/src/Task.kt b/Object-Oriented Programming/Polymorphism/Exercise 3/src/Task.kt new file mode 100644 index 00000000..f5a1f5c9 --- /dev/null +++ b/Object-Oriented Programming/Polymorphism/Exercise 3/src/Task.kt @@ -0,0 +1,3 @@ +package polymorphismExercise3 + +// type your solution here \ No newline at end of file diff --git a/Object-Oriented Programming/Polymorphism/Exercise 3/task-info.yaml b/Object-Oriented Programming/Polymorphism/Exercise 3/task-info.yaml new file mode 100644 index 00000000..7ad1b827 --- /dev/null +++ b/Object-Oriented Programming/Polymorphism/Exercise 3/task-info.yaml @@ -0,0 +1,6 @@ +type: edu +files: +- name: src/Task.kt + visible: true +- name: test/Tests.kt + visible: false diff --git a/Object-Oriented Programming/Polymorphism/Exercise 3/task.md b/Object-Oriented Programming/Polymorphism/Exercise 3/task.md new file mode 100644 index 00000000..39d56ba7 --- /dev/null +++ b/Object-Oriented Programming/Polymorphism/Exercise 3/task.md @@ -0,0 +1,50 @@ +## Polymorphism (#3) + +Create a base class named `Base` containing two methods, `f1()` and `f2()`. +`f1()` uses `atomictest.Trace` to report "Base.f1", then calls `f2()`. `f2()` +traces "Base.f2". + +From `Base`, inherit a class called `Derived`. Override `f1()`, first tracing +"Derived.f1", then calling the base-class version of `f1()`. Override `f2()` +the same way. + +In `main()`, create a `Derived` object and upcast it to a `Base` reference. +Call `f1()` for this reference and explain the resulting trace. + +```kotlin +// Polymorphism/PolyExercise3.kt +package polymorphism +import atomictest.* + +private val trace = Trace() + +open class Base { + open fun f1() { + trace("Base.f1") + f2() + } + open fun f2() = trace("Base.f2") +} + +class Derived : Base() { + override fun f1() { + trace("Derived.f1") + super.f1() + } + override fun f2() { + trace("Derived.f2") + super.f2() + } +} + +fun main() { + val base: Base = Derived() + base.f1() + trace eq """ + Derived.f1 + Base.f1 + Derived.f2 + Base.f2 + """ +} +``` \ No newline at end of file diff --git a/Object-Oriented Programming/Polymorphism/Exercise 3/test/Tests.kt b/Object-Oriented Programming/Polymorphism/Exercise 3/test/Tests.kt new file mode 100644 index 00000000..63f4d586 --- /dev/null +++ b/Object-Oriented Programming/Polymorphism/Exercise 3/test/Tests.kt @@ -0,0 +1,11 @@ +package polymorphismExercise3 + +import org.junit.Assert +import org.junit.Test + +class TestPolymorphismExercise3 { + @Test fun testSolution() { + //TODO: implement your test here + Assert.assertTrue("Tests not implemented for the task", false) + } +} \ No newline at end of file diff --git a/Object-Oriented Programming/Polymorphism/lesson-info.yaml b/Object-Oriented Programming/Polymorphism/lesson-info.yaml index d8e63b88..c9fb967a 100644 --- a/Object-Oriented Programming/Polymorphism/lesson-info.yaml +++ b/Object-Oriented Programming/Polymorphism/lesson-info.yaml @@ -1,2 +1,5 @@ content: - Examples +- Exercise 1 +- Exercise 2 +- Exercise 3 diff --git a/Object-Oriented Programming/Upcasting/Exercise 1/src/Task.kt b/Object-Oriented Programming/Upcasting/Exercise 1/src/Task.kt new file mode 100644 index 00000000..e6589517 --- /dev/null +++ b/Object-Oriented Programming/Upcasting/Exercise 1/src/Task.kt @@ -0,0 +1,3 @@ +package upcastingExercise1 + +// type your solution here \ No newline at end of file diff --git a/Object-Oriented Programming/Upcasting/Exercise 1/task-info.yaml b/Object-Oriented Programming/Upcasting/Exercise 1/task-info.yaml new file mode 100644 index 00000000..7ad1b827 --- /dev/null +++ b/Object-Oriented Programming/Upcasting/Exercise 1/task-info.yaml @@ -0,0 +1,6 @@ +type: edu +files: +- name: src/Task.kt + visible: true +- name: test/Tests.kt + visible: false diff --git a/Object-Oriented Programming/Upcasting/Exercise 1/task.md b/Object-Oriented Programming/Upcasting/Exercise 1/task.md new file mode 100644 index 00000000..d2319a61 --- /dev/null +++ b/Object-Oriented Programming/Upcasting/Exercise 1/task.md @@ -0,0 +1,64 @@ +## Upcasting (#1) + +Create a `Rodent` interface containing `eat()` and `speak()` functions. Make +two implementations of `Rodent`: `Mouse` and `KangarooRat`. For each function, +use `atomictest.Trace` to record the name of the class, a dot, and the name of +the function. In `KangarooRat`, add a `jump()` function which follows the form +of the other functions. + +Create a function `upcast(rodent: Rodent)` which calls `eat()` and `speak()`. +Show that the compiler won't allow you to call `jump()`. + +In `main()`, create an instance of `Mouse` and `KangarooRat`, and show that +you can call `jump()` for the latter. Pass both objects into `upcast()`, and +use `trace` to verify the output. + +```kotlin +// Upcasting/UpcastExercise1.kt +package upcasting +import atomictest.* + +private var trace = Trace() + +interface Rodent { + fun eat() + fun speak() +} + +class Mouse: Rodent { + override fun eat() = + trace("Mouse.eat") + override fun speak() = + trace("Mouse.speak") +} + +class KangarooRat: Rodent { + override fun eat() = + trace("KangarooRat.eat") + override fun speak() = + trace("KangarooRat.speak") + fun jump() = + trace("KangarooRat.jump") +} + +fun upcast(rodent: Rodent) { + rodent.eat() + rodent.speak() + // rodent.jump() // Won't compile +} + +fun main() { + val mouse = Mouse() + val kangarooRat = KangarooRat() + kangarooRat.jump() + upcast(mouse) + upcast(kangarooRat) + trace eq """ + KangarooRat.jump + Mouse.eat + Mouse.speak + KangarooRat.eat + KangarooRat.speak + """ +} +``` \ No newline at end of file diff --git a/Object-Oriented Programming/Upcasting/Exercise 1/test/Tests.kt b/Object-Oriented Programming/Upcasting/Exercise 1/test/Tests.kt new file mode 100644 index 00000000..e53667f2 --- /dev/null +++ b/Object-Oriented Programming/Upcasting/Exercise 1/test/Tests.kt @@ -0,0 +1,11 @@ +package upcastingExercise1 + +import org.junit.Assert +import org.junit.Test + +class TestUpcastingExercise1 { + @Test fun testSolution() { + //TODO: implement your test here + Assert.assertTrue("Tests not implemented for the task", false) + } +} \ No newline at end of file diff --git a/Object-Oriented Programming/Upcasting/Exercise 2/src/Task.kt b/Object-Oriented Programming/Upcasting/Exercise 2/src/Task.kt new file mode 100644 index 00000000..d280b888 --- /dev/null +++ b/Object-Oriented Programming/Upcasting/Exercise 2/src/Task.kt @@ -0,0 +1,3 @@ +package upcastingExercise2 + +// type your solution here \ No newline at end of file diff --git a/Object-Oriented Programming/Upcasting/Exercise 2/task-info.yaml b/Object-Oriented Programming/Upcasting/Exercise 2/task-info.yaml new file mode 100644 index 00000000..7ad1b827 --- /dev/null +++ b/Object-Oriented Programming/Upcasting/Exercise 2/task-info.yaml @@ -0,0 +1,6 @@ +type: edu +files: +- name: src/Task.kt + visible: true +- name: test/Tests.kt + visible: false diff --git a/Object-Oriented Programming/Upcasting/Exercise 2/task.md b/Object-Oriented Programming/Upcasting/Exercise 2/task.md new file mode 100644 index 00000000..eb18a908 --- /dev/null +++ b/Object-Oriented Programming/Upcasting/Exercise 2/task.md @@ -0,0 +1,76 @@ +## Upcasting (#2) + +Upcasting also happens when you add an object of a derived type into a +container that holds the base type. + +Make a `private var counter = 0` at file scope. Create an `abstract` class +`Apple` that takes an argument `val type: String` to hold the type of apple. +Add a `private val id` which is initialized by getting the value of `counter` +and incrementing it. Inside `init`, use `atomictest.Trace` to record the +`type` and `id`. + +Add an `abstract fun consume()` to `Apple`. + +From `Apple`, inherit `GrannySmith`, `Gala`, `Fuji` and `Braeburn`. Override +`consume()` so, respectively, they call `trace()` with `chomp GrannySmith`, +`bite Gala`, `press Fuji` and `peel Braeburn`. + +In `main()`, make a `List` and populate it with the specific types of +`Apple`. Iterate through the list calling `consume()` for each object. + +```kotlin +// Upcasting/UpcastExercise2.kt +package upcasting +import atomictest.* + +private var trace = Trace() +private var counter = 0 + +abstract class Apple(val type: String) { + private val id = counter++ + init { + trace("$type $id") + } + abstract fun consume() +} + +class GrannySmith : Apple("GrannySmith") { + override fun consume() = + trace("chomp $type") +} + +class Gala : Apple("Gala") { + override fun consume() = + trace("bite $type") +} + +class Fuji : Apple("Fuji") { + override fun consume() = + trace("press $type") +} + +class Braeburn : Apple("Braeburn") { + override fun consume() = + trace("peel $type") +} + +fun main() { + val apples: List = listOf( + GrannySmith(), + Gala(), + Fuji(), + Braeburn() + ) + apples.forEach { it.consume() } + trace eq """ + GrannySmith 0 + Gala 1 + Fuji 2 + Braeburn 3 + chomp GrannySmith + bite Gala + press Fuji + peel Braeburn + """ +} +``` \ No newline at end of file diff --git a/Object-Oriented Programming/Upcasting/Exercise 2/test/Tests.kt b/Object-Oriented Programming/Upcasting/Exercise 2/test/Tests.kt new file mode 100644 index 00000000..07566c6e --- /dev/null +++ b/Object-Oriented Programming/Upcasting/Exercise 2/test/Tests.kt @@ -0,0 +1,11 @@ +package upcastingExercise2 + +import org.junit.Assert +import org.junit.Test + +class TestUpcastingExercise2 { + @Test fun testSolution() { + //TODO: implement your test here + Assert.assertTrue("Tests not implemented for the task", false) + } +} \ No newline at end of file diff --git a/Object-Oriented Programming/Upcasting/Exercise 3/src/Task.kt b/Object-Oriented Programming/Upcasting/Exercise 3/src/Task.kt new file mode 100644 index 00000000..e3177a16 --- /dev/null +++ b/Object-Oriented Programming/Upcasting/Exercise 3/src/Task.kt @@ -0,0 +1,3 @@ +package upcastingExercise3 + +// type your solution here \ No newline at end of file diff --git a/Object-Oriented Programming/Upcasting/Exercise 3/task-info.yaml b/Object-Oriented Programming/Upcasting/Exercise 3/task-info.yaml new file mode 100644 index 00000000..7ad1b827 --- /dev/null +++ b/Object-Oriented Programming/Upcasting/Exercise 3/task-info.yaml @@ -0,0 +1,6 @@ +type: edu +files: +- name: src/Task.kt + visible: true +- name: test/Tests.kt + visible: false diff --git a/Object-Oriented Programming/Upcasting/Exercise 3/task.md b/Object-Oriented Programming/Upcasting/Exercise 3/task.md new file mode 100644 index 00000000..2cd6a3c9 --- /dev/null +++ b/Object-Oriented Programming/Upcasting/Exercise 3/task.md @@ -0,0 +1,73 @@ +## Upcasting (#3) + +When you combine interfaces to create a class, you can upcast an object of +that class to each different interface. + +Create three interfaces: `Fight` with a function `fight()`, `Swim` with a +function `swim()`, and `Fly` with a function `fly()`. Create a class +`ActionCharacter` which has a `fight()` function that uses `atomictest.Trace` +to report `"ActionCharacter fight"`. + +Now define a class `Hero` that combines `ActionCharacter`, `Fight`, `Swim` and +`Fly`. Notice that the `fight()` in `ActionCharacter` provides the `fight()` +needed by the `Fight` interface. Define `swim()` to trace `"Hero swim"` +and `fly()` to trace `"Hero fly"`. + +Next, define `t(x: Fight)`, `u(x: Swim)`, `v(x: Fly)`, and `w(x: ActionCharacter)`, +so that each function calls the member function avalable to its parameter. + +In `main()`, make a `Hero` object and pass it to each of the functions `t()`, +`u()`, `v()`, and `w()` and validate the output using `trace`. Notice how +passing a `Hero` to each of the functions upcasts it so that, inside the +function, the `Hero` becomes only the type of that parameter. + + +```kotlin +// Upcasting/UpcastExercise3.kt +package upcasting +import atomictest.* + +private var trace = Trace() + +interface Fight { + fun fight() +} + +interface Swim { + fun swim() +} + +interface Fly { + fun fly() +} + +open class ActionCharacter { + fun fight() = + trace("ActionCharacter fight") +} + +class Hero : + ActionCharacter(), Fight, Swim, Fly { + override fun swim() = trace("Hero swim") + override fun fly() = trace("Hero fly") +} + +fun t(x: Fight) = x.fight() +fun u(x: Swim) = x.swim() +fun v(x: Fly) = x.fly() +fun w(x: ActionCharacter) = x.fight() + +fun main() { + val h = Hero() + t(h) // Treat it as a Fight + u(h) // Treat it as a Swim + v(h) // Treat it as a Fly + w(h) // Treat it as an ActionCharacter + trace eq """ + ActionCharacter fight + Hero swim + Hero fly + ActionCharacter fight + """ +} +``` \ No newline at end of file diff --git a/Object-Oriented Programming/Upcasting/Exercise 3/test/Tests.kt b/Object-Oriented Programming/Upcasting/Exercise 3/test/Tests.kt new file mode 100644 index 00000000..c0e2bc77 --- /dev/null +++ b/Object-Oriented Programming/Upcasting/Exercise 3/test/Tests.kt @@ -0,0 +1,11 @@ +package upcastingExercise3 + +import org.junit.Assert +import org.junit.Test + +class TestUpcastingExercise3 { + @Test fun testSolution() { + //TODO: implement your test here + Assert.assertTrue("Tests not implemented for the task", false) + } +} \ No newline at end of file diff --git a/Object-Oriented Programming/Upcasting/lesson-info.yaml b/Object-Oriented Programming/Upcasting/lesson-info.yaml index d8e63b88..c9fb967a 100644 --- a/Object-Oriented Programming/Upcasting/lesson-info.yaml +++ b/Object-Oriented Programming/Upcasting/lesson-info.yaml @@ -1,2 +1,5 @@ content: - Examples +- Exercise 1 +- Exercise 2 +- Exercise 3 diff --git a/Object-Oriented Programming/section-info.yaml b/Object-Oriented Programming/section-info.yaml index 6763faae..204c4668 100644 --- a/Object-Oriented Programming/section-info.yaml +++ b/Object-Oriented Programming/section-info.yaml @@ -10,7 +10,6 @@ content: - Polymorphism - Composition - Inheritance & Extensions -- Designing with Inheritance - Extensibility - Class Delegation - Downcasting @@ -18,3 +17,4 @@ content: - Inner & Nested Classes - Objects - Companion Objects +- OO Design, Revisited diff --git a/Power Tools/section-info.yaml b/Power Tools/section-info.yaml index 6fb0006f..87c7288f 100644 --- a/Power Tools/section-info.yaml +++ b/Power Tools/section-info.yaml @@ -5,7 +5,6 @@ content: - Scope Functions - Immutability - Hashing -- Destructuring Declarations - Operator Overloading - Using Operators - Lazy Initialization diff --git a/Power Tools/Destructuring Declarations/Examples/src/Computation.kt b/Usability/Destructuring Declarations/Examples/src/Computation.kt similarity index 100% rename from Power Tools/Destructuring Declarations/Examples/src/Computation.kt rename to Usability/Destructuring Declarations/Examples/src/Computation.kt diff --git a/Usability/Destructuring Declarations/Examples/src/DestructuringEx1.kt b/Usability/Destructuring Declarations/Examples/src/DestructuringEx1.kt new file mode 100644 index 00000000..9249a7a8 --- /dev/null +++ b/Usability/Destructuring Declarations/Examples/src/DestructuringEx1.kt @@ -0,0 +1,22 @@ +// Destructuring/DestructuringEx1.kt +package destructuringex1 +import atomictest.eq + +fun calculate(n1: Int, n2: Int): + Triple { + if(n1 < 0 || n2 < 0) + return Triple(false, 0, 0) + return Triple(true, n1 + n2, n1 * n2) +} + +fun main() { + val result = calculate(5, 7) + result.first eq true + result.second eq 12 + result.third eq 35 + val (success, plus, multiply) = + calculate(11, 13) + success eq true + plus eq 24 + multiply eq 143 +} \ No newline at end of file diff --git a/Usability/Destructuring Declarations/Examples/src/DestructuringEx2.kt b/Usability/Destructuring Declarations/Examples/src/DestructuringEx2.kt new file mode 100644 index 00000000..a7c83d10 --- /dev/null +++ b/Usability/Destructuring Declarations/Examples/src/DestructuringEx2.kt @@ -0,0 +1,23 @@ +// Destructuring/DestructuringEx2.kt +package destructuringex2 +import atomictest.eq + +class Computation( + val data: Int, + val info: String +) { + operator fun component1() = data + operator fun component2() = info +} + +fun evaluate(input: Int) = + if (input > 5) + Computation(input * 2, "High") + else + Computation(input * 2, "Low") + +fun main() { + val (value, description) = evaluate(7) + value eq 14 + description eq "High" +} \ No newline at end of file diff --git a/Usability/Destructuring Declarations/Examples/src/DestructuringEx3.kt b/Usability/Destructuring Declarations/Examples/src/DestructuringEx3.kt new file mode 100644 index 00000000..57fbb2d6 --- /dev/null +++ b/Usability/Destructuring Declarations/Examples/src/DestructuringEx3.kt @@ -0,0 +1,14 @@ +// Destructuring/DestructuringEx3.kt +package destructuringex3 +import atomictest.eq + +fun f() = Pair(true, Pair("Yes", 100)) + +fun main() { + // val (ok, (u, v)) = f() + val (ok, p) = f() + ok eq true + val (u, v) = p + u eq "Yes" + v eq 100 +} \ No newline at end of file diff --git a/Power Tools/Destructuring Declarations/Examples/src/ForLoop.kt b/Usability/Destructuring Declarations/Examples/src/ForLoop.kt similarity index 100% rename from Power Tools/Destructuring Declarations/Examples/src/ForLoop.kt rename to Usability/Destructuring Declarations/Examples/src/ForLoop.kt diff --git a/Power Tools/Destructuring Declarations/Examples/src/PairDestructuring.kt b/Usability/Destructuring Declarations/Examples/src/PairDestructuring.kt similarity index 100% rename from Power Tools/Destructuring Declarations/Examples/src/PairDestructuring.kt rename to Usability/Destructuring Declarations/Examples/src/PairDestructuring.kt diff --git a/Power Tools/Destructuring Declarations/Examples/src/Pairs.kt b/Usability/Destructuring Declarations/Examples/src/Pairs.kt similarity index 100% rename from Power Tools/Destructuring Declarations/Examples/src/Pairs.kt rename to Usability/Destructuring Declarations/Examples/src/Pairs.kt diff --git a/Power Tools/Destructuring Declarations/Examples/src/Tuple.kt b/Usability/Destructuring Declarations/Examples/src/Tuple.kt similarity index 100% rename from Power Tools/Destructuring Declarations/Examples/src/Tuple.kt rename to Usability/Destructuring Declarations/Examples/src/Tuple.kt diff --git a/Power Tools/Destructuring Declarations/Examples/task-info.yaml b/Usability/Destructuring Declarations/Examples/task-info.yaml similarity index 60% rename from Power Tools/Destructuring Declarations/Examples/task-info.yaml rename to Usability/Destructuring Declarations/Examples/task-info.yaml index 554059f1..599f1621 100644 --- a/Power Tools/Destructuring Declarations/Examples/task-info.yaml +++ b/Usability/Destructuring Declarations/Examples/task-info.yaml @@ -10,3 +10,9 @@ files: visible: true - name: src/ForLoop.kt visible: true +- name: src/DestructuringEx1.kt + visible: true +- name: src/DestructuringEx2.kt + visible: true +- name: src/DestructuringEx3.kt + visible: true diff --git a/Power Tools/Destructuring Declarations/Examples/task.md b/Usability/Destructuring Declarations/Examples/task.md similarity index 100% rename from Power Tools/Destructuring Declarations/Examples/task.md rename to Usability/Destructuring Declarations/Examples/task.md diff --git a/Usability/Destructuring Declarations/Exercise 1/src/Task.kt b/Usability/Destructuring Declarations/Exercise 1/src/Task.kt new file mode 100644 index 00000000..41735e5d --- /dev/null +++ b/Usability/Destructuring Declarations/Exercise 1/src/Task.kt @@ -0,0 +1,3 @@ +package destructuringDeclarationsExercise1 + +// type your solution here \ No newline at end of file diff --git a/Usability/Destructuring Declarations/Exercise 1/task-info.yaml b/Usability/Destructuring Declarations/Exercise 1/task-info.yaml new file mode 100644 index 00000000..7ad1b827 --- /dev/null +++ b/Usability/Destructuring Declarations/Exercise 1/task-info.yaml @@ -0,0 +1,6 @@ +type: edu +files: +- name: src/Task.kt + visible: true +- name: test/Tests.kt + visible: false diff --git a/Usability/Destructuring Declarations/Exercise 1/task.md b/Usability/Destructuring Declarations/Exercise 1/task.md new file mode 100644 index 00000000..92295d43 --- /dev/null +++ b/Usability/Destructuring Declarations/Exercise 1/task.md @@ -0,0 +1,39 @@ +## Destructuring Declarations (#1) + +Using `Pairs.kt` as a model, write a function `calculate(n1: Int, n2: Int)` +which returns a `Triple` containing a `Boolean` and two `Int`s. If either `n1` +or `n2` is less than zero, it returns `false` and two zeros. Otherwise, it +returns a `Triple` containing: + +- `true` +- The sum of `n1` and `n2` +- `n1` multiplied by `n2` + +The starter code contains a `main()` with tests, showing the different between +unpacking the `Triple` using `first`, `second` and `third` versus a +destructuring declaration. + +```kotlin +// Destructuring/DestructuringEx1.kt +package destructuringex1 +import atomictest.eq + +fun calculate(n1: Int, n2: Int): + Triple { + if(n1 < 0 || n2 < 0) + return Triple(false, 0, 0) + return Triple(true, n1 + n2, n1 * n2) +} + +fun main() { + val result = calculate(5, 7) + result.first eq true + result.second eq 12 + result.third eq 35 + val (success, plus, multiply) = + calculate(11, 13) + success eq true + plus eq 24 + multiply eq 143 +} +``` \ No newline at end of file diff --git a/Usability/Destructuring Declarations/Exercise 1/test/Tests.kt b/Usability/Destructuring Declarations/Exercise 1/test/Tests.kt new file mode 100644 index 00000000..ebb92fb1 --- /dev/null +++ b/Usability/Destructuring Declarations/Exercise 1/test/Tests.kt @@ -0,0 +1,11 @@ +package destructuringDeclarationsExercise1 + +import org.junit.Assert +import org.junit.Test + +class TestDestructuringDeclarationsExercise1 { + @Test fun testSolution() { + //TODO: implement your test here + Assert.assertTrue("Tests not implemented for the task", false) + } +} \ No newline at end of file diff --git a/Usability/Destructuring Declarations/Exercise 2/src/Task.kt b/Usability/Destructuring Declarations/Exercise 2/src/Task.kt new file mode 100644 index 00000000..8bd25fdb --- /dev/null +++ b/Usability/Destructuring Declarations/Exercise 2/src/Task.kt @@ -0,0 +1,3 @@ +package destructuringDeclarationsExercise2 + +// type your solution here \ No newline at end of file diff --git a/Usability/Destructuring Declarations/Exercise 2/task-info.yaml b/Usability/Destructuring Declarations/Exercise 2/task-info.yaml new file mode 100644 index 00000000..7ad1b827 --- /dev/null +++ b/Usability/Destructuring Declarations/Exercise 2/task-info.yaml @@ -0,0 +1,6 @@ +type: edu +files: +- name: src/Task.kt + visible: true +- name: test/Tests.kt + visible: false diff --git a/Usability/Destructuring Declarations/Exercise 2/task.md b/Usability/Destructuring Declarations/Exercise 2/task.md new file mode 100644 index 00000000..2b83ceb8 --- /dev/null +++ b/Usability/Destructuring Declarations/Exercise 2/task.md @@ -0,0 +1,39 @@ +## Destructuring Declarations (#2) + +If you do not define a class as a `data` class, you must add extra functions to +allow that class to be used in a destructuring declaration. Start with +`Computation.kt` and remove the `data` from the definition of `Computation`. +The code no longer compiles. Intellij IDEA will prompt you and automatically +fill in the skeleton definitions for `operator fun component1()` and `operator +fun component2()`, or you may do this by hand. (Note: we do not cover the +`operator` keyword until [Operator Overloading], but you don't need to +understand it for this exercise). Provide the correct bodies for these +functions and show that the rest of the code still works without modifying it. +Consider how much more work (and visual noise) results from more fields in the +class, and how much effort is saved by using `data` classes. + +```kotlin +// Destructuring/DestructuringEx2.kt +package destructuringex2 +import atomictest.eq + +class Computation( + val data: Int, + val info: String +) { + operator fun component1() = data + operator fun component2() = info +} + +fun evaluate(input: Int) = + if (input > 5) + Computation(input * 2, "High") + else + Computation(input * 2, "Low") + +fun main() { + val (value, description) = evaluate(7) + value eq 14 + description eq "High" +} +``` \ No newline at end of file diff --git a/Usability/Destructuring Declarations/Exercise 2/test/Tests.kt b/Usability/Destructuring Declarations/Exercise 2/test/Tests.kt new file mode 100644 index 00000000..3ac64aeb --- /dev/null +++ b/Usability/Destructuring Declarations/Exercise 2/test/Tests.kt @@ -0,0 +1,11 @@ +package destructuringDeclarationsExercise2 + +import org.junit.Assert +import org.junit.Test + +class TestDestructuringDeclarationsExercise2 { + @Test fun testSolution() { + //TODO: implement your test here + Assert.assertTrue("Tests not implemented for the task", false) + } +} \ No newline at end of file diff --git a/Usability/Destructuring Declarations/Exercise 3/src/Task.kt b/Usability/Destructuring Declarations/Exercise 3/src/Task.kt new file mode 100644 index 00000000..b8e72d1b --- /dev/null +++ b/Usability/Destructuring Declarations/Exercise 3/src/Task.kt @@ -0,0 +1,3 @@ +package destructuringDeclarationsExercise3 + +// type your solution here \ No newline at end of file diff --git a/Usability/Destructuring Declarations/Exercise 3/task-info.yaml b/Usability/Destructuring Declarations/Exercise 3/task-info.yaml new file mode 100644 index 00000000..7ad1b827 --- /dev/null +++ b/Usability/Destructuring Declarations/Exercise 3/task-info.yaml @@ -0,0 +1,6 @@ +type: edu +files: +- name: src/Task.kt + visible: true +- name: test/Tests.kt + visible: false diff --git a/Usability/Destructuring Declarations/Exercise 3/task.md b/Usability/Destructuring Declarations/Exercise 3/task.md new file mode 100644 index 00000000..42d9f821 --- /dev/null +++ b/Usability/Destructuring Declarations/Exercise 3/task.md @@ -0,0 +1,25 @@ +## Destructuring Declarations (#3) + +Write a function `f()` that returns a `Pair` containing `true` along with a +second nested `Pair` containing "Yes" and 100. In `main()`, attempt to write +a destructuring declaration that unpacks the `Boolean` along with both parts +of the nested `Pair` in a single statement. Now unpack the result of `f()` in +two steps: first capture the two components of the outer `Pair`, then unpack +the two components of the nested `Pair`. + +```kotlin +// Destructuring/DestructuringEx3.kt +package destructuringex3 +import atomictest.eq + +fun f() = Pair(true, Pair("Yes", 100)) + +fun main() { + // val (ok, (u, v)) = f() + val (ok, p) = f() + ok eq true + val (u, v) = p + u eq "Yes" + v eq 100 +} +``` \ No newline at end of file diff --git a/Usability/Destructuring Declarations/Exercise 3/test/Tests.kt b/Usability/Destructuring Declarations/Exercise 3/test/Tests.kt new file mode 100644 index 00000000..8d3c0d11 --- /dev/null +++ b/Usability/Destructuring Declarations/Exercise 3/test/Tests.kt @@ -0,0 +1,11 @@ +package destructuringDeclarationsExercise3 + +import org.junit.Assert +import org.junit.Test + +class TestDestructuringDeclarationsExercise3 { + @Test fun testSolution() { + //TODO: implement your test here + Assert.assertTrue("Tests not implemented for the task", false) + } +} \ No newline at end of file diff --git a/Usability/Destructuring Declarations/lesson-info.yaml b/Usability/Destructuring Declarations/lesson-info.yaml new file mode 100644 index 00000000..c9fb967a --- /dev/null +++ b/Usability/Destructuring Declarations/lesson-info.yaml @@ -0,0 +1,5 @@ +content: +- Examples +- Exercise 1 +- Exercise 2 +- Exercise 3 diff --git a/Usability/section-info.yaml b/Usability/section-info.yaml index c88505d2..ff6ab724 100644 --- a/Usability/section-info.yaml +++ b/Usability/section-info.yaml @@ -5,6 +5,7 @@ content: - when Expressions - Enumerations - Data Classes +- Destructuring Declarations - Nullable Types - Safe Calls & the Elvis Operator - Non-null Assertions diff --git a/util/test/TestAllExamples.java b/util/test/TestAllExamples.java index 66e5ebda..6a9c2fd0 100644 --- a/util/test/TestAllExamples.java +++ b/util/test/TestAllExamples.java @@ -1006,6 +1006,46 @@ public class TestAllExamples extends AbstractTestExamples { testExample("../AtomicKotlinCourse/Usability/Data Classes/Examples/src/Simple.kt", SimpleKt::main); } + @Test + public void testDestructuringEx3() { + testExample("../AtomicKotlinCourse/Usability/Destructuring Declarations/Examples/src/DestructuringEx3.kt", destructuringex3.DestructuringEx3Kt::main); + } + + @Test + public void testComputation() { + testExample("../AtomicKotlinCourse/Usability/Destructuring Declarations/Examples/src/Computation.kt", destructuring.ComputationKt::main); + } + + @Test + public void testDestructuringEx2() { + testExample("../AtomicKotlinCourse/Usability/Destructuring Declarations/Examples/src/DestructuringEx2.kt", destructuringex2.DestructuringEx2Kt::main); + } + + @Test + public void testPairDestructuring() { + testExample("../AtomicKotlinCourse/Usability/Destructuring Declarations/Examples/src/PairDestructuring.kt", destructuring.PairDestructuringKt::main); + } + + @Test + public void testDestructuringEx1() { + testExample("../AtomicKotlinCourse/Usability/Destructuring Declarations/Examples/src/DestructuringEx1.kt", destructuringex1.DestructuringEx1Kt::main); + } + + @Test + public void testForLoop() { + testExample("../AtomicKotlinCourse/Usability/Destructuring Declarations/Examples/src/ForLoop.kt", ForLoopKt::main); + } + + @Test + public void testTuple() { + testExample("../AtomicKotlinCourse/Usability/Destructuring Declarations/Examples/src/Tuple.kt", destructuring.TupleKt::main); + } + + @Test + public void testPairs() { + testExample("../AtomicKotlinCourse/Usability/Destructuring Declarations/Examples/src/Pairs.kt", destructuring.PairsKt::main); + } + @Test public void testExplicitCheck() { testExample("../AtomicKotlinCourse/Usability/Nullable Types/Examples/src/ExplicitCheck.kt", ExplicitCheckKt::main); @@ -1613,7 +1653,7 @@ public class TestAllExamples extends AbstractTestExamples { @Test public void testExploreMaze() { - testExample("../AtomicKotlinCourse/Object-Oriented Programming/Object-Oriented Design/Examples/src/ExploreMaze.kt", robotexplorer.ExploreMazeKt::main); + testExample("../AtomicKotlinCourse/Object-Oriented Programming/Object-Oriented Design/Examples/src/ExploreMaze.kt", robotexplorer1.ExploreMazeKt::main); } @Test @@ -1686,11 +1726,6 @@ public class TestAllExamples extends AbstractTestExamples { testExample("../AtomicKotlinCourse/Object-Oriented Programming/Base Class Initialization/Examples/src/BCIExercise3.kt", baseclassinit.BCIExercise3Kt::main); } - @Test - public void testExploreMaze2() { -// testExample("../AtomicKotlinCourse/Object-Oriented Programming/Base Class Initialization/Examples/src/ExploreMaze2.kt", robotexplorer2.ExploreMaze2Kt::main); - } - @Test public void testBCIExercise2() { testExample("../AtomicKotlinCourse/Object-Oriented Programming/Base Class Initialization/Examples/src/BCIExercise2.kt", baseclassinit.BCIExercise2Kt::main); @@ -1876,49 +1911,19 @@ public class TestAllExamples extends AbstractTestExamples { testExample("../AtomicKotlinCourse/Object-Oriented Programming/Inheritance & Extensions/Examples/src/InhExtensionsEx1.kt", inheritanceextensionsex1.InhExtensionsEx1Kt::main); } - @Test - public void testDesigningWIEx1() { - testExample("../AtomicKotlinCourse/Object-Oriented Programming/Designing with Inheritance/Examples/src/DesigningWIEx1.kt", designingwithinheritanceex1.DesigningWIEx1Kt::main); - } - - @Test - public void testDesigningWIEx3() { - testExample("../AtomicKotlinCourse/Object-Oriented Programming/Designing with Inheritance/Examples/src/DesigningWIEx3.kt", designingwithinheritanceex3.DesigningWIEx3Kt::main); - } - - @Test - public void testDesigningWIEx2() { - testExample("../AtomicKotlinCourse/Object-Oriented Programming/Designing with Inheritance/Examples/src/DesigningWIEx2.kt", designingwithinheritanceex2.DesigningWIEx2Kt::main); - } - - @Test - public void testUsingLists() { - testExample("../AtomicKotlinCourse/Object-Oriented Programming/Designing with Inheritance/Examples/src/UsingLists.kt", designingwithinheritance.UsingListsKt::main); - } - - @Test - public void testBeverages() { - testExample("../AtomicKotlinCourse/Object-Oriented Programming/Designing with Inheritance/Examples/src/Beverages.kt", BeveragesKt::main); - } - - @Test - public void testMutableMaze() { - testExample("../AtomicKotlinCourse/Object-Oriented Programming/Designing with Inheritance/Examples/src/MutableMaze.kt", designingwithinheritance.MutableMazeKt::main); - } - @Test public void testExtensibilityEx1() { testExample("../AtomicKotlinCourse/Object-Oriented Programming/Extensibility/Examples/src/ExtensibilityEx1.kt", designingwithinheritanceex1.ExtensibilityEx1Kt::main); } @Test - public void testExploreMaze3() { - testExample("../AtomicKotlinCourse/Object-Oriented Programming/Extensibility/Examples/src/ExploreMaze3.kt", robotexplorer3.ExploreMaze3Kt::main); + public void testExtensibilityEx2() { + testExample("../AtomicKotlinCourse/Object-Oriented Programming/Extensibility/Examples/src/ExtensibilityEx2.kt", designingwithinheritanceex2.ExtensibilityEx2Kt::main); } @Test - public void testExtensibilityEx2() { - testExample("../AtomicKotlinCourse/Object-Oriented Programming/Extensibility/Examples/src/ExtensibilityEx2.kt", designingwithinheritanceex2.ExtensibilityEx2Kt::main); + public void testExploreMaze2() { + testExample("../AtomicKotlinCourse/Object-Oriented Programming/Extensibility/Examples/src/ExploreMaze2.kt", robotexplorer2.ExploreMaze2Kt::main); } @Test @@ -2111,6 +2116,11 @@ public class TestAllExamples extends AbstractTestExamples { testExample("../AtomicKotlinCourse/Object-Oriented Programming/Companion Objects/Examples/src/NamedCompanionObject.kt", NamedCompanionObjectKt::main); } + @Test + public void testExploreMaze3() { + testExample("../AtomicKotlinCourse/Object-Oriented Programming/OO Design, Revisited/Examples/src/ExploreMaze3.kt", robotexplorer3.ExploreMaze3Kt::main); + } + @Test public void testTryFinally() { testExample("../AtomicKotlinCourse/Preventing Failure/Exception Handling/Examples/src/TryFinally.kt", exceptionhandling.TryFinallyKt::main); @@ -2411,31 +2421,6 @@ public class TestAllExamples extends AbstractTestExamples { testExample("../AtomicKotlinCourse/Power Tools/Hashing/Examples/src/UnpredictableHashing.kt", UnpredictableHashingKt::main); } - @Test - public void testComputation() { - testExample("../AtomicKotlinCourse/Power Tools/Destructuring Declarations/Examples/src/Computation.kt", destructuring.ComputationKt::main); - } - - @Test - public void testPairDestructuring() { - testExample("../AtomicKotlinCourse/Power Tools/Destructuring Declarations/Examples/src/PairDestructuring.kt", destructuring.PairDestructuringKt::main); - } - - @Test - public void testForLoop() { - testExample("../AtomicKotlinCourse/Power Tools/Destructuring Declarations/Examples/src/ForLoop.kt", ForLoopKt::main); - } - - @Test - public void testTuple() { - testExample("../AtomicKotlinCourse/Power Tools/Destructuring Declarations/Examples/src/Tuple.kt", destructuring.TupleKt::main); - } - - @Test - public void testPairs() { - testExample("../AtomicKotlinCourse/Power Tools/Destructuring Declarations/Examples/src/Pairs.kt", destructuring.PairsKt::main); - } - @Test public void testMemberOperator() { testExample("../AtomicKotlinCourse/Power Tools/Operator Overloading/Examples/src/MemberOperator.kt", operatoroverloading.MemberOperatorKt::main); @@ -3546,36 +3531,11 @@ public class TestAllExamples extends AbstractTestExamples { testExample("../AtomicKotlinCourse/Functional Programming/Recursion/Exercise 4/src/Task.kt", recursionExercise4.TaskKt::main); } - @Test - public void testGameMatrix() { - testExample("../AtomicKotlinCourse/Object-Oriented Programming/Interfaces/Exercise 4/src/GameMatrix.kt", interfacesExercise4.GameMatrixKt::main); - } - - @Test - public void testMaze() { - testExample("../AtomicKotlinCourse/Object-Oriented Programming/Complex Constructors/Exercise 4/src/Maze.kt", complexConstructorsExercise4.MazeKt::main); - } - @Test public void testGardenItem1() { testExample("../AtomicKotlinCourse/Object-Oriented Programming/Secondary Constructors/Exercise 3/src/GardenItem.kt", secondaryConstructorsExercise3.GardenItemKt::main); } - @Test - public void testBomb() { - testExample("../AtomicKotlinCourse/Object-Oriented Programming/Inheritance/Exercise 4/src/Bomb.kt", inheritanceExercise4.BombKt::main); - } - - @Test - public void testGameElements() { - testExample("../AtomicKotlinCourse/Object-Oriented Programming/Base Class Initialization/Exercise 4/src/GameElements.kt", baseClassInitializationExercise4.GameElementsKt::main); - } - - @Test - public void testRobot() { - testExample("../AtomicKotlinCourse/Object-Oriented Programming/Abstract Classes/Exercise 1/src/Robot.kt", abstractClassesExercise1.RobotKt::main); - } - @Test public void testTask194() { testExample("../AtomicKotlinCourse/Power Tools/Lambda with Receiver/Exercise 1/src/Task.kt", lambdaWithReceiverExercise1.TaskKt::main); diff --git a/util/test/TestAllExercises.kt b/util/test/TestAllExercises.kt index f1b803bd..77fad6a3 100644 --- a/util/test/TestAllExercises.kt +++ b/util/test/TestAllExercises.kt @@ -353,6 +353,15 @@ class TestAllExercises : AbstractTestExercises() { @Test fun testDataClassesExercise3() = testClass(dataClassesExercise3.TestDataClassesExercise3::class) + @Test + fun testDestructuringDeclarationsExercise1() = testClass(destructuringDeclarationsExercise1.TestDestructuringDeclarationsExercise1::class) + + @Test + fun testDestructuringDeclarationsExercise2() = testClass(destructuringDeclarationsExercise2.TestDestructuringDeclarationsExercise2::class) + + @Test + fun testDestructuringDeclarationsExercise3() = testClass(destructuringDeclarationsExercise3.TestDestructuringDeclarationsExercise3::class) + @Test fun testNullableTypesExercise1() = testClass(nullableTypesExercise1.TestNullableTypesExercise1::class) @@ -563,9 +572,6 @@ class TestAllExercises : AbstractTestExercises() { @Test fun testInterfacesExercise3() = testClass(interfacesExercise3.TestInterfacesExercise3::class) - @Test - fun testInterfacesExercise4() = testClass(interfacesExercise4.TestInterfacesExercise4::class) - @Test fun testComplexConstructorsExercise1() = testClass(complexConstructorsExercise1.TestComplexConstructorsExercise1::class) @@ -575,9 +581,6 @@ class TestAllExercises : AbstractTestExercises() { @Test fun testComplexConstructorsExercise3() = testClass(complexConstructorsExercise3.TestComplexConstructorsExercise3::class) - @Test - fun testComplexConstructorsExercise4() = testClass(complexConstructorsExercise4.TestComplexConstructorsExercise4::class) - @Test fun testSecondaryConstructorsExercise1() = testClass(secondaryConstructorsExercise1.TestSecondaryConstructorsExercise1::class) @@ -596,9 +599,6 @@ class TestAllExercises : AbstractTestExercises() { @Test fun testInheritanceExercise3() = testClass(inheritanceExercise3.TestInheritanceExercise3::class) - @Test - fun testInheritanceExercise4() = testClass(inheritanceExercise4.TestInheritanceExercise4::class) - @Test fun testBaseClassInitializationExercise1() = testClass(baseClassInitializationExercise1.TestBaseClassInitializationExercise1::class) @@ -609,10 +609,49 @@ class TestAllExercises : AbstractTestExercises() { fun testBaseClassInitializationExercise3() = testClass(baseClassInitializationExercise3.TestBaseClassInitializationExercise3::class) @Test - fun testBaseClassInitializationExercise4() = testClass(baseClassInitializationExercise4.TestBaseClassInitializationExercise4::class) + fun testAbstractClassesExercise1() = testClass(abstractClassesExercise1.TestAbstractClassesExercise1::class) @Test - fun testAbstractClassesExercise1() = testClass(abstractClassesExercise1.TestAbstractClassesExercise1::class) + fun testAbstractClassesExercise2() = testClass(abstractClassesExercise2.TestAbstractClassesExercise2::class) + + @Test + fun testAbstractClassesExercise3() = testClass(abstractClassesExercise3.TestAbstractClassesExercise3::class) + + @Test + fun testUpcastingExercise1() = testClass(upcastingExercise1.TestUpcastingExercise1::class) + + @Test + fun testUpcastingExercise2() = testClass(upcastingExercise2.TestUpcastingExercise2::class) + + @Test + fun testUpcastingExercise3() = testClass(upcastingExercise3.TestUpcastingExercise3::class) + + @Test + fun testPolymorphismExercise1() = testClass(polymorphismExercise1.TestPolymorphismExercise1::class) + + @Test + fun testPolymorphismExercise2() = testClass(polymorphismExercise2.TestPolymorphismExercise2::class) + + @Test + fun testPolymorphismExercise3() = testClass(polymorphismExercise3.TestPolymorphismExercise3::class) + + @Test + fun testCompositionExercise1() = testClass(compositionExercise1.TestCompositionExercise1::class) + + @Test + fun testCompositionExercise2() = testClass(compositionExercise2.TestCompositionExercise2::class) + + @Test + fun testCompositionExercise3() = testClass(compositionExercise3.TestCompositionExercise3::class) + + @Test + fun testInheritanceAndExtensionsExercise1() = testClass(inheritanceAndExtensionsExercise1.TestInheritanceAndExtensionsExercise1::class) + + @Test + fun testInheritanceAndExtensionsExercise2() = testClass(inheritanceAndExtensionsExercise2.TestInheritanceAndExtensionsExercise2::class) + + @Test + fun testInheritanceAndExtensionsExercise3() = testClass(inheritanceAndExtensionsExercise3.TestInheritanceAndExtensionsExercise3::class) @Test fun testLambdaWithReceiverExercise1() = testClass(lambdaWithReceiverExercise1.TestLambdaWithReceiverExercise1::class)