欧拉项目4

我对Haskell非常陌生,我认为为了得到编写haskell程序的一窍不通,我可能会解决一些项目问题。

所以我继续进行并实施了欧拉项目的第四个问题。

问题陈述:

回文数字读取相同的方式。 由两个2位数字产品制成的最大回文是9009 = 91×99。

查找由两个3位数字产品制成的最大回文。

但是我的解决方案似乎有些问题。

这里是:

projectEuler4 :: (Ord a,Num a) => a 

projectEuler4 = max palindromeList
  where palindromeList = [reverse(x*y)|x<-[1..999],y <- [1..999]]

GHCI给我这个错误:

ProjectEuler4.hs:2:17:
Could not deduce (a ~ ([[a0]] -> [[a0]]))
from the context (Ord a, Num a)
  bound by the type signature for
             projectEuler4 :: (Ord a, Num a) => a
  at ProjectEuler4.hs:1:18-35
  `a' is a rigid type variable bound by
      the type signature for projectEuler4 :: (Ord a, Num a) => a
      at ProjectEuler4.hs:1:18
In the return type of a call of `max'
Probable cause: `max' is applied to too few arguments
In the expression: max palindromeList
In an equation for `projectEuler4':
    projectEuler4
      = max palindromeList
      where
          palindromeList
            = [reverse (x * y) | x <- [1 .. 1000], y <- [1 .. 1000]]

我不知道这意味着什么,对于找不到错误原因感到沮丧。 任何帮助将不胜感激。谢谢。


所以在阅读了一些答案和评论之后,我做了这样的事情:

projectEuler4 :: (Ord a,Num a) => a 
projectEuler4 = max' palindromeList
    where palindromeList = [reverse(show(x*y))|x<-[1..999],y <- [1..999]]

max' :: (Ord a) => [a] -> a
max' [] = error "Empty List"
max' [p] = p
max' (p:ps) = max p (max' ps)   

仍然不起作用。


好..

按照bheklilr的建议,我改变了我的计划:

products :: [Integer] -> [Integer] -> [Integer]
products ns ms = [x * y | x <- ns, y <- ms]

isPalindrome :: Integer -> Bool
isPalindrome n = let s = show n in s == reverse s

palindromes :: [Integer]
palindromes = maximum filter (isPalindrome "") (products [100..999] [100..999])

现在我用什么来代替引号? 我很困惑。


第一个重大错误是你打电话

reverse (x * y)

由于x * y是一个数字,并且reverse仅适用于列表,所以不会编译。 您可以使用show将该数字转换为String (这是一个列表):

reverse $ show $ x * y

然而,反转字符串并不是你真正想要做的,你想过滤找到所有的回文,所以你需要用谓词过滤你的(x * y)列表。 相反,你可以写

palindromeList = [z | x <- [1..999], y <- [1..999], let z = x * y, if show z == reverse (show z)]

但是,由于这是从屏幕的一侧走下来的,我建议将其分解为更小的功能

-- Generates all products
products :: [Integer] -> [Integer] -> [Integer]
products ns ms = [x * y | x <- ns, y <- ms]

-- Checks if a number is a palindrome
isPalindrome :: Integer -> Bool
isPalindrome n = let s = show n in s == reverse s

-- Generates problem-specific palindromes
palindromes :: [Integer]
palindromes = ??? -- Implementation here.  Hint: filter

下一个大问题是因为你正在使用具有类型的max函数

max :: Ord a => a -> a -> a

但是我们真的想要找到一个列表的最大值,所以我们转向maximum ,它有类型

maximum :: Ord a => [a] -> a

所以你可以最终确定你的程序

projectEuler4 :: Integer
projectEuler4 = maximum palindromes

最后一个想法是:问题是你需要找到最大的回文数是2位三位数字的倍数,但是你正在查看的范围是[1..999] ,其中包括1和2位数字。 你可以做什么不检查这些? 方便,它会使程序更快。


Prelude> :t max
max :: (Ord a) => a -> a -> a

这是max的类型。 当你在类型a某个参数上调用它时,会得到类型a -> a - 一个函数的结果。 这是因为max通常被称为两个值; 部分应用程序会导致在计算结果之前等待第二个参数的函数,即两个值中最大的一个。

该错误显示Haskell已经推断出palindromeList的类型为[[a0]]因此结果的类型为[[a0]] -> [[a0]] 。 你把它作为(Ord a,Num a) => a和Haskell不能匹配这两个。

你打算使用maximum ,它处理一个列表并找到其中最大的值:

Prelude> :t maximum
maximum :: (Ord a) => [a] -> a

palindromeList的定义也是错误的。 对于初学者来说, [1..999]中从1到99的数字不是三位数字。 然后你需要测试它们。 reverse (x*y)当然是错误的: reverse :: [a] -> [a]但是两个数字相乘的结果是一个数字,但是 - 即使修复它,这仍然不是测试。

测试类似show (x*y) == reverse (show (x*y))


您正在尝试用以下方法反转数字:

reverse(x*y)

reverse仅适用于列表。 幸运的是, String是一个列表, show是创建值的String表示的规范方式。

所以试试像这样:

reverse (show (x*y))
链接地址: http://www.djcxy.com/p/80427.html

上一篇: Project Euler 4

下一篇: Project Euler #18 in Haskell