【发布时间】:2016-10-17 02:12:01
【问题描述】:
我正在尝试解决名为:N 的尾随零数的 Codewars 问题!与哈斯克尔。 我知道我不需要计算阶乘来知道尾随零,实际上我只是在计算有多少个数字可以被 5 整除,以及每个数字有多少次。 我写了 2 个版本,一个在分解数字时使用 memoization 以获得可被 5 整除的次数,另一个不使用 memoization。 令我惊讶的是,假定的 DP 方法比普通的递归方法花费的时间更长。我可能在我的代码中做了一些非常愚蠢的事情。
这些是函数:
zeros x = helperZeros [1..x]
helperZeros :: [Integer] -> Integer
helperZeros = sumArrayTuple . filter (\x -> x `mod` 5 == 0)
sumArrayTuple = foldl (\acc x -> acc + (fastDef x)) 0
data Tree a = Tree (Tree a) a (Tree a)
instance Functor Tree where
fmap f (Tree l m r) = Tree (fmap f l) (f m) (fmap f r)
index :: Tree Integer -> Integer -> Integer
index (Tree _ m _) 0 = m
index (Tree l _ r) n = case (n-1) `divMod` 2 of
(q,0) -> index l q
(q,1) -> index r q
nats = go 0 1
where
go n s = Tree (go l s') n (go r s' )
where
l = n + s
r = l + s
s' = s * 2
fastDef:: Integer -> Integer
fastDef x = trace (show x) index memTreetDef x
memTreetDef = fmap (defact fastDef) nats
defact f n
| n `mod` 5 /= 0 = 0
| otherwise = 1 + f (n `div` 5)
zeros' x = helperZeros' [1..x]
helperZeros' :: [Integer] -> Integer
helperZeros' = sumArrayTuple' . filter (\x -> x `mod` 5 == 0)
sumArrayTuple' = foldl (\acc x -> acc + (def x)) 0
def n
| n `mod` 5 /= 0 = 0
| otherwise = 1 + def (n `div` 5)
我要记住的是 defact 函数的结果,例如如果我已经计算了 defact 200,那么它将重用这个结果来计算 defact 1000。
我对 Haskell 中的 DP 相当陌生。
【问题讨论】:
-
你不也需要计算二的数量吗?
-
@Bergi 你总是有足够的二来匹配所有的五!
标签: haskell dynamic-programming factorial