Search code examples
haskellsumlist-comprehensiondigitssum-of-digits

Cross sum of digits of a non-negative number using list comprehension


I'm looking for a non-recursive implementation of sum of digits (a "cross sum") of a non-negative number like this:

cs :: Int -> Int 
cs n = sum digits_of_n where digits_of_n = [ . | ... ] 

A cross sum of a number (e.g. 512) is the sum of its individual digits (e.g. 5 + 1 + 2 = 8)

cs takes a non-negative number "n" as input, then should use list comprehension to split the number to its digits (e.g. 1234 -> [1,2,3,4]), which then gets summed up.

The part where list comprehension is used is the question, I don't know how to implement that.

The "usual", recursive way would be extracting the digits from a number recursively using modulo and division, and then summing them up like this:

cs :: Int -> Int
cs n = if n == 0 then 0 else n `mod` 10 + cs (n `div` 10)

I have however difficulty expressing this without recursion and with list comprehension, does anyone have ideas regarding this?


Solution

  • First let me remark that such digit sums are an almost completely useless thing to compute, and there are way too many questions here about them.

    ...anyway – your question boils down to writing a function Int -> [Int] that produces the list of digits of a nonnegative number. Well, that can of course be done recursively, it can be done using show (which is a bit of a hack, but then, anything that requires the decimal digits will be a hack), with an unfold, or indeed with a list comprehension. In this case, you can't very well terminate on having consumed all digits anymore, but you can still compute the number of digits first, then determine each i-th digit separately:

    decimalDigits :: Int -> [Int]
    decimalDigits n = [ _ | i <- [0 .. ceiling . logBase 10 $ fromIntegral n ]
    

    Then, to compute the i-th digit, you'll need to use mod and div much as you would in the recursive solution, just not with 10 but its i-th power.