Scala: One down

In the previous post, I completed my first attempt at the Project Euler problem: "Find the sum of all the multiples of 3 or 5 below 1000".

I was pretty happy with the result, but felt there was room for improvement - plus an opportunity to continue my investigations into the language.

Collections

After thinking about the problem a bit more, an alterative to iteratively or recursively going from 1 to 1000 (or vice-versa) and summing as we go, could be to get the set of numbers from 1 to 1000, find the ones which are divisible by 3 or 5, then summing up the resultant list.

This gave me an opportunity to look into the collection classes within Scala. First off, there's a List.range method which I can use to easily create the initial list and a yield feature which I'm thinking is a good way to do the filtering. Finally, there's a foldLeft method which can do the 'summing'. These three things in mind, this is what I came up with:

def sumOfMultiples(upto : Int) : Int = {
  def isDivisibleBy3Or5(value : Int) = {
    value % 3 == 0 || value % 5 == 0
  }
  def createRange(sumCond: Int => Boolean) : List[Int] = {
    for (i <- List.range(1, upto + 1) if sumCond(i)) yield i
  }
  def sum(x : Int, y : Int) = x + y
  createRange(isDivisibleBy3Or5).foldLeft[Int](0)(sum)
}

This also reads quite well - just taking the last line, create a range which is divisible by 3 or 5, then aggregate using a sum function.

The one problem for me is the size - it's still quite a few lines of code for such a simple task. Further digging, I find a few other neat little features that get me to me final solution (at the moment anyway!).

Instead of using yield, there's a filter function which would make the code read better. Also, Scala can infer types. I'd already seen this with the return type being optional. Finally there's some rather obscure syntax using underscores. Putting this together, I ended up with this goodness:

def sumOfMultiples(upto : Int) = List range(1, upto + 1) filter(x => x % 3 == 0 || x % 5 == 0) reduceLeft(_ + _)

Apart from that underscore syntax which looks a little odd on first glance, this looks pretty nice. It reads much more of "what not how" implementation: that is, describing what I want "a list from 1 to n, filtered on each item being divisible by 3 or 5, finally reducing down using the sum of all the elements" rather than how "by iterating a number of times, incrementing some counter, etc...".

Summary

This rather succinct version got me to thinking in how it would look in say Java or C# (the two languages I use daily at the moment) using just the built in libraries - i.e. JDK 6 (J2SE) or .NET 3.5. As well as exploring that, next time I will look back at how things have gone so far.


Comment Guidelines
See the FAQ for details on the full rules and guidelines. No Spam. Write clearly and thoughtfully - no bad language.