项目euler问题3在haskell

时间:2011-07-01 06:49:41

标签: haskell project

我是Haskell的新手并尝试从http://projecteuler.net/解决3个问题。

The prime factors of 13195 are 5, 7, 13 and 29.

What is the largest prime factor of the number 600851475143 ?

我的解决方案:

import Data.List

getD :: Int -> Int
getD x = 
  -- find deviders
  let deriveList = filter (\y -> (x `mod` y) == 0) [1 .. x]
      filteredList = filter isSimpleNumber deriveList
  in maximum filteredList

-- Check is nmber simple
isSimpleNumber :: Int -> Bool
isSimpleNumber x = let deriveList = map (\y -> (x `mod` y)) [1 .. x]
                       filterLength = length ( filter (\z -> z == 0) deriveList)
                       in 
                          case filterLength of
                            2 -> True
                            _ -> False

我尝试运行例如:

getD 13195
> 29

但是当我尝试时:

getD 600851475143

我得到错误异常:Prelude.maximum:空列表为什么?

谢谢@Barry Brown,我想我必须使用:

getD :: Integer -> Integer

但我得到错误:

Couldn't match expected type `Int' with actual type `Integer'
Expected type: [Int]
  Actual type: [Integer]
In the second argument of `filter', namely `deriveList'
In the expression: filter isSimpleNumber deriveList

谢谢。

3 个答案:

答案 0 :(得分:6)

您的类型签名将整数值限制为大约2 ^ 29。尝试将Int更改为Integer

修改

我看到你已经意识到你需要使用Integer而不是Int。您需要更改getD和isSimpleNumber的类型,否则会出现类型不匹配。

另外一般情况下,如果您遇到类型问题,只需删除类型声明,让Haskell告诉您正确的类型。

Main> :t getD
getD :: Integral a => a -> a

Main> :t isSimpleNumber
isSimpleNumber :: Integral a => a -> Bool

答案 1 :(得分:4)

发现错误后,我是否可以指出您的解决方案非常详细?在这种情况下,使用强力的非常简单的实现就足够了:

getD n = getD' n 2 where
  getD' n f | n == f = f 
            | n `mod` f == 0 = getD' (n `div` f) f
            | otherwise = getD' n (succ f)  

答案 2 :(得分:1)

这个问题对于暴力解决方案来说很容易,但这样做是个坏主意,因为项目euler的整个想法是你需要真正想到要解决的问题(参见答案结束) 所以这里有一些程序的缺陷:

首先,使用rem而不是mod。它更有效率。

一些数学思想应该告诉你,你不需要检查isprime函数和getD函数中从1到x的所有数字,但检查从squareroot到1(或反转)的所有数字应该足够了。请注意,在getD中,您实际上需要在x和平方根之间过滤数字,因为您搜索的是最大的数字。

为什么要在getD中使用最大函数?你知道这个名单是单调增长的,所以你也可以得到最后一个。

尽管你只需要最大的除数(这是素数),你可以计算从小到大的除数列表,如果它是除数,计算机会检查每个值,尽管一旦找到更大的除数就丢弃结果。它应该通过过滤数字列表从x到1而不是从1到x来修复。这将导致计算机检查可分性(我应该怎么说?)以获得最大可能的除数,而不是将先前检查的知识扔给垃圾。请注意,此优化仅在前一个点被优化时生效,否则计算机将计算所有除数。

如果前面的点混合了,你应该过滤掉所有数字[x,x-1 .. squareroot x]并取得第一个。

您没有使用高效的isPrime功能。如果我是你,我会搜索一个isprime库函数,保证有效。 还有更多..

使用这种代码,你永远无法解决更难的项目euler问题。它们的设计需要额外考虑问题(例如,注意你不必从平方根检查更大的数字)并编写快速有效的代码。这是项目欧拉的目的;对编程很聪明。所以不要跳过它。