Reputation: 59
I'm a total newbie to Haskell, and programming in general, but I'm trying to work through some Project Euler problems because I do like problem solving. However, I have a problem with problem #12.
I devised a solution I thought would work, but alas, it does not.
Can you help me by opening my eyes to the problem with my code, and maybe push me in the right direction towards fixing it? Thank you.
Here is the code:
triangleNumber = scanl1 (+) [1..]
factors n = [x | x <- [1..n], n `mod` x == 0]
numFactors = length . factors
eulerTwelve = find ((>500) . numFactors) triangleNumber
Thank you very much! :)
Upvotes: 5
Views: 899
Reputation: 31579
I assume the problem you're alluding to is that eulerTwelve
takes way too long to terminate; your code is correct, it's just inefficient. The bottleneck is your factors
function, which is trying every number between 1 and n
to see if it's a divisor of n
. Here's a faster way to find the divisors of a number, using efficient prime factorization and a nifty implementation of the power set:
import Data.Numbers.Primes (primeFactors)
powerSet = filterM (const [True, False])
factors = map product . nub . powerSet . primeFactors
Even this is pretty inefficient; you can instead calculate numFactors
directly from primeFactors
like so:
numFactors = product . map ((+1) . length) . group . primeFactors
When I replace your numFactors
with this one I obtain the result instantly.
Upvotes: 1
Reputation: 65854
The Project Euler questions are designed so that it's a bad idea to try solve them by "brute force", that is, by programming the obvious search and just leaving it to run. (Some of the earlier questions can be solved like that, but it's a good idea not to exploit that, but to use them as practice.) Instead, you have to think about the mathematical content of the question so as to make the computer search tractable.
I don't want to give away too much, but here are some hints:
There's a formula for the nth triangular number. Find it, so you don't have to compute it by summation.
Given this formula for the nth triangular number, what numbers can possibly be its divisors?
Given what you know about these divisors, what's an easy way to figure out how many of them are there? (Without having to enumerate them.)
Upvotes: 3
Reputation: 47
IIRC when checking for factors you don't need to test every integer between 1 and n - only the numbers between 1 and n^0.5 (squareroot of n), since at this number you will already have obtained all the factors available.
Upvotes: 0
Reputation: 6855
I copied it and what it threw me was an error that find couldn't be found. That is because you need to import the module List where find is in:
import Data.List
By the way, you should optimize your factors function.
Upvotes: 2