【问题标题】:project euler 14 using the state monad使用状态单子的项目 euler 14
【发布时间】:2015-04-13 20:24:22
【问题描述】:

我正在尝试通过 Project Euler(再次)自学 Haskell。问题 14 (https://projecteuler.net/problem=14) 正在乞求动态编程,从历史上看,我一直强烈反对单子(因为一再未能学会充分利用它们来让生活更轻松而不是更难)所以我试图咬一口子弹并使用 State monad 来记住我的代码......它进展不顺利。我想明确一点,我已经以简单/缓慢的方式解决了这个问题,此时我正在尝试学习一些东西(即Project Euler No. 14 Haskell 不是我想要的)。

到目前为止我的代码是:

collatzMemoCheck :: Int -> State (Map Int Int) Int
collatzMemoCheck n = state $ \s -> maybe (let (a, s') = runState (collatzFast n) s
                                          in (a+1, Map.insert n (a+1) s'))
                                         (\len -> (len, s))
                                         (Map.lookup n s)

collatzFast :: Int -> State (Map Int Int) Int
collatzFast 1 = state $ \_ -> (1, Map.singleton 1 1)
collatzFast n
  | even n    = collatzMemoCheck (n `quot` 2)
  | otherwise = collatzMemoCheck (3 * n + 1)

这适用于 cabal repl 中的单个查询,但在我的一生中,我无法弄清楚如何将重复调用 collat​​zFast 的状态链接起来。我想要类似的东西

-- DOES NOT WORK
allCollatzLengths = scanl (>>= collatzFast) (return Map.empty) [1..999999]

但我认为这是由内而外的。 Bind 获取上一个 State 计算的结果部分并将其传递给下一个调用,但我希望它获取上一个 State 计算的 state 部分并将 it 传递给下一个调用。

有没有正确的方法可以做到这一点,还是我把自己画到了角落里?如果我不能使用 >>=,那么拥有一个 monad 有什么意义? ...或者没有意义,因为这是一种愚蠢的方法?帮忙?

【问题讨论】:

  • 我会注意到,使用 State 不是 Haskell 中记忆的惯用方式,也不是获得优雅 DP 的方式。您所说的“简单/缓慢方式”的这个问题实际上确实有很多答案使用惯用的 DP 方式来实现非常好的性能......您想使用 State 来学习如何使用它还是你对 Haskell 中的高效 DP 更感兴趣吗?
  • 两者都有,但另一种方式已经很好地涵盖了。你知道为什么这不是惯用的吗?编辑:另外,我并没有把这个问题称为简单/缓慢的方式,我指的是一个天真的非 DP 实现作为简单/缓慢的方式。
  • 只是出于好奇:您可以接受的速度是多少?我是一个简单的(非单子)版本,我在我的钻机上以 4.5 秒的速度通过严格的地图 - 这对你来说会慢吗?
  • 我的慢版本甚至不涉及地图,它只是 collat​​zSlow :: Int -> [Int] 然后最大 $ map (\a -> (length $ collat​​zSlow a, a)) [ 1..999999]。编辑:似乎我天真的代码很慢的原因是我在 repl 中运行它。 cabal repl 花了 128.5 秒,但 cabal run 只花了 1.5 秒
  • 哇,这很有趣,快速版本(由 Daniel 启用)在 repl 中需要 18 秒,而常规运行需要 2.8 秒!为什么天真的版本在运行模式下更快我什至不明白。

标签: haskell


【解决方案1】:

你可能会喜欢

mapM :: Monad m => (a -> m b) -> [a] -> m [b]

特别是mapM collatzFast :: [Int] -> State (Map Int Int) [Int]

【讨论】:

    猜你喜欢
    • 2019-10-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-10
    相关资源
    最近更新 更多