Project Euler 4

I am very new to Haskell and i thought that to get a hang of writing haskell programs,i might solve some project euler problems.

So i went on with it and implemented the problem number 4 of Project Euler.

The problem Statement:

A palindromic number reads the same both ways. The largest palindrome made from the product of two 2-digit numbers is 9009 = 91 × 99.

Find the largest palindrome made from the product of two 3-digit numbers.

But there seems to be something wrong with my solution.

Here it is:

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

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

GHCI gives me this error:

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]]

I dont know what this means and am frustrated for not finding the reason for the error. Any help will be appreciated.Thanks.


So After reading some of the answers and comments, i did something like This:

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)   

Still doesn't work.


OK..

BY following @bheklilr's advice, i changed my program:

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])

Now what do i put in place of the inverted comma? I am seriously confused.


The first big error is that you're calling

reverse (x * y)

Since x * y is a number, and reverse only works on lists, this won't compile. You can convert the number to a String (which is a list) with show :

reverse $ show $ x * y

However, reversing the string is not what you really want to do, you want to filter find all the palindromes, so you need to filter your list of (x * y) s by a predicate. Instead you could write

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

But since this marches off the side of the screen, I would recommend breaking it up into smaller functions

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

The next big problem is because you're using the max function, which has the type

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

But we really want to find the max of a list, so we turn to maximum , which has the type

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

So you can finalize your program as

projectEuler4 :: Integer
projectEuler4 = maximum palindromes

One final thought: the problem says that you need to find the largest palindrome that is a multiple of 2 three-digit numbers, but your range that you're looking over is [1..999] , which includes 1 and 2 digit numbers. What could you do to not check those? Conveniently, it'll make the program faster.


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

That's the type of max . When you call it on some argument of type a , you get a result of type a -> a - a function. That is because max is normally called with two values; partial application results in a function which still waits for the second argument before calculating the result, the biggest of two values.

The error shows that Haskell has deduced the type of palindromeList as [[a0]] so the result's type is [[a0]] -> [[a0]] . You gave it as (Ord a,Num a) => a and Haskell can't match the two.

What you intended was to use maximum , which processes a list and finds the biggest value in it:

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

The definition of palindromeList is wrong too. For starters, the numbers from 1 through 99 in [1..999] are not triple-digit numbers. Then you need to test them. reverse (x*y) of course is wrong: reverse :: [a] -> [a] but result of multiplication of two numbers is a number, but - this is still not a test even when you fix it.

A test is something like show (x*y) == reverse (show (x*y)) .


You are trying to reverse a number with:

reverse(x*y)

reverse only works on lists. Fortunately, a String is a list, and show is the canonical way to create the String representation of a value.

So try something like:

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

上一篇: 欧拉项目8

下一篇: 欧拉项目4