Skip to content

Replace nondeterministic performantTraversables #97

New issue

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

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

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Dec 10, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 12 additions & 16 deletions src/main/scala/stdlib/Traversables.scala
Original file line number Diff line number Diff line change
Expand Up @@ -511,23 +511,19 @@ object Traversables extends FlatSpec with Matchers with org.scalaexercises.defin
intList.min should be(res3)
}

/** You would choose `foldLeft`/`reduceLeft` or `foldRight`/`reduceRight` based on your mathematical goal. One other reason for deciding is performance - `foldLeft` generally has better performance since it uses tail recursion. This exercise will either work fine or you will receive a `StackOverflowError`:
/** The naive recursive implementation of `reduceRight` is not tail recursive and would lead to a stack overflow if used on larger traversables.
* However, `reduceLeft` can be implemented with tail recursion.
*
* To avoid the potential stack overflow with the naive implementation of `reduceRight` we can easily implement it based on `reduceLeft` by reverting the list and the inverting the reduce function.
* The same applies for folding operations.
*
* There is also a `reduce` (and `fold`) available, which works exactly like `reduceLeft` (and `foldLeft`) and it should be the prefered method to call unless there is a strong reason to use `reduceRight` (or `foldRight`).
*/
def performantTraversables(res0: Boolean) {
val MAX_SIZE = 1000000
val reduceLeftStartTime = new java.util.Date
(1 to MAX_SIZE) reduceLeft (_ + _)
val reduceLeftEndTime = new java.util.Date

val reduceRightStartTime = new java.util.Date
(1 to MAX_SIZE) reduceRight (_ + _)
val reduceRightEndTime = new java.util.Date

val totalReduceLeftTime = reduceLeftEndTime.getTime - reduceLeftStartTime.getTime
val totalReduceRightTime = reduceRightEndTime.getTime - reduceRightStartTime
.getTime

(totalReduceRightTime > totalReduceLeftTime) should be(res0)
def reduceRightAsReduceLeft(res0: Int, res1: Int, res2: Int) {
val intList = List(5, 4, 3, 2, 1)
intList.reduceRight((x, y) => x - y) should be(res0)
intList.reverse.reduceLeft((x, y) => y - x) should be(res1)
intList.reverse.reduce((x, y) => y - x) should be(res2)
}

/** `transpose` will take a traversable of traversables and group them by their position in it's own traversable, e.g.:
Expand Down
17 changes: 8 additions & 9 deletions src/test/scala/stdlib/TraversablesSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -441,15 +441,14 @@ class TraversablesSpec extends Spec with Checkers {
)
}

// FIXME: this test depends on runtime timing of code
// def `performant traversals` = {
// check(
// Test.testSuccess(
// Traversables.performantTraversables _,
// false :: HNil
// )
// )
// }
def `reduceRight as reduceLeft` = {
check(
Test.testSuccess(
Traversables.reduceRightAsReduceLeft _,
3 :: 3 :: 3 :: HNil
)
)
}

def `transpose function` = {
check(
Expand Down