CoffeeScript Euler #1

So, CoffeeScript is the latest hot new thing I find myself using, and what better way to start to get to grips with it than to solve some Euler problems while attempting to be idiomatic and use interesting language features?

Problem one – sum all multiples of 3 and 5 below 1000.

sum = (nums) -> nums[0] + sum(nums[1..]) unless (nums.length == 0)
Number.prototype.multipleOf = (x) -> this % x == 0

sum (n for n in [1...1000] when (n.multipleOf 3) or (n.multipleOf 5))

(if you want to try the above example, a good way is to get CoffeeScript installed and paste it into the REPL – you can enter multi-line mode with ctrl-v)

I’m still on a kick of favouring recursion over loops, and in the case of CoffeeScript this approach actually seems to yield the tersest and most readable code:

sum = (nums) -> nums[0] + sum(nums[1..]) unless (nums.length == 0)

“Add the first number to the sum of the remaining numbers, unless there are no numbers to add”

The unless condition means that this function returns undefined if the array is empty – I find this preferable to return 0, as 0 has a meaning which should be tied to the content of the array.

Adding undefined to a number is like adding zero, so there is no need to check for any special case, which is a big help in keeping the code concise.

A nice feature of CoffeeScript is the way ranges can be defined and used to slice up arrays – nums[1..] effectively gives you the “tail” of nums, all elements from index 1 to the end.

This could have been written with an if at the start, but I instinctively prefer using the unless; it feels better and it means the first piece of code you read is the “meat” of the function. It’s also the first time I’ve been using a language with “unless” in years…

Number.prototype.multipleOf = (x) -> this % x == 0

This is purely for readability – reading x.multipleOf(y) is quicker to understand for a human being than x % y == 0. It’s also an opportunity to mess around with adding a function to a JavaScript type through prototypes; I could have defined a local function just as with sum which takes two arguments, but again it wouldn’t read quite as naturally – multipleOf(x,y) vs x.multipleOf(y).

sum (n for n in [1...1000] when (n.multipleOf 3) or (n.multipleOf 5))

This then is the line which solves the problem, and demonstrates a few nice things.

“n for n in” is a way of iterating over an array, assigning each value to n (You can use it as the input to a function for each n – console.log n for n in [1..3]). The optional when clause can be used to filter with a conditional statement (or is an alias for ||), not dissimilar to the FLWOR structure of xQuery.

The use of three periods when defining the range specifies that the last value is not to be included – I could have had the same effect with [1..999], but I like using the exclusive range in this case as the solution is phrased in the same terms as the problem – all numbers under 1000, not all numbers to 999.

Finally, like Scala, when a function takes a single parameter the parentheses may be omitted, which can make for improved readability and also makes CoffeeScript a good language for defining DSLs. However, the parentheses were required around the two conditions being or’d, which did catch me out to start with (though the REPL is a great sandbox for quickly working through such snags).

One final feature I like which I didn’t manage to lever into the example here is string interpolation using a hash and curly braces:

result = sum (n for n in [1...1000] when (n.multipleOf 3) or (n.multipleOf 5))
console.log "The sum of all multiples of 3 or 5 below 1000 is #{result}"

No need to construct strings using a format or concatenation, it takes variables from the context with the added benefit they are appropriately named within the string. Very nice indeed.

Conclusion

I already really like CoffeeScript – the syntax is simpler and cleaner than JavaScript, and some of the new features it brings really aid in the production of clean code. Many of its advantages are reminiscent of the advantages of Scala over Java, and it seems like a much less surprising language to come to from an OO background than vanilla JavaScript.

originally published at https://kinjacono.wordpress.com/2013/02/23/coffeescript-euler-1/

About

Jim Kinsey is an English software engineer based in Berlin. Currently at Springer Nature, formerly of BBC News & Sport.