0

Task is to find all two-valued numbers representable as the sum of the roots of two natural numbers using list's generator and print all these combinations + length of list. I got this:

import Data.List

func = filter (>9) (takeWhile (<100) (nub [floor (sqrt (x) + sqrt (y)) | x <- [0..], y <- [0..]]))
l = length func

How can I print every combination, not just result?

1 Answers1

3

I suspect by "How can I print every combination?", what you mean is "How do I get the x and y values that gave me the appropriate sum?". The minimal fix is to have the list comprehension return x, y, and the sum all at once, and modify your filter and dropWhile to ignore the x and y bits. Thus:

func = id
    . filter (\(x,y,sum) -> sum > 9)
    . takeWhile (\(x,y,sum) -> sum < 100)
    . nub
    $ [(x,y,floor (sqrt (x) + sqrt (y))) | x <- [0..], y <- [0..]]

There is also a nubBy that may interest you. However, there remain many "thinkos" that you should address, one at a time:

  1. func is a bad name; the name implies that it is a function, which isn't true.
  2. You are not checking that the sqrts add to an integer; instead, you are forcing their sum to be an integer.
  3. Your iteration strategy will never choose an x other than 0. You should either limit the upper bounds of your iterations by a known worst-case, e.g. by

    x <- [0..100^2], y <- [0..100^2]
    

    or apply the fix described in another of my answers.

  4. Once you have fixed the previous bit, you will notice that the sums are not monotonically increasing. This means that your takeWhile strategy for deciding when to stop will not be correct.
  5. Once you have had some practice fixing this algorithm, you should rethink whether this is the right algorithm to use. (i.e. why are we iterating over so many x and y values which are not squares?)
Daniel Wagner
  • 145,880
  • 9
  • 220
  • 380