Some tips for getting started on Project Euler
So the other day at work my boss casually mentioned that he had messed around with Project Euler. He knew I was a bit of a geek for online programming fun and games. Project Euler is a very large set of programming puzzles (237, to date) that tests your ability to solve largely mathematical (and often algorithmic) challenges. Brute force will in principle work, but in practice it tends to take a bit too long (sometimes longer than the age of the universe). Generally, the difficulty is in solving the problems efficiently so you can get an answer within a few seconds.
I knew of Project Euler but I had never really joined in the fun. He casually mentioned that he had reached level 1. Congratulations were clearly in order. This weekend I decided to give it a try. I stopped after gaining level 2. We thrive on one-upmanship. Ball’s in your court, Mike.
Project Euler, a weekend vanished
So I ended up solving a good 60 or so of these problems (starting from the easiest) over a few hours a day this weekend. The vast majority of the first 25 problems are fairly trivial to brute-force if you have decent tools. With a decent high-level language many of these problems become fairly trivial.
The “second level” problems (25-50) start to require a bit more programming and a bit more thought, but you can still pretty much brute force your way through them without too much optimization.
Getting started is fairly easy, but if I could make a suggestion, choose your language wisely. Here are the basic functionality you’ll need (either built-in or to build yourself):
- You need multi-precision support. If you don’t have it, you’ll spend alot of time inventing it. (if you want to use C/C++, go here)
- You need good type-conversion tools
- You need good containers
- Good functional programming support will help alot
- If you have a prime-number library, use it. You’ll be building one up, if you don’t.
- Same goes for permutations and combinations.
My language of choice, Python, had pretty much everything you’d need.
A quick example
Project Euler is constantly asking you treat numbers in non-standard ways. They’ll want you to manipulate numbers like strings, like arrays of digits, and as normal numbers. This can be rough in languages that don’t really support this. Here’s an example:
If we take 47, reverse and add, 47 + 74 = 121, which is palindromic.
Not all numbers produce palindromes so quickly. For example,
349 + 943 = 1292,
1292 + 2921 = 4213
4213 + 3124 = 7337That is, 349 took three iterations to arrive at a palindrome.
Although no one has proved it yet, it is thought that some numbers, like 196, never produce a palindrome. A number that never forms a palindrome through the reverse and add process is called a Lychrel number. Due to the theoretical nature of these numbers, and for the purpose of this problem, we shall assume that a number is Lychrel until proven otherwise. In addition you are given that for every number below ten-thousand, it will either (i) become a palindrome in less than fifty iterations, or, (ii) no one, with all the computing power that exists, has managed so far to map it to a palindrome. In fact, 10677 is the first number to be shown to require over fifty iterations before producing a palindrome: 4668731596684224866951378664 (53 iterations, 28-digits).
Surprisingly, there are palindromic numbers that are themselves Lychrel numbers; the first example is 4994.
How many Lychrel numbers are there below ten-thousand?
When I saw this problem, my inner C programmer cried out in pain. You need to reverse the digits of number. Ugh. You need to determine if a number is a palindrome. Double ugh. And don’t forget that you’ll need multi-precision integer math to actually compute this stuff.
It’s just so much cleaner (and clearer) like this:
#SPOILER#
def is_palin(n):
return str(n)==str(n)[::-1]
def rev(n):
return int(str(n)[::-1])
def lychrel(n, iter):
if iter > 50: return True
next = n + rev(n)
if is_palin(next): return False
return lychrel(next, iter+1)
def l(n):
return lychrel(n,0)
print len(filter(l,range(1,10001)))
March 23rd, 2009 at 12:00 pm
I’m doing project euler to teach myself Haskell. At some points it is really a pain in the neck but I think its quite effective to learn a programming language in such a way.
March 23rd, 2009 at 12:22 pm
I know alot of people (including randall of xkcd) have used this to teach themselves a new language.
I did it to learn Lisp.
March 23rd, 2009 at 1:10 pm
I also remember thinking that as I was proceeding. Additionally, It would be an awesome way to learn functional programming if you’ve never done it before. Maybe I’ll switch to & learn Clojure or Haskell for a few problems.
March 26th, 2009 at 10:56 am
Oh my, I think you just gave me a new project to brush up on C++ with.
<3
April 7th, 2009 at 11:12 am
I started some months ago solving some of the Project Euler’s problems with C++, and I haven’t realized that Python would fit far better to solve those problems. I think that I will do as Andre Bluehs says and use it to learn more about it. Thanks for the post
May 8th, 2009 at 3:02 am
Project Euler is very addictive, I actually had few sleepless nights because of it
). However, I started to be proficient in Ruby after the 3rd problem.
Another interesting site not completely orthogonal is project eureka (http://www.projecteureka.org/), besides programming problems, it has puzzle and math questions.