什么是Haskell解决这个问题的方法?

时间:2014-05-06 01:39:28

标签: haskell

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的输出。我该怎么做?

4 个答案:

答案 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

  • 定义两个函数isPrimeprimeList,它们是相互递归的,用于计算素数,你应该在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