Adding two functions together in Haskell

后端 未结 3 1662
刺人心
刺人心 2021-01-17 02:04

Hi I am new in Haskell and I came across an interesting problem but I was not really sure on how I would go about solving it. I am about to show you only two parts of the qu

3条回答
  •  悲哀的现实
    2021-01-17 02:09

    The missing component is a way to break down an integer into its digits, and build it back up from there. That's easy:

    digits:: Int -> [Int]
    digits = map (`mod` 10) . takeWhile (/= 0) . iterate (`div` 10)
    
    undigits :: [Int] -> Int
    undigits = foldr f 0 where f i r = 10 * r + i
    

    Then it looks like you need to post-process those digits in two different ways, but only if they match a predicate. Let's build a combinator for that:

    when :: (a -> Bool) -> (a -> a) -> a -> a
    when p f a = if p a then f a else a
    

    The first case appears when you want to double digits in odd position (from left to right). Again trivial, with the minor inconvenience that digits breaks down a number by increasing power of ten. Let's prefix each number by its position:

    prefix :: [Int] -> [(Int, Int)]
    prefix is = let n = length is in zip [n, n-1..1] is
    

    doubleOdd can now be expressed as

    doubleodd :: [Int] -> [Int]
    doubleodd = map (snd . when (odd . fst) (id *** double)) . prefix
    

    You mentioned in a comment that when the double number overflows, its digits must be added together. This is the second case I was referring to and is again simplicity itself:

    double :: Int -> Int
    double = when (>= 10) (sum . digits) . (* 2)
    

    Here is your final program:

    program = undigits . doubleodd . tail . digits
    

    ... assuming the "between 13 and 15 digits" part is verified separately.

提交回复
热议问题