Reputation: 1128
New to Haskell. I have the following code
fac :: Integer -> [Integer]
fac x = take 1 $ map (x `mod` ) $ reverse [2 .. xs]
where xs = floor $ sqrt $ fromIntegral x
I want to display the first value from [2 .. xs]
such that x mod y == 0
. But I can't use filter
as that only would work off the output from mod
. How do I do this?
Upvotes: 0
Views: 200
Reputation: 2167
You can use filter
. Just compose (==0)
and (x `mod`)
for the first argument of filter
.
If you are trying to do Project Euler Problem 3, this will be an incredibly painful way of solving it.
I would suggest the following:
Define a function for what you have in the where
clause, i.e. isqrt = round . sqrt . fromIntegral
Define two functions isPrime
and primeList
that are mutually recursive for calculating primes and you should use isqrt
in the definition of isPrime
, although the use of the isqrt
isn't actually necessary; I just find it easier to think about for writing this function. (there is a hint below for how to do this step)
Using primeList
, define a recursive factorize
function that outputs a list of primes (or something similar)
Factorize the number from the question and return the largest prime in the list
What I have suggested above is usually not that great for calculating very large primes quickly, but it should be adequate for this problem. This paper goes into more detail why: http://www.cs.hmc.edu/~oneill/papers/Sieve-JFP.pdf
For future number theory related PE problems, look into using this library: https://hackage.haskell.org/package/arithmoi-0.2.0.4
Other comments:
Instead of take 1
, you should actually use head
; it's slightly better.
Also, since the biggest number you will deal with here is 600851475143, you don't actually need the function to have type Integer -> [Integer]
. 32-bit Int
doesn't do the trick, because maxBound :: Int
is 2147483647. maxBound :: Int64
, however, is 9223372036854775807, which is much more than you need. So you could just define your function to have type Int64 -> [Int64]
(or just Int -> [Int]
if the machine is 64-bit already).
Hint:
primeList
should be defined as something like primeList = 2 : 3 : filter isPrime [5,7..]
, but you can decide to be as fancy as you want with this); again, these definitions should be mutually recursive.
Upvotes: 2
Reputation: 11690
You can use filter. Here's a one-liner (well, two-liner if you count the import):
import Data.Ix (range)
fac x = head . filter ((==) 0 . mod x) . curry range 2 . floor . sqrt . fromIntegral $ x
Upvotes: 1
Reputation: 15121
I want to display the first value from [2 .. xs] such that x mod y == 0
In this case, you should not use reverse
:
fac x = take 1 $ filter (\y -> x `mod` y == 0) $ reverse [2 .. xs]
where xs = floor $ sqrt $ fromIntegral x
If you want to find out the first value starting from xs
such that mod x y == 0
, there is also no need to use reverse
:
fac x = take 1 $ filter (\y -> x `mod` y == 0) $ [xs, xs-1 .. 2]
where xs = floor $ sqrt $ fromIntegral x
Upvotes: 2
Reputation: 9457
fac x = take 1 $ filter (\y -> x `mod` y == 0 ) $ reverse [2 .. xs]
where xs = floor $ sqrt $ fromIntegral x
or, to be point-free:
fac x = take 1 $ filter ((== 0).(x `mod`)) $ reverse [2 .. xs]
where xs = floor $ sqrt $ fromIntegral x
Not sure if you want reverse
here, or what exactly is your goal.
Upvotes: 1