How do I get the sums of the digits of a large number in Haskell?

Why not just sumd = sum . Map Char. DigitToInt .Show.

I find going via strings and characters is really unnatural since there is nothing in the problem that is concerned with strings. It's just numbers and the solution should reflect that. – svenningsson May 15 '10 at 10:42.

This is just a variant of @ony's, but how I'd write it: import Data. List (unfoldr) digits :: (Integral a) => a -> a digits = unfoldr step . Abs where step n = if n==0 then Nothing else let (q,r)=n`divMod`10 in Just (r,q) This will product the digits from low to high, which while unnatural for reading, is generally what you want for mathematical problems involving the digits of a number.(Project Euler anyone?) Also note that 0 produces , and negative numbers are accepted, but produce the digits of the absolute value.

(I don't want partial functions! ) If, on the other hand, I need the digits of a number as they are commonly written, then I would use @newacct's method, since the problem is one of essentially orthography, not math: import Data. Char (digitToInt) writtenDigits :: (Integral a) => a -> a writtenDigits = map (fromIntegral.

DigitToInt) . Show . Abs Compare output: > digits 123 3,2,1 > writtenDigits 123 1,2,3 > digits 12300 0,0,3,2,1 > writtenDigits 12300 1,2,3,0,0 > digits 0 > writtenDigits 0 0 In doing Project Euler, I've actually found that some problems call for one, and some call for the other.

About . And "point-free" style To make this clear for those not familiar with Haskell's . Operator, and "point-free" style, these could be rewritten as: import Data.

Char (digitToInt) import Data. List (unfoldr) digits :: (Integral a) => a -> a digits I = unfoldr step (abs i) where step n = if n==0 then Nothing else let (q,r)=n`divMod`10 in Just (r,q) writtenDigits :: (Integral a) => a -> a writtenDigits I = map (fromIntegral. DigitToInt) (show (abs i)) These are exactly the same as the above.

You should learn that these are the same: f . G (\a -> f (g a)) And "point-free" means that these are the same: foo a = bar a foo = bar Combining these ideas, these are the same: foo a = bar (baz a) foo a = (bar . Baz) a foo = bar .

Baz The laster is idiomatic Haskell, since once you get used to reading it, you can see that it is very concise.

I am unable to find what what the . Show and . Abs are doing in the writtenDigits function.

Could you explain what are they doing? Thanks – Tim May 15 '10 at 15:39 ". Show"?.

Doesn't work like it does in C/C++/Java/Python/PHP, see my expanded answer for details. The reason for abs is that I want the functions to be defined for negative numbers, rather than crash or loop (which they will without the abs). That makes them total functions, not partial functions, which in Haskell (or any language really) good.

– MtnViewMark May 15 '10 at 17:42.

Sumd 0 = 0 sumd x = (x `mod` 10) + sumd (x `div` 10) Then run it: ghci> sumd 2345 14 UPDATE 1: This one doesn't generate thunks and uses accumulator: sumd2 0 acc = acc sumd2 x acc = sumd2 (x `div` 10) (acc + (x `mod` 10)) Test: ghci> sumd2 2345 0 14 UPDATE 2: Partially applied version in pointfree style: sumd2w = (flip sumd2) 0 Test: ghci> sumd2w 2345 14 I used flip here because function for some reason (probably due to GHC design) didn't work with accumulator as a first parameter.

Writing your recursive functions in this manner is going to use unbounded stack. Much better to recurse in terms with an accumulator, so no thunks are generated. – jrockway May 15 '10 at 3:11 Best to wrap sumd2 so the user doesn't have to put in the initial accumulation value.

– trinithis May 15 '10 at 22:12.

Just to make pool of solutions greater: miterate :: (a -> Maybe (a, b)) -> a -> be miterate f = go . F where go Nothing = go (Just (x, y)) = y : (go (f x)) sumd = sum . Miterate f where f 0 = Nothing f x = Just (x `divMod` 10).

1 The 'miterate' function is really just 'unfoldr'. – svenningsson May 15 '10 at 10:44 Yep. I haven't looked good enough (i.e.In Data.

List). Why it wasn't imported in Prelude?... – ony May 15 '10 at 13:41.

To sum up all digits of a number: digitSum = sum . Map (read . Return) .

Show show transforms a number to a string. Map iterates over the single elements of the string (i.e. The digits), turns them into a string (e.g. Character '1' becomes the string "1") and read turns them back to an integer.

Sum finally calculates the sum.

Well, one, your Haskell function misses brackets, you need fac (n - 1). (oh, I see you fixed that now) Two, the real answer, what you want is first make a list: listdigits n = if n Int). Then we just make a sum as in sum (listdigits n).

And we should be done. Naturally, you can generalize the example above for the list for many different radices, also, you can easily translate this to products too.

(++) is slow however, I wouldn't recommend to use it in other algorithms. – Yasir Arsanukaev May 15 '10 at 3:38.

Although maybe not as efficient as the other examples, here is a different way of approaching it: import Data. Char sumDigits :: Integer -> Int sumDigits = foldr ((+) . DigitToInt) 0 .

Show Edit: newacct's method is very similar, and I like it a bit better :-).

I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.

Related Questions