Haskell新手。我有以下代码
fac :: Integer -> [Integer]
fac x = take 1 $ map (x `mod` ) $ reverse [2 .. xs]
where xs = floor $ sqrt $ fromIntegral x
我想显示[2 .. xs]
的第一个值x mod y == 0
。但是我不能使用filter
,因为它只会影响mod
的输出。我该怎么做?
答案 0 :(得分:2)
我想显示[2 .. xs]中的第一个值,使得x mod y == 0
在这种情况下,您不应使用reverse
:
fac x = take 1 $ filter (\y -> x `mod` y == 0) $ reverse [2 .. xs]
where xs = floor $ sqrt $ fromIntegral x
如果您想查找从xs
开始的mod x y == 0
的第一个值,则也无需使用reverse
:
fac x = take 1 $ filter (\y -> x `mod` y == 0) $ [xs, xs-1 .. 2]
where xs = floor $ sqrt $ fromIntegral x
答案 1 :(得分:2)
您可以使用filter
。只需为(==0)
的第一个参数撰写(x `mod`)
和filter
。
如果你正在尝试做项目欧拉问题3,这将是解决它的难以置信的痛苦方式。
我建议如下:
为where
子句中的内容定义一个函数,即isqrt = round . sqrt . fromIntegral
定义两个函数isPrime
和primeList
,它们是相互递归的,用于计算素数,你应该在isqrt
的定义中使用isPrime
,尽管使用isqrt
实际上并不是必需的;我只是觉得编写这个函数更容易思考。 (下面有关于如何执行此步骤的提示)
使用primeList
,定义一个递归factorize
函数,输出素数列表(或类似的东西)
对问题中的数字进行分解并返回列表中最大的素数
我上面提到的通常不是很快就能很好地计算非常大的质数,但它应该足以解决这个问题。本文详细介绍了原因:http://www.cs.hmc.edu/~oneill/papers/Sieve-JFP.pdf
对于未来数字理论相关的PE问题,请考虑使用此库:https://hackage.haskell.org/package/arithmoi-0.2.0.4
其他评论:
而不是take 1
,您应该实际使用head
;它稍微好一些。
此外,由于您将在此处理的最大数字是600851475143,因此您实际上不需要该函数具有类型Integer -> [Integer]
。 32位Int
不起作用,因为maxBound :: Int
是2147483647. maxBound :: Int64
,但是,它是9223372036854775807,远远超过您的需要。因此,您可以将函数定义为类型Int64 -> [Int64]
(如果计算机已经是64位,则只需Int -> [Int]
)。
提示:
primeList
应该被定义为类似primeList = 2 : 3 : filter isPrime [5,7..]
的东西,但你可以决定用它来表达你喜欢的东西);再次,这些定义应该是相互递归的。
答案 2 :(得分:1)
fac x = take 1 $ filter (\y -> x `mod` y == 0 ) $ reverse [2 .. xs]
where xs = floor $ sqrt $ fromIntegral x
或者,是无点的:
fac x = take 1 $ filter ((== 0).(x `mod`)) $ reverse [2 .. xs]
where xs = floor $ sqrt $ fromIntegral x
不确定您是否需要reverse
,或者您的目标究竟是什么。
答案 3 :(得分:1)
您可以使用过滤器。这是一个单行(如果计算导入的话,那么,两行;)
import Data.Ix (range)
fac x = head . filter ((==) 0 . mod x) . curry range 2 . floor . sqrt . fromIntegral $ x