Project euler problem 3 in haskell - haskell

I'm new in Haskell and try to solve 3 problem from http://projecteuler.net/.
The prime factors of 13195 are 5, 7, 13 and 29.
What is the largest prime factor of the number 600851475143 ?
My solution:
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
I try to run for example:
getD 13195
> 29
But when i try:
getD 600851475143
I get error Exception: Prelude.maximum: empty list Why?
Thank you #Barry Brown, I think i must use:
getD :: Integer -> Integer
But i get error:
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
Thank you.

Your type signature limits the integer values to about 2^29. Try changing Int to Integer.
Edit:
I see that you already realised that you need to use Integer instead of Int. You need to change the types of both getD and isSimpleNumber otherwise you will get a type mismatch.
Also in general, if you are having trouble with types, simply remove the type declarations and let Haskell tell you the correct types.
Main> :t getD
getD :: Integral a => a -> a
Main> :t isSimpleNumber
isSimpleNumber :: Integral a => a -> Bool

After you found the error, may I point out that your solution is quite verbose? In this case a very simple implementation using brute force is good enough:
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)

this question is easy enough for brute-force solution, but it is a bad idea to do so because the whole idea of project euler is problems you need to really think of to solve (see end of answer)
so here are some of your program's flaws:
first, use rem instead of mod. it is more efficient.
some mathematical thinking should have told you that you don't need to check all numbers from 1 to x in the isprime function and the getD function, but checking all numbers from the squareroot to one (or reversed) should be sufficient. note that in getD you will actually need to filter numbers between x and the square root, because you search for the biggest one.
why do you use the maximum function in getD? you know the list is monotonically growing, so you may as well get the last one.
despite you only need the biggest divisor (which is prime) you compute the divisors list from small to big making the computer check for each value if it is a divisor or not although discarding the result once a bigger divisor is found. it should be fixed by filtering the list of numbers from x to 1, not from 1 to x. this will cause the computer to check divisibility (how should I say that?) for the biggest possible divisor, not throwing to the trash the knowledge of previous checks. note that this optimization takes effect only if the previous point is optimized, because otherwise the computer will compute all divisors anyway.
with the previous points mixed, you should have filtered all numbers [x,x-1 .. squareroot x] and taken the first.
you don't use an efficient isPrime function. if I were you, I would have searched for an isprime library function, which is guaranteed to be efficient.
and there are more..
with this kind of code you will never be able to solve harder project euler problems. they are designed to need extra thinking about the problem (for instance noticing you don't have to check numbers greater from the square root) and writing fast and efficient code. this is the purpose of project euler; being smart about programming. so don't skip it.

Related

creating tuples from infinite list

When trying to solve this challenge I stumbled upon something I was not able to explain myself.
First I generate an infinite list of prime numbers as follows:
primes = [n|n<-[2..],product[1..n-1]`rem`n==n-1]
This has the inferred type [Integer] so Int-overflow should not be a problem.
Then I try to make 2-tuples of subsequent primes (goal: [(2,3),(5,7),...]). To achieve this I wrote another function:
listtotuples l=[ (l!!i, l!!(i+1) ) |i<-[0,2..]]
Strangely this listtotuples function seems to work fine on e.g. [0..], but it just stops working when I apply it to primes, the output is just (after interrupting)
[(2,3),(5,7),(11,13),(Interrupted.
I do not understand why this happens, can anyone explain?
EDIT: This does not only happen when trying to output the infinite list, but also e.g. using take 10 $ listtotuples primes in Prelude after having loaded a file with the two lines from above. It does get stuck at the exact same point.
I am using Windows 7 with GHCi 7.10.2.
EDIT2: The full contents of my file are as follows:
order p m=head[n-1|n<-[0..],mod m (p^n)>0]
primes = [n|n<-[2..],product[1..n-1]`rem`n==n-1]
listtotuples l=[ (l!!i, l!!(i+1) ) |i<-[0,2..]]
p=listtotuples primes
f n=product[r^(order s n) * s^(order r n)|(r,s)<-take n p]
The problem disappears as soon as I comment/remove the last line (the function f, but I still think this is very strange, as f is not called and does not have anything todo with the functions above. Also if I replace take n p in the function f with [(2,3)] everything works as defined.
The addition of f forces your primes to have type Int, which does overflow during the factorial operation. The reasoning goes like this:
take :: Int -> [a] -> [a]
In f n, the use of take n p forces n :: Int.
Because the arguments to order must have the same type, the calls order r n and order s n force r, s :: Int.
(r, s) <- take n p forces p :: [(Int, Int)]
p = listtotuples primes forces primes :: [Int]
Simple fixes include breaking steps 2 or 3 above; use take (fromInteger n) p to break step 2 or order s (fromIntegral n) and order r (fromIntegral n) to break step 3.
...and now you know why adding top-level type signatures is considered a best practice. =)

sum of squares of integers [duplicate]

This question already has answers here:
Sum of Squares using Haskell
(3 answers)
Closed 8 years ago.
Ok This is a homework question but I'm not asking for a solution to how its done
What I want to ask is what it is asking me to do?
The sum of the squares of integers in the range m:n (where m ≥ n) can
be computed recursively. If there is more than one number in the range
m:n, the solution is to add the square of m to the sum of the squares
in the rangem+1:n; otherwise there is only one number in the range
m:n, so m == n, and the solution is just the square of m.
a. Define the recursive function sumsquares to carry out this
computation. As always, draw up a series of test data showing the
expected output, and then test the function.
I know I have to write a recursive function called sumsquares but I dont quite understand what it means by "The sum of the squares of integers in the range m:n (where m ≥ n) can be computed recursively".
This is the code I have so far, Would this be correct??
sumsquares :: Integral a=> Int -> Int -> Int
sumsquares m n
|m > n = error "First number cannot be bigger than second number"
|m==n = m*n
|otherwise = m*n +sumsquares (m+1)n
Someone else came up with this answer
sumOfSquaresFast :: Integral a => a -> a -> a
sumOfSquaresFast lo hi
| lo > hi = error "sumOfSquaresFast: lo > hi"
| otherwise = ssq hi - ssq (lo - 1)
where ssq x = div (2 * x^3 + 3 * x^2 + x) 6
But I do not understand the bottom part, the ssq and the div functions?
From what I understand, you want to take two numbers, e.g. 1 and 10, square each number between them (inclusively), and then take the sum of that. So you'd want some function like
sumOfSquaresBetween :: Int -> Int -> Int
sumOfSquaresBetween m n = ???
Now, you have to use recursion, so this means that ??? is going to be some expression that uses sumOfSquaresBetween.
Now here's the trick: If you know sumOfSquares n n, then how would you find sumOfSquares (n - 1) n? What about sumOfSquares (n - 2) n? Can you generalize this all the way to sumOfSquares m n for m <= n? If so, then you've just performed your desired algorithm, but in reverse.
Hope this hint helps.
"The sum of the squares of integers in the range m:n (where m ≥n) can be computed recursively."
Let's break this apart....
"integers in the range m:n"
is the set of integers starting from m, going to n
[m, m+1, m+2, ....n]
ie-
integers in the range 4:8 = [4,5,6,7,8]
"squares of...."
As you probably know, the square of a number x is x*x, so
squares of integers in the range 4:8 = [16, 26, 36, 49, 64]
"The sum of...."
add them
The sum of the squares of integers in the range 4:8 = 16+26+36+49+64
".... can be computer recursively"
Well, you have to understand recursion to get this....
Any function that contains itself in the definition is recursive. Of course you have to be careful, if done incorrectly, a recursive function could lead to infinite loops....
For Ints, (N-1) recursion is common.... If you can use the calculation for (N-1) to evaluate the calculation for N, the computer can run down the numbers until a known value is hit (typically 0). This is better seen with an example.
let func n = sum of integers from 0 to n
(this is like your problem, but without the squares part)
if you know the value of func (n-1), you can easily compute the value of func n
func n = n + func (n-1)
func 0 = 0
The computer will use func 0 to compute func 1, func 1 to compute func 2, etc, all the way to N.
Recursion has two common (but actually pretty different) uses... First, as shown above, it allows for very clean function definitions.
Secondly, it is often used in mathematics to prove truths over all integers (ie- to prove something is true for all ints, prove it is true for 0, then prove if it is true for N, it is true for N+1....).
Really, the best way to solve this problem is also the easiest: use library functions.
sumsquares :: Integral a => a -> a -> a
sumsquares m n = sum (map (^2) (enumFromTo n m))
You just enumerate the numbers from n to m, square each of them, and take the sum of the results. Trying to solve this problem in with direct recursion just makes things needlessly complicated.
Exercise: Write your own versions of the library functions used in this answer.
-- | Generate the list of all values in the given range. Result is inclusive.
enumFromTo :: Enum a => a -> a -> [a]
-- | Apply a function individually to each element of the argument list,
-- and collect the results as a list, respecting the order of the original.
map :: (a -> b) -> [a] -> [b]
-- | Calculate the sum of a list of numbers.
sum :: Num a => [a] -> a

How can I replace generators if I need only one result?

I'm playing with Haskell for first time.
I've created function that returns first precise enough result. It works as expected, but I'm using generator for this. How can I replace generator in this task?
integrateWithPrecision precision =
(take 1 $ preciseIntegrals precision) !! 0
preciseIntegrals :: Double -> [Double]
preciseIntegrals precision =
[
integrate (2 ^ power) pi | power <- [0..],
enoughPowerForPrecision power precision
]
You can use the beautiful until function. Here it is:
-- | #'until' p f# yields the result of applying #f# until #p# holds.
until :: (a -> Bool) -> (a -> a) -> a -> a
until p f x | p x = x
| otherwise = until p f (f x)
So, you can write your function like this:
integrateWithPrecision precision = integrate (2 ^ pow) pi
where
pow = until done succ 0
done pow = enoughPowerForPrecision pow precision
In your case, you do all the iteration and then compute a result just once. But until is useful even when you need to compute a result at each step - just use an (iter, result) tuple and then just extract the result at the end with snd.
It seems like you want to check higher and higher powers until you get one that satisfies a requirement. This is what you could do: First you define a function to get enough power, and then you integrate using that.
find gets the first element of a list that satisfies a condition – like being enough of a power! Then we need a fromJust to get the actual value from that. Please note that almost always, fromJust is a terrible idea to have in your code. However, in this case the list is infinite, so we will have troubles with infinite loops long before fromJust is able to crash the program.
enoughPower :: Double -> Int
enoughPower precision =
fromJust $ find (flip enoughPowerForPrecision precision) [0..]
preciseIntegrals :: Double -> Double
preciseIntegrals precision = integrate (2^(enoughPower precision)) pi
The function
\xs -> take 1 xs !! 0
is called head
head [] = error "Cannot take head of empty list"
head (x:xs) = x
Its use is somewhat unsafe, as shown it can throw an error if you pass it an empty list, but in this case since you can be certain your list is non-empty it's fine.
Also, we tend not to call these "generators" in Haskell as they're not a special form but are instead a simple consequence of lazy evaluation. In this case, preciseIntegrals is called a "list comprehension" and [0..] is nothing more than a lazily generated list.

Convert Int into [Int]

I'm looking through a past exam paper and don't understand how to convert Int to [Int].
For example, one of the questions asks us to produce a list of all the factors of a whole number excluding both the number itself and 1.
strictFactors Int -> [Int]
strictFactors x = ???
I'm not asking for anyone to do this question for me! I just want to know how I'd convert an integer input to a list of integer output. Thanks!
Perhaps it would be easiest to have a look at some similar code. As requested, I won't give you the answer, but you should be able to use these ideas to do what you want.
Brute force
Here we're just going to use all the pairs of numbers between 1 and x to test if we can make x as the sum of two square numbers:
sumOfSquares :: Int -> [Int]
sumOfSquares x = [ (a,b) | a <- [1..x], b <- [a..x], a^2 + b^2 == x]
You call this like this:
ghci> asSumOfSquares 50
[(1,7),(5,5)]
because 50 = 1^2+7^2 and also 50 = 5^2 + 5^2.
You can think of sumOfSquares as working by first taking an a from the list [1..x] of numbers between 1 and x and then another between that and x. It then checks a^2 + b^2 == x. If that's True, it adds (a,b) to the resulting list.
Generate and check
This time let's generate some single numbers then check whether they're a multiple of another. This will calculate the least common multiple (lcm). For example, the least common multiple of 15 and 12 is 60, because it's the first number that's in both the 15 and 12 times tables.
This function isn't of the type you want but it uses all the techniques you want.
lcm :: Int -> Int -> Int
lcm x y = head [x*a | a <- [1..], (x*a) `mod` y == 0]
You can call that like this:
ghci> lcm 12 15
60
This time the list of numbers [1..] is (in principle) infinite; good job we're just picking the first one with head!
(x*a) `mod` y == 0 does the checking to see whether the number x*a is a multiple of y (mod gives the remainder after division). That's a key idea you should use.
Summary
Use a <- [1..end] to generate numbers, test them with a True/False expression (i.e. a Bool), perhaps using the mod function.
I'm quite new at Haskell but can think of a myriad ways of "converting" an Int to a list containing that same Int:
import Control.Applicative (pure)
sane_lst :: Int -> [Int]
sane_lst x = [x]
lst :: Int -> [Int]
lst x = take 1 $ repeat x
lst' :: Int -> [Int]
lst' = replicate 1
lst'' :: Int -> [Int]
lst'' = return
lst''' :: Int -> [Int]
lst''' = pure
lst'''' :: Int -> [Int]
lst'''' x = enumFromTo x x
I guess the point here is that you don't "convert" to a list, you rather "construct" the list you need. The staightforward strategy for the kind of question you posed is to find something that will give you a suitable starting list to work with based on your parameter, then filter, fold or comprehend as needed.
For example when I say:
lst x = take 1 $ repeat x
I'm first constructing an infinite list repeating the value I passed in, and then taking from it a list containing just the first element. So if you think about what kind of list you need to start with to find the solution to your problem you'll be halfway there.
If your only goal is to convert between the types (for now) then strictFactors x = [x] is the most canonical answer. This function is also called pure since [] is what's known as an Applicative and return since [] is known as a Monad.

Learning Haskell, care to help out with coding style?

I started learning haskell yesterday and I got stuck on a problem. After a bit of trying different things I thought I'd finally come here and ask how to fix this. Also, feel free to criticize the way I have done things so far so I can know what direction to go. Thanks.
module Main where
main = putStrLn lastPrime
where
lastPrime :: String
lastPrime = show(last(take 10001 primes))
primes :: [Int]
primes = [x| x <- [1..],length [a| a <- [1..lessen(x)], mod x a /= 0] == x - 2]
lessen :: Int -> Int
lessen a = ceiling(sqrt(a))
To fix your type error, you want this:
lessen :: Int -> Int
lessen a = ceiling (sqrt (fromIntegral a))
a has type Int, but sqrt is expecting a floating point type, and the easiest way to convert an integral type to another numeric type is fromIntegral.
In addition to the type error in lessen you have a logic error in primes:
length [a| a <- [1..lessen(x)], mod x a /= 0] == x - 2
You're (rightly) only considering elements up to lessen x. This has the consequence that the list will almost never have exactly x - 2 elements. As a consequence you'll get into an infinite loop when trying to get more than two elements out of that list (because there is no 3rd element for which the condition is true, but haskell doesn't know that so it iterates to infinity trying to find it).
Also note that taking the length of a list is an O(n) operation and there's almost always a better way to achieve what you want.
As a style note, I would recommend defining a separate method isPrime. This will make your code look like this:
module Main where
main = putStrLn lastPrime
where
lastPrime :: String
lastPrime = show(last(take 10001 primes))
isPrime x = length [a| a <- [1..lessen(x)], mod x a /= 0] == x - 2]
primes :: [Int]
primes = [x| x <- [1..], isPrime x]
lessen :: Int -> Int
lessen a = ceiling(sqrt (fromIntegral a))
This IMHO makes the list comprehension much more readable. However it still contains the bug. To get rid of the bug, I'd suggest defining isPrime using a different approach. Going up to lessen x is fine (except you should start from 2 because 1 cleanly divides everything), but instead of building a new list with all the divisors, you should just check whether any of the numbers in the range divides x. For this we can use the higher order function any, so we get this:
isPrime x = not (any (\a -> mod x a == 0) [2 .. lessen x])

Resources