haskell中的euler问题3项目

haskell中的euler问题3项目,haskell,project,Haskell,Project,我是Haskell的新手,试着从中解决3个问题 我的解决方案: 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 -- Ch

我是Haskell的新手,试着从中解决3个问题

我的解决方案:

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

谢谢。

您的类型签名将整数值限制在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

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

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)  

这个问题对于蛮力解决方案来说足够简单,但这样做是个坏主意,因为project euler的整个想法都是您需要真正思考才能解决的问题(请参见答案末尾) 以下是您的程序的一些缺陷:

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

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

为什么在getD中使用maximum函数?你知道这个列表是单调增长的,所以你最好得到最后一个

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

在前面的点混合的情况下,您应该过滤所有数字[x,x-1..squareroot x]并取第一个

您没有使用有效的iPrime函数。如果我是你,我会搜索isprime库函数,它保证是高效的。 还有更多


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

哪种版本的Haskell?也就是说,您使用的是哪种环境?有些不支持任意精度整数。任意精度整数实际上是Haskell语言的一部分,所以这不是真的。没有忽略它们的Haskell实现。“如果您在类型方面遇到问题,只需删除类型声明并让Haskell告诉您正确的类型”——这对于Haskell新手来说是一个非常糟糕的建议。我认为在学习哈斯克尔时,最好是手写所有的字体。为了更好地理解类型系统。你自己算出类型是很理想的,但这不是OP在这里所做的。让GHC告诉你这种类型比让StackOverflow上的人告诉你更有教育意义。我目前正在尝试这个问题,并且正在这样做。。。但它似乎不起作用。你知道为什么吗?main=do-let-pgen(p:xs)=p:pgen[x | x 0]print(最后一次([x | x我用它来表示“factor”)。我自己倾向于使用函数
fn
,但我同意
d
会更好。
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)