【发布时间】:2019-02-05 07:09:41
【问题描述】:
我正在尝试解决来自 Haskell 的 Project Euler 的问题 #26,但遇到了一些问题。
我已经设法弄清楚倒数的循环周期只与它的素数除数有关,所以我想我只需要找出循环周期最长的素数的倒数。于是我用 Haskell 写了一个算法:
isPrime :: Int -> Bool
isPrime k
| k <= 1 = error "Seriously?"
| otherwise = null [ x | x <- [2..floor(sqrt(fromIntegral k))], k `mod` x == 0]
lp = [x | x <- [7..1000], isPrime x]
s = map (\n -> head [x | x <- [ceiling(logBase 10 (fromIntegral n))..], 10^x `mod` n == 1]) lp
main::IO()
main = print $ maximum s
但是,它无法产生答案。我尝试使用 lamda,它可以产生循环周期的数字,带有几个素数,我设法得到正确的数字数(我希望算法不会有问题)。我还检查了列表s 的输出,它产生了[6,2,6,16,18,45,23,15,3,5,63, 没有结束。我不知道为什么会这样,因为如果我手动将函数应用于每个素数,我可以获得正确的输出。
谁能告诉我我的代码有什么问题,或者我解决它的方法是错误的?谢谢。
【问题讨论】:
-
该算法对我来说似乎还可以 - 不是特别有效,因此它可能会运行很长时间,但您打印出的值似乎是正确的(至少我检查过的值),并且
s不可能是无限的提升。如果到那时还没有人提出解释,我会尝试自己在 ghci 中测试它,但它必须等到我今晚在家。 [PS 为了速度,您可能只想找到所有小于 1000 的素数的列表,并将其硬编码为lp。] -
@RobinZigmond 谢谢,我发现如果我设置函数
f n = head [x | x <- [ceiling(logBase 10 (fromIntegral n))..], 10^x `mod` n == 1],如果我直接输入像f 89这样的素数,该函数会给出输出,但如果用@ 替换它就不能工作987654330@ -
@RobinZigmond 查看我对答案的编辑;并非所有结果都是正确的,这就是我意识到正在进行一些环绕算术的方式。它不是特别慢,需要几秒钟才能生成多达 1000 个的完整列表。
-
@MeowcolmLaw 它与
89一起使用,因为它把89解释为polymorphic literal 类型为Num a => a,并默认为Integer。 -
我有时对 Haskell 打字感到沮丧。通常使用
fromIntegral可以快速修复,但这里不是。我通过消除使用n和[ (n,x) | i <- [n], x <- [(ceiling.logBase 10 $ fromIntegral i)..], mod (10^x) i == 1 ]来实现此功能,使用i代替n。你可以使用let,但它会不那么紧凑。
标签: haskell