user721010
user721010

Reputation:

Recursive function to add up all of the digits in a number

I'm working on a function that adds up all of the digits in a number, and to keep adding up digits until the number is reduced to a single digit. For example, the number 99999999999 should be evaluated like this:

99999999999
9+9+9+9+9+9+9+9+9+9+9
99
9+9
18
1+8
9

However, when I try running the number 99999999999 through my function, it returns 7, even though it should return 9. I've gone over my code several times, and I can't think of any reason why.

Here's the code:

sumdr x
  | x <= 9 = x
  | otherwise = sumdr $ addupnums x

addupnums y = foldl (+) 0 $ map read1 $ show y

read1 :: Char -> Int
read1 '1' = 1
read1 '2' = 2
read1 '3' = 3
read1 '4' = 4
read1 '5' = 5
read1 '6' = 6
read1 '7' = 7
read1 '8' = 8
read1 '9' = 9
read1 '0' = 0
read1 x = error "needs to be a number"

Upvotes: 0

Views: 1184

Answers (2)

Landei
Landei

Reputation: 54574

[Edit]

If you are only interested in the result of the repeated application until one digit remains, of course Daniel Fischer is right, and you should use his solution. It might be still instructive how to deal with this kind of problem if such a shortcut isn't possible, hence I leave my old answer.

[/Edit]

You got the answer, but two remarks:

  • Using Hoogle you could have found the function digitToInt in Data.Char, which is your read1
  • Transforming a number to a string just to get the digits seems to be wasteful, when a little bit more math will work as well, e.g.

.

f 0 = 0
f y = (y `mod` 10) + f (y `div` 10)

Or the slightly cryptic version:

f = sum . map (`mod` 10) . takeWhile (> 0) . iterate (`div` 10)

If you're really concerned with speed, you can use divMod, and you can try if accumulators are faster, e.g.

f n = go n 0 where
  go 0 s = s
  go k s = go k' (s+s') where (k',s') = k `divMod` 10

Upvotes: 2

sepp2k
sepp2k

Reputation: 370112

This works fine for me on a 64-bit system. If you're on a 32 bit system, 99999999999 doesn't fit into an Int, so it will overflow and give you wrong results.

If you change the type to Integer, it should work.

Upvotes: 6

Related Questions