Project Euler 20

As a way to learn Haskell, and get better at math, I’ve been slowly sniping at Project Euler problems. Because the thread is archived for problem 20, and I thought (snooty as can be) that my solution was a neat little one-liner, I thought I’d post it here. The problem’s not particularly hard (which is good; learning Haskell is proving difficult enough without having to push into mathematical theorems as yet); I just like showing off!

The assigned problem is to sum all the digits in 100! (so factorial(100)):

import Data.Char (digitToInt)
import LearnHaskell (factorial)

foldr ((+) . digitToInt) 0 (show (factorial 100))

It’s nice and simple: it calculates the factorial of 100, converting that into a String (which is a list of Chars, remember!) using show. It then folds across that String, converting each char back to an Int (using digitToInt), and summing those Ints as it goes ((+) . digitToInt). I think I’m just happy that I understand it; after all, a Python one-liner is similarly simple (and arguably simpler to understand…):

from math import factorial

# although, of course, the idiomatic equivalent is:
acc = 0
for c in str(factorial(100)):
    acc += int(c)
    
# these oneliners are neater, and reasonably obvious; first up,
# a list comprehension
sum([int(c) for c in str(factorial(100))])
# or...
sum(map(int, str(factorial(100))))

Of course, even that Haskell can be made easier to understand; I just wanted to work with foldr. Idiomatically matching the Python examples above, I spotted these in the thread (adapted to use my crappy factorial function):

import LearnHaskell (factorial)

-- using a list comprehension
sum [digitToInt x | x <- show(factorial(100))] 
-- or...
sum (map (digitToInt) (show (factorial(100))))

Both of these solutions are nice and clean.

Posted: 15 Dec, 2009
Tags:
blog comments powered by Disqus