1

I am attempting to make an algorithm to solve Project Euler Problem 255

I came up with this solution:

roundedSq n | (roundedSq n) == roundedSq (n-1) = n : roundedSq (n+1)
            | rem n 2 == 1  = n : floor ( ((2*10^((d-1) `div` 2)) + ceiling (n `div` (2*10^((d-1) `div` 2)) )) `div` 2 )
            | otherwise     = n : floor ( ((7*10^((d-2) `div` 2)) + ceiling (n `div` (7*10^((d-2) `div` 2)) )) `div` 2 )
        where
                d = length (map (digitToInt) (show (n)))
                        
average a = (sum a) `div` (length a)
answer = average [map roundedSq [10E13..10E14]]

main = do
  print answer

But every time I try to load, it comes with an error for the answer calculating function. What have I done wrong and will this even give me a correct solution or will it just get stick in a loop??

4 Answers 4

5
answer = average [map roundedSq [10E13..10E14]]

You've put the mapped list into a list of one element here. I think perhaps you mean:

answer = average (map roundedSq [10E13..10E14])
Sign up to request clarification or add additional context in comments.

Comments

2

There is a problem with your average.

average a = (sum a) `div` (length a)

sum uses the entire list. length also uses the entire list. This means that the whole list will be generated and held in memory while one of these functions traverses it, and will not be garbage collected until the other function traverses it.

You pass average a very large list, so you will run out of memory.

Solution: rewrite average as a function that only traverses the list once, so that the list can be garbage collected as it is generated.

Example (untested):

average a = sum `div` length
  where (sum, length) = foldl' f (0, 0) a
        f (sum, length) i = (sum + i, length + 1)

Note that this uses foldl', from Data.List, not foldl. foldl has its own space issues (which someone more knowledgeable than me may wish to comment on).

And as Tobias Wärre has pointed out,

roundedSq n | (roundedSq n) == roundedSq (n-1) = n : roundedSq (n+1)

will result in an endless loop:

  1. we want to evaluate roundedSq n
  2. if (roundedSq n) == roundedSq (n-1) is true, we will return n : roundedSq (n+1) as the answer
  3. we need to evaluate (roundedSq n) == roundedSq (n-1)
  4. we need to evaluate roundedSq n
  5. goto 1.

2 Comments

I thought that: roundedSq n | (roundedSq n) == roundedSq (n-1) = n : roundedSq (n+1) would check to see if the current iteration is the same as the one before it, it will go to the next one with = n : roundedSq (n+1)
See my edit. You need a different way of detecting when you can stop iterating.
1

If you want average to return a Fractional number you'll need to use this definition:

average a = (sum a) / (fromIntegral $ length a)

(/) is the Fractional division operator whereas div is the Integral division operator. Note you also need to use fromIntegral because length returns an Int which is not a part of the Fractional type class.

1 Comment

You can also use genericLength from Data.List instead of combining length and fromIntegral.
0

You'll get stuck in an infinite loop due to

roundedSq n | (roundedSq n) ...

Edit: Sometimes it seems like I have a hole in my head. Of course average is ok.

However, since you don't decrement or increment all recursive calls to roundedSq you will never hit the "bottom" and terminate.

3 Comments

I tried loading only the average function and I got a correct answer for the when I typed: average [5..10] i got the answer 7. So the question arises as to how to make it list the average to 10 decimal places
I don't see what's wrong with the usage of average, it's just a function of type [Int] -> Int ?
I fixed it with: average :: [Double] -> Double average a = (sum a) / (fromIntegral $(length a)) :: Double It seemed that using div was the source of the error

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.