2
\$\begingroup\$

Task: given a number (positive or negative), square every digit of it and concatenate them, forming a resulting number.

For example:

9119 should become 811181 = 9^2*10^0 + 1*10^1 + 1*10^2 + 9^2*10^3 (-1) should become (-1)

My code:

-- convert a number to the list of digits
-- doesn't work with negative numbers
digs :: Integral x => x -> [x]
digs 0 = [0]
digs x = let
      helper :: Integral x => x -> [x]
      helper 0 = []
      helper n = helper (n `div` 10) ++ [n `mod` 10]
  in
      helper x

squareDigit :: Int -> Int
squareDigit n = let sign = signum n
                    digits = (digs (abs n))
                    digs_sq = map (^ 2) digits
                    -- we can't concat squares as they may have more then 1 digit
                    digs_sq_flat = map digs digs_sq >>= id
                in
                  sign * foldl (\acc x -> x + (acc * 10)) 0 digs_sq_flat

Basically, it works:

*SquareDigit> squareDigit 9119
811181
*SquareDigit> squareDigit (-9119)
-811181

But maybe, my solution can be made more elegant.

\$\endgroup\$
3
\$\begingroup\$

Separate out combinators that apply some perspective to your data.

squareDigit = overAbs $ overDigits $ concatMap $ digs . (^ 2) where
  overAbs f n = signum n * f (abs n)
  overDigits f = foldl (\acc x -> x + (acc * 10)) 0 . f . digs
| improve this answer | |
\$\endgroup\$
2
\$\begingroup\$

You could replace

digs_sq_flat = map digs digs_sq >>= id

with

digs_sq_flat = concatMap digs digs_sq

(>>= id) is the definition of join from Control.Monad, which, when specialized to [a] is the same thing as concat. So you basically have a map followed by concat which is exactly concatMap

| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.