Uri Goren
Uri Goren

Reputation: 13692

Break an integer to a list of digits

I am learning Haskell, and I am solving problem 30 on project Euler.

digits n = if n<10 then [n] else (digits (quot n 10)) ++ [(mod n 10)]
isP30 n = (sum $ map (^5) $ digits n) == n
sum $ filter isP30 [10^5..10^6-1]

Is there a more readable way to implement the digits function ?

Upvotes: 1

Views: 1028

Answers (3)

Will Ness
Will Ness

Reputation: 71065

First of all it is always more readable to write code with guards, instead of if-then-else. All the extraneous parens are also distracting.

The standard transformation for the inefficient appending-at-end functions, like your

digits n | n < 10    = [n] 
         | otherwise = digits (quot n 10) ++ [mod n 10]

is to introduce an additional argument, where calling the old digits n ++ xs is the same as calling the new go n xs:

digits n = go n []   -- digits_old n ++ [] == go n []
   where
   go n next | n < 10    = n : next
             | otherwise = go (quot n 10) (mod n 10 : next)

--                            [a,b,c,...,x,y]         [z]
--                            [a,b,c,...,x]         [y,z]

Thus the digits being produced in the reversed order go one by one into the result list being built bottom-to-the-top in an accumulator parameter, resulting in the list created in the correct order.

Upvotes: 2

bwroga
bwroga

Reputation: 5459

What about:

digits n = fmap digitToInt $ show n

I forgot to mention that you need to import digitToInt from Data.Char first, as in @bheklilr's answer.

Upvotes: 3

bheklilr
bheklilr

Reputation: 54058

Using @BenjaminHodgson's suggestion, you can write an unfold as

import Data.Tuple (swap)
import Data.List (unfoldr)

digits = unfoldr go
    where go 0 = Nothing
          go n = Just (swap $ n `divMod` 10)

However, due to how unfoldr works you will get the digits in reverse order here. Another solution is to ditch this entirely and go with

import Data.Char (digitToInt)

digits = map digitToInt . show

My timings found it to be faster and use about 25% of the memory in an unoptimized GHCi session, it also doesn't reverse the order of the digits.

Upvotes: 2

Related Questions