I was first introduced to the term
polyglot when I was in
high school. Our French class did a presentation at a Foreign Language
Day. I have this vague recollection that the theme of the day was
"Polyglots Have More Fun". I've always liked the word, so I was
thrilled to see
Neal
Ford using it.
In any case, Bill Wagner started things
off at SRT by working the Project Euler
problems in C#/LINQ. Marina Fedner joined in,
addressing the problems in Ruby. Darrell Hawley tackled
them with Python, and I (Dianne
Marsh) jumped in with Scala. This
article compares the solutions to Problem 1, in each of the languages. We don’t maintain that these are optimal
solutions, in any of these languages, and we’re happy to take and post feedback
containing better solutions.
Problem
1:
If we list all the natural numbers below 10 that are multiples of 3 or 5, we
get 3, 5, 6 and 9. The sum of these multiples is 23.
Find the sum of all the multiples of 3 or 5 below 1000.
Here are the SRT “solutions”, in alphabetical order.
C# 3.0/LINQ:
var nums = from n in
Generators.NumberSequence(0, 1000)
where ((n % 3 == 0) || (n % 5 == 0))
select n;
var answer = nums.Sum();
// note: Bill put this in a library for
future use
public static IEnumerable<int>
NumberSequence(int from, int to)
{
do
{
yield return from++;
} while (from < to);
}
Python:
print sum([x for x in range(1,1000) if x%5==0 or x%3==0])
Ruby:
answer = (0..999).select {|a| a%3 ==0 || a%5==0}puts answer.inject {|sum, n| sum+n}
Scala:
val
nums = 3 until 1000
val somenums = nums.filter(x => (x % 3 == 0 || x % 5 ==0))
var sum = 0
somenums.foreach(sum += _)
println (sum)
The Ruby and Python implementations are really concise! I was left wondering
if Bill and I could have done better jobs in our respective languages.
Without rethinking the approach, but just eliminating local variables, I was
able to get the Scala version down to a more respectable:
sum = 0
(1 to
1000).filter(x => (x %3 == 0 || x % 5 ==0)).foreach( sum += _)
println (sum)
Then, I looked at the C#. The only
thing bloating the C# implementation is the missing “Range” function, which
Bill rightly put into a library for later use as NumberSequence. The comments in his blog for Problem 1 noted
a built-in function
Enumerable.Range(0,
1000)
that could be used to simplify the code and obviate the need for that
function. So, the C# code refactored to:
var nums = from n in
Enumerable.Range(0, 1000)
where ((n % 3 == 0) || (n % 5 == 0))
select n;
var answer = nums.Sum();
So there you have it: 4 implementations, fairly similar in their approach
but using different syntax, to Problem 1.
If you wish, add a comment to this blog indicating which you prefer, and
why! And, perhaps also indicate if your
preferred implementation is in your typical programming language or if you like
what you see in another, better.