无法弄清楚简单的haskell递归问题
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了无法弄清楚简单的haskell递归问题相关的知识,希望对你有一定的参考价值。
我正在尝试编写一个简单的haskell程序,它总结了一个整数的数字,例如我的整数是888所以总和应该是8 + 8 + 8 = 24。我得到了这个部分,但我希望我的程序继续前进,直到没有任何东西可以添加,例如在添加8 + 8 + 8 = 24后它应该添加2 + 4 = 6然后返回6.感谢您的帮助!
import System.IO
import Data.List
integer = 888
todigits :: Integral x => x -> [x]
todigits 0 = []
todigits x = todigits (x `div` 10) ++ [x `mod` 10]
add::[Int]->Int
add (x:xs) = sum(x:xs)
added = add (todigits integer)
main = do
print(added)
你的函数只适用于一次迭代。你只需要递归调用它,直到得到1位数的结果(当然是空列表)。
我们将从你现有的函数开始,我已经重命名并重写了它,以便它以相反的顺序返回列表(首先是单位数字)。这根本不是必需的,你可以完全使用你之前的定义(因为到目前为止我们唯一感兴趣的是列表的总和,订单无关紧要),但这会更多如果您需要从数字列表中重建数字(我认为还应该更好),这很方便:
todigitsOnce :: Integral x => x -> [x]
todigitsOnce 0 = []
todigitsOnce x = x `mod` 10 : todigitsOnce (x `div` 10)
这是递归toDigit
函数:
toDigit :: Integral x => x -> [x]
toDigit x
| length firstResult < 2 = firstResult
| otherwise = toDigit . sum $ firstResult
where firstResult = todigitsOnce x
正数和它的数字总和总是一致的模数9.此外,由于所有非零数字都至少有一个正数而没有负数,因此无法从正数得到0的数字和。因此:
digitSum x = case (x, x `mod` 9) of
(0, _) -> 0
(_, 0) -> 9
(_, v) -> v
在ghci中尝试一下:
> digitSum 888
6
此函数可能无法按照您对负数进行操作 - 但是,原始函数也不会优雅地处理负数,所以...... =)
在另一种答案中,特别是因为你正在做递归数字(基数为10)和默认的show
实例是基数10,你可以通过字符串往返并很好地用视图模式写,
{-# LANGUAGE ViewPatterns #-}
digitSum :: Int -> Int
digitSum x@(show -> (_:"")) = x
digitSum (show -> cs) = digitSum $ sum . map ( read . (:[]) ) $ cs
如果字符串表示是任何单个字符(即.0 <= x <= 9
),则只返回x
,否则递归字符串表示中的整数之和。
您仍然可以很好地使用视图模式(imo)而无需往返,但它确实需要辅助函数将整数表示为其数字列表,
import Data.List (unfoldr)
import Data.Tuple (swap)
digitList :: (Integral a) => a -> [a]
digitList 0 = [0]
digitList n = unfoldr f n
where f 0 = Nothing
f i = Just . swap $ i `divMod` 10
digitSum' :: (Integral a) => a -> a
digitSum' (digitList -> x:[]) = x
digitSum' (digitList -> xs) = digitSum' $ sum xs
以上是关于无法弄清楚简单的haskell递归问题的主要内容,如果未能解决你的问题,请参考以下文章