Project Euler 12 与 Haskell 的 State Monad
在尝试增加我的 Haskell 知识时,我想尝试使用 State Monad 解决第 12 个 Project Euler 问题。当时对我来说,将整个三角形数字的创建与将其置于状态中似乎是有意义的。
这是我的代码:
module Main where
import Control.Monad
import Control.Monad.State
type MyState = (Integer, Integer)
s0 = (7, 28)
tick :: State MyState Int
tick = do
(n,o) <- get
let divs = getDivLen (n,o)
if divs >= 500
then do
let n' = n + 1
let o' = o + n'
put (n', o')
tick
else
return divs
getDivLen :: MyState -> Int
getDivLen (n,o) = foldl1 (+) [2 | x <- [1..x], o `mod` x == 0]
where x = round . sqrt $ fromIntegral o
main :: IO ()
main = print $ evalState tick s0
代码编译后,我将结果 6 发送到控制台。我只是不确定我做错了什么而没有发生递归。
提前致谢。
In trying to increase my Haskell knowledge I thought I'd try and get the 12th Project Euler problem solved using the State Monad. It seemed to make sense to me at the time to incorporate the whole triangle number creation with putting it in state.
Here is my code:
module Main where
import Control.Monad
import Control.Monad.State
type MyState = (Integer, Integer)
s0 = (7, 28)
tick :: State MyState Int
tick = do
(n,o) <- get
let divs = getDivLen (n,o)
if divs >= 500
then do
let n' = n + 1
let o' = o + n'
put (n', o')
tick
else
return divs
getDivLen :: MyState -> Int
getDivLen (n,o) = foldl1 (+) [2 | x <- [1..x], o `mod` x == 0]
where x = round . sqrt $ fromIntegral o
main :: IO ()
main = print $ evalState tick s0
The code compiles and I get the result 6 to the console. I'm just not sure what I'm doing wrong to not have the recursion happen.
Thanks in advance.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
看起来你的循环条件倒退了。只有当你找到一个至少有 500 个约数的三角形数时,你才会进行递归,所以它当然会立即停止,因为第一个三角形的约数少于这个数。
要解决此问题,请将行
if divs >= 500
更改为if divs <; 500
。完成此操作后,您应该返回数字本身,而不是除数的数量,因此您还必须修复
返回 div
。我会把那部分的问题留给你来解决。Looks like you have your loop condition backwards. You're only recursing if you've found a triangle number with at least 500 divisors, so it will of course stop immediately since the first one has fewer than that.
To fix this, change the line
if divs >= 500
toif divs < 500
.Once you've done that, you're supposed to return the number itself, not the number of divisors, so you'll have to fix the
return divs
as well. I'll leave fixing that part to you.