-
Notifications
You must be signed in to change notification settings - Fork 2
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
Problem 1 [Language]: Multiples of 3 and 5 #14
Comments
The advantage of going to a conference like Scala eXchange is that you learn new tricks. And so I stumbled over the (1 until 1000).filter(l => l % 3 == 0 || l % 5 == 0).sum The var result = 0
(1 until 1000).withFilter(l => l % 3 == 0 || l % 5 == 0).foreach(result += _)
result But not being happy with the very basic methods of
The (1 until 1000).view.filter(l => l % 3 == 0 || l % 5 == 0).sum |
In addition to Problem005, I also committed an over-engineered solution for Problem001. The best and most straightforward solution is simply: (1 until 1000).filter(l => l % 3 == 0 || l % 5 == 0).sum But we can try to model our own Range object and explore some Scala features. P001: Range model It has two methods, There is also a companion object that allow us to initialize a TotalRange. P001: controlling invariants on constructor P001: adding filtering At that point it must be obvious why we had initially a next(n:Int) and previous(n:Int). Methods Calling def withFilter(filter: (Int) => Boolean) : Range = {
FilteredRange(this, filterFunc && filter) // must more elegant
} P001: foldLeft with Monoid It's just a construct with two methods:
A Monoid trait looks like: trait Monoid[T] {
def zero:T
def append(left:T, right:T) An object IntAddMonoid extends Monoid[Int] {
def zero = 0
def append(left:Int, right:Int) = left + right
} and a object ListIntMonoid extends Monoid[List[Int]] {
def zero = List[Int]() // zero is an empty list
def append(left:List[Int], right:List[Int]) = left ++ right // merge two Lists
} Now we move out the def foldLeft[T](z: T)(op: (T, Int) => T) : T = {
@tailrec
def loop(num:Int, acc:T) : T = {
if (num > end) acc
else if (num == end) op(acc, num)
else loop(next(num), op(acc, num))
}
loop(begin, z)
} Note: this implementation has the second parameter of the function And now the definition of a private def foldLeftMonoid[T](monoid:Monoid[T])(builder: (Int) => T) : T = {
foldLeft(monoid.zero) { (acc, num) =>
monoid.append(acc, builder(num))
}
} Note the Following we can see how to implement both def sum: Int = foldLeftMonoid(IntAddMonoid)(identity)
def toList: List[Int] = foldLeftMonoid(ListIntMonoid) { n => List(n) } Note: the The def identity[A](x: A): A = x For any given type A return the same value. P005: adds from/to/until 'dsl' and problem solution The last commit introduces a DSL to build ranges. It uses anonymous objects to create an intermediary object that will finally build a range. object Range {
def apply(start: Int, end: Int) : Range = TotalRange(start, end)
def from(start:Int) = new {
def to(end:Int) : Range = TotalRange(start, end)
def until(end:Int) : Range = TotalRange(start, end - 1)
}
} And you can use it as: val range = Range.from(1).until(10) This over-engineered solution has impressive performance! Compare it with the collection impl and the pure loop impl added on my Problem005 solution. |
How does the solution using Set, as demonstrated in one of the solutions, work ?
Answer:
Scala Sets work as mathematical sets. Every value of a set is unique within that set, i.e. there are no duplicates.
The Scala Set collection defines a number of useful operations that allow you to combine two sets.
For example, taking the union of two sets can be done using the
++
operator.For example:
will print the following:
As can be seen, Sets are unordered. Note that, in case you need an ordered Set, there is an implementation of such an animal in the Scala collection library.
As a bonus, there are other useful operators on Set such as
&
and&~
as demonstrated here:You should be able to figure out what these do for yourself. Quite powerful these Scala collections...
The text was updated successfully, but these errors were encountered: