Take the 2-minute tour ×

I need a program that checks if the difference between all pairs of elements is in the interval from -2 up to 2 ( >= -2 && < 2). If it is, then return True, else return False. Foe example, [1,2,3] is True, but [1,3,4] is False. I am using the all function. What is wrong with my if clause?

allfunc (x : xs)
   = if all (...) xs
      then allfunc xs
      else [x] ++ allfunc xs
allfunc _
   = []

Or I am doing something completely wrong?

share|improve this question
You should note that this combines using a continuation, and using something which you could probably write better as a fold. –  Kristopher Micinski Jun 12 '12 at 17:20
Is the order relevant? what's the output for [-2,0]? –  is7s Jun 12 '12 at 17:58
add comment

5 Answers

up vote 3 down vote accepted

For this, it's probably easier to use list comprehensions or do-notation.

pairsOf lst = do 
  x <- lst
  y <- lst
  return (x, y)

pairsOf returns the list of pairs of numbers in the input lst. For example, pairsOf [1,2,3] results in [(1,1),(1,2),(1,3),(2,1),(2,2),(2,3),(3,1),(3,2),(3,3)].

Now, you can define the difference between a pair in a one-liner \(x, y) -> x - y and map that over the list:

differences lst = map (\(x, y) -> x - y) (pairsOf lst)

Now you just have to make sure that each element in differences lst is between -2 and 2.

Of course, this is just one possible way to do it. There are many other ways as well.

share|improve this answer
One could probably simplify and do something like: diffs lst= [ (x - y) | x<-lst, y<-lst], then push the result list of differences into checkDiffS = all (\x-> x<2 && x>-2) –  user268396 Jun 12 '12 at 17:21
add comment

The naive way to do what you describe is:

allfunc xs = all (<=2) [abs(a-b) | a <- xs, b <- xs ]

However, a more efficient method would be to compare the minimum and maximum of the list:

fastfunc [] = true
fastfunc xs = maximum xs - minimum xs <= 2
share|improve this answer
add comment

Why not simply...

allfunc xs = (maximum xs - minimum xs) <= 2

Or if you really want to investigate every pair, you can use monads:

import Control.Monad
allfunc xs = all ((<=2).abs) $ liftM2 (-) xs xs

liftA2 from Control.Applicative would do as well.

share|improve this answer
add comment

Basically, yes you're doing something wrong. all is meant to take a predicate and a list of values to test. So it will return True if and only if all values yield true when applied to the given predicate function. I.e.:

allValuesEven = all even
allValuesOdd  = all odd
share|improve this answer
Your first sentence is incorrect: [] does not match the pattern x:xs. –  Daniel Wagner Jun 12 '12 at 17:55
add comment

Well, the problem specification isn't very clear.

You say:

the diffence between all elements is in interval from -2 till 2 ( >= -2 && < 2)

But also:


How is it True for [1,2,3]?

Assuming you mean -2 <= diff <= 2, then I would use this:

allfunc :: (Ord a, Num a) => [a] -> Bool
allfunc theList = all (\x -> (x >= -2) && (x<2)) [x-y | x <- theList, y <- theList ]

allfunc [1,2,3] -- => True
allfunc [1,3,4] -- => False
share|improve this answer
add comment

Your Answer

