Skip to content

Commit c0b5885

Browse files
committed
Add more exercises
1 parent b6ef557 commit c0b5885

18 files changed

+203
-26
lines changed

src/main/scala/scalatutorial/sections/DefinitionsAndEvaluation.scala

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,19 @@ object DefinitionsAndEvaluation extends ScalaTutorialSection {
204204
* corresponding parameter is unused in the evaluation of the function body.
205205
*
206206
* Scala normally uses call-by-value.
207+
*
208+
* = Exercise =
209+
*
210+
* Complete the following definition of the `triangleArea` function,
211+
* which takes a triangle base and height as parameters and returns
212+
* its area:
207213
*/
208-
def nothing(): Unit = ()
214+
def triangleAreaExercise(res0: Double, res1: Double): Unit = {
215+
def triangleArea(base: Double, height: Double): Double =
216+
base * height / res0
217+
218+
triangleArea(3, 4) shouldBe 6
219+
triangleArea(5, 6) shouldBe res1
220+
}
209221

210222
}

src/main/scala/scalatutorial/sections/ImperativeProgramming.scala

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -320,14 +320,33 @@ object ImperativeProgramming extends ScalaTutorialSection {
320320
* Example:
321321
*
322322
* {{{
323-
* for (i <- 1 until 3; j <- "abc") println(i + " " + j)
323+
* for (i <- 1 until 3; j <- "abc") println(s"$i $j")
324324
* }}}
325325
*
326326
* translates to:
327327
*
328328
* {{{
329-
* (1 until 3) foreach (i => "abc" foreach (j => println(i + " " + j)))
329+
* (1 until 3) foreach (i => "abc" foreach (j => println(s"$i $j")))
330330
* }}}
331+
*
332+
* = Exercise =
333+
*
334+
* Complete the following imperative implementation of `factorial`:
331335
*/
332-
def nothing(): Unit = ()
336+
def factorialExercise(res0: Int, res1: Int, res2: Int): Unit = {
337+
def factorial(n: Int): Int = {
338+
var result = res0
339+
var i = res1
340+
while (i <= n) {
341+
result = result * i
342+
i = i + res2
343+
}
344+
result
345+
}
346+
347+
factorial(2) shouldBe 2
348+
factorial(3) shouldBe 6
349+
factorial(4) shouldBe 24
350+
factorial(5) shouldBe 120
351+
}
333352
}

src/main/scala/scalatutorial/sections/LexicalScopes.scala

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,22 @@ object LexicalScopes extends ScalaTutorialSection {
267267
* {{{
268268
* $ scala Hello
269269
* }}}
270+
*
271+
* = Exercise =
272+
*
270273
*/
271-
def nothing(): Unit = ()
274+
def objectScopes(res0: Int): Unit = {
275+
object Foo {
276+
val x = 1
277+
}
278+
object Bar {
279+
val x = 2
280+
}
281+
object Baz {
282+
import Bar.x
283+
val y = x + Foo.x
284+
}
285+
286+
Baz.y shouldBe res0
287+
}
272288
}

src/main/scala/scalatutorial/sections/ObjectOrientedProgramming.scala

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,7 @@ object ObjectOrientedProgramming extends ScalaTutorialSection {
304304
* a computation model based on substitution. Now we extend this
305305
* model to classes and objects.
306306
*
307-
* How is an instantiation of the class `new C(e1, …, en)` evaluted?
307+
* How is an instantiation of the class `new C(e1, …, en)` evaluated?
308308
*
309309
* The expression arguments `e1, …, en`
310310
* are evaluated like the arguments of a normal function. That's it.
@@ -627,6 +627,35 @@ object ObjectOrientedProgramming extends ScalaTutorialSection {
627627
* val y: String = null // y: String
628628
* val z: Int = null // error: type mismatch
629629
* }}}
630+
*
631+
* = Exercise =
632+
*
633+
* The following `Reducer` abstract class defines how to
634+
* reduce a list of values into a single value by starting
635+
* with an initial value and combining it with each element
636+
* of the list:
630637
*/
631-
def nothing(): Unit = ()
638+
def reducer(res0: Int, res1: Int): Unit = {
639+
abstract class Reducer(init: Int) {
640+
def combine(x: Int, y: Int): Int
641+
def reduce(xs: List[Int]): Int =
642+
xs match {
643+
case Nil => init
644+
case y :: ys => combine(y, reduce(ys))
645+
}
646+
}
647+
648+
object Product extends Reducer(1) {
649+
def combine(x: Int, y: Int): Int = x * y
650+
}
651+
652+
object Sum extends Reducer(0) {
653+
def combine(x: Int, y: Int): Int = x + y
654+
}
655+
656+
val nums = List(1, 2, 3, 4)
657+
658+
Product.reduce(nums) shouldBe res0
659+
Sum.reduce(nums) shouldBe res1
660+
}
632661
}

src/main/scala/scalatutorial/sections/PolymorphicTypes.scala

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -419,7 +419,21 @@ object PolymorphicTypes extends ScalaTutorialSection {
419419
*
420420
* - covariant type parameters may appear in lower bounds of method type parameters
421421
* - contravariant type parameters may appear in upper bounds of method
422+
*
423+
* = Exercise =
424+
*
425+
* Complete the following implementation of the `size` function that returns
426+
* the size of a given list.
422427
*/
423-
def nothing(): Unit = ()
428+
def sizeExercise(res0: Int, res1: Int): Unit = {
429+
def size[A](xs: List[A]): Int =
430+
xs match {
431+
case Nil => res0
432+
case y :: ys => res1 + size(ys)
433+
}
434+
size(Nil) shouldBe 0
435+
size(List(1, 2)) shouldBe 2
436+
size(List("a", "b", "c")) shouldBe 3
437+
}
424438

425439
}

src/main/scala/scalatutorial/sections/StandardLibrary.scala

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -261,21 +261,32 @@ object StandardLibrary extends ScalaTutorialSection {
261261
*
262262
* === Manipulating `Either[A, B]` Values ===
263263
*
264-
* `Either` has `map` and `flatMap`. These methods transform the `Right`
265-
* case only. Way say that `Either` is “right biased”:
264+
* Since Scala 2.12, `Either` has `map` and `flatMap`. These methods
265+
* transform the `Right` case only. Way say that `Either` is “right biased”:
266266
*
267267
* {{{
268268
* Right(1).map((x: Int) => x + 1) shouldBe Right(2)
269269
* Left("foo").map((x: Int) => x + 1) shouldBe Left("foo")
270270
* }}}
271271
*
272-
* `Either` also has a `filterOrElse` method that turn a `Right` value
272+
* `Either` also has a `filterOrElse` method that turns a `Right` value
273273
* into a `Left` value if it does not satisfy a given predicate:
274274
*
275275
* {{{
276276
* Right(1).filterOrElse(x => x % 2 == 0, "Odd value") shouldBe Left("Odd value")
277277
* }}}
278+
*
279+
* However, prior to Scala 2.12, `Either` was “unbiased”. You had to explicitly
280+
* specify which “side” (`Left` or `Right`) you wanted to `map`:
278281
*/
279-
def nothing(): Unit = ()
282+
def either(res0: Either[String, Int], res1: Either[String, Int]): Unit = {
283+
def triple(x: Int): Int = 3 * x
284+
285+
def tripleEither(x: Either[String, Int]): Either[String, Int] =
286+
x.right.map(triple)
287+
288+
tripleEither(Right(1)) shouldBe res0
289+
tripleEither(Left("not a number")) shouldBe res1
290+
}
280291

281292
}

src/main/scala/scalatutorial/sections/StructuringInformation.scala

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ object StructuringInformation extends ScalaTutorialSection {
4242
* val c3 = Note("C", "Quarter", 3)
4343
* }}}
4444
*
45+
* `c3` is a value that aggregates the arguments passed to the `Note`
46+
* constructor.
47+
*
4548
* Then, you can retrieve the information carried by each ''member'' (`name`,
4649
* `duration` and `octave`) by using the dot notation:
4750
*/
@@ -221,6 +224,28 @@ object StructuringInformation extends ScalaTutorialSection {
221224
* {{{
222225
* case class Note(name: String, duration: String, octave: Int) extends Symbol
223226
* }}}
227+
*
228+
* = Exercise =
229+
*
230+
* Consider the following algebraic data type that models note durations.
231+
* Complete the implementation of the function `fractionOfWhole`, which
232+
* takes as parameter a duration and returns the corresponding fraction
233+
* of the `Whole` duration.
224234
*/
225-
def nothing(): Unit = ()
235+
def adts(res0: Double, res1: Double): Unit = {
236+
sealed trait Duration
237+
case object Whole extends Duration
238+
case object Half extends Duration
239+
case object Quarter extends Duration
240+
241+
def fractionOfWhole(duration: Duration): Double =
242+
duration match {
243+
case Whole => 1.0
244+
case Half => res0
245+
case Quarter => res1
246+
}
247+
248+
fractionOfWhole(Half) shouldBe 0.5
249+
fractionOfWhole(Quarter) shouldBe 0.25
250+
}
226251
}

src/main/scala/scalatutorial/sections/TermsAndTypes.scala

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -164,13 +164,23 @@ object TermsAndTypes extends ScalaTutorialSection {
164164
/**
165165
* = Common Types =
166166
*
167-
* - `Int`: 32-bit integers
168-
* - `Double`: 64-bit floating point numbers
169-
* - `Boolean`: boolean values
170-
* - `String`: text
167+
* - `Int`: 32-bit integers (e.g. `1`, `23`, `456`)
168+
* - `Double`: 64-bit floating point numbers (e.g. `1.0`, `2.3`, `4.56`)
169+
* - `Boolean`: boolean values (`true` and `false`)
170+
* - `String`: text (e.g. `"foo"`, `"bar"`)
171171
*
172-
* Note that type names always begin with an upper case.
172+
* Note that type names always begin with an upper case letter.
173+
*
174+
* = Exercise =
175+
*
176+
* Here are some more methods of standard types. Can you guess what they do?
173177
*/
174-
def nothing(): Unit = ()
178+
def moreMethods(res0: String, res1: Boolean, res2: String): Unit = {
179+
16.toHexString shouldBe res0
180+
(0 to 10).contains(10) shouldBe true
181+
(0 until 10).contains(10) shouldBe res1
182+
"foo".drop(1) shouldBe "oo"
183+
"bar".take(2) shouldBe res2
184+
}
175185

176186
}

src/test/scala/scalatutorial/sections/DefinitionsAndEvaluationSpec.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,8 @@ class DefinitionsAndEvaluationSpec extends Spec with Checkers {
1616
check(Test.testSuccess(DefinitionsAndEvaluation.areaExercise _, 314.159 :: HNil))
1717
}
1818

19+
def `check triangle area`: Unit = {
20+
check(Test.testSuccess(DefinitionsAndEvaluation.triangleAreaExercise _, 2.0 :: 15.0 :: HNil))
21+
}
22+
1923
}

src/test/scala/scalatutorial/sections/HigherOrderFunctionsSpec.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ import shapeless.HNil
88

99
class HigherOrderFunctionsSpec extends Spec with Checkers {
1010

11-
def `check tail rec sum`: Unit = {
12-
check(Test.testSuccess(HigherOrderFunctions.tailRecSum _, 1 :: 0 :: HNil))
13-
}
11+
// def `check tail rec sum`: Unit = {
12+
// check(Test.testSuccess(HigherOrderFunctions.tailRecSum _, 1 :: 0 :: HNil))
13+
// }
1414

1515
}

0 commit comments

Comments
 (0)