欧拉项目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