4

Create an infinite list pairs :: [(Integer, Integer)] containing pairs of the form (m,n), where each of m and n is a member of [0 ..]. An additional requirement is that if (m,n) is a legit member of the list, then (elem (m,n) pairs) should return True in finite time. An implementation of pairs that violates this requirement is considered a non- solution.

****Fresh edit Thank you for the comments, Lets see if I can make some progress****

    pairs :: [(Integer, Integer)]
    pairs = [(m,n) | t <- [0..], m <- [0..], n <-[0..], m+n == t]

Something like this? I just don't know where it's going to return True in finite time.

I feel the way the question is worded elem doesn't have to be part of my answer. Just if you call (elem (m,n) pairs) it should return true. Sound right?

Brian Tompsett - 汤莱恩
  • 5,195
  • 62
  • 50
  • 120
john stamos
  • 961
  • 5
  • 15
  • 32
  • 4
    Hint: Generate them one diagonal at a time. Set `t = x + y` and generate all pairs `(x, y)` for each `t` in `[0..]`. Since there are only a finite number of pairs for each `t`, this will satsify the requirements. – hammar Mar 23 '13 at 06:32
  • I like this method. Except i'm not sure how to implement it. – john stamos Mar 23 '13 at 06:46
  • 1
    Instead of filtering, generate only the possible values for `m` and `n`. For a fixed `t`, what is the highest value `m` can have? Once you've picked a `t` and `m`, you can use `t = m + n` to calculate `n` directly. – hammar Mar 23 '13 at 07:43
  • Are you sure you're explaining the problem correctly? What is the list `(m,n)` meant to hold? Perhaps the problem is to generate all `(m,n)` pairs where `m` and `n` satisfy `helper m n == True` (i.e., you know what `helper` is when you *make* the list)? – Andrew Jaffe Mar 23 '13 at 07:56
  • It's just to create an infinite list of pairs. Whole question is there. Like I say above I'm not sure if I actually have to implement (elem (m,n) pairs). Seems like it should just return true if that was called. – john stamos Mar 23 '13 at 08:00
  • Where did the `m+n==t` condition come from? Is that part of the question? I am pretty sure that your list eventually contains all possible pairs of integers, in which case the answer is always `True`! – Andrew Jaffe Mar 23 '13 at 08:07
  • the m+n==t is the filter for t so m and n get all possible pairs such as [(0,0), (0,1), (1,0), (0,2), (1,1), (2,0), ...]. Other wise it would just go [(0, _), (1 , _), (2 , _), (3 , _), (4 , _), ...] to infinity. Is this incorrect? – john stamos Mar 23 '13 at 08:27
  • Correct. But it still has *all possible pairs*. So `elem` should always just return true. Which isn't very interesting, and which is why (sorry) I still think you've mis-stated the problem. (Conversely, there is *no* way that you can actually search a list that contains an arbitrary and unknown restricted subset of all possible pairs in a constant time.) – Andrew Jaffe Mar 23 '13 at 08:35
  • Yah just copied and pasted the question. They're not always very interesting. Think this is what was intended. Yah our prof said something about that it only evaluates as much as you need, so if you call this with the situation that needs (10,_) it will evaluate to there, but has the possibility to go on infinitely. Is that correct? – john stamos Mar 23 '13 at 08:41
  • 2
    In your last revision, the question didn't make any sense anymore (as pretty much everything had been removed). I rolled it back; not sure what your intention was there (if you indeed wanted to say "this here is done, no more answers please" then don't modify your question but just accept the most helpful answer). – leftaroundabout Mar 23 '13 at 10:52

4 Answers4

8

Ignoring the helper method, the list comprehension you have will list out all pairs but the order of elements is a problem. You'll have a infinitely many pairs like (0, m) which are followed by infinitely many pairs like (1, m). Of course elem will forever iterate all the (0, m) pairs never reaching (1, m) or (2, m) etc.

I'm not sure why you have the helper method -- with it, you are only building a list of pairs like [(0,0), (1,1), (2,2), ...] because you've filtered on m = n. Was that part of the requirements?

Like @hammar suggested, start with 0 = m + n and list out the pairs (m, n). Then list pairs (m, n) where 1 = m + n. Then your list will look like [(0,0), (0,1), (1,0), (0,2), (1,1), (2,0), ...].

kputnam
  • 1,071
  • 7
  • 8
1

The helper function ensures that pairs is a list of the form [ (0,0) , (1,1) , (2,2) ... ].

So elem ( m , n ) pairs can be implemented as:

elem (m , n) _ |  m == n    = True
               |  otherwise = False

This is a constant time implementation.

Anthon
  • 51,019
  • 25
  • 150
  • 211
  • What is the underscores function here? I'll update my code now. – john stamos Mar 23 '13 at 06:39
  • @johnstamos: It's a wildcard pattern which doesn't bind the second argument of `elem` to a name. This is because this implementation doesn't actually need to see the list to check membership. – kputnam Mar 23 '13 at 06:41
  • 1
    You can eliminate the guard in the pattern match here: `elem (m, n) _ = m == n` would suffice. – kputnam Mar 23 '13 at 06:42
  • Is that still part of helper though? – john stamos Mar 23 '13 at 06:43
  • 2
    If this is a homework assignment, I would assume you aren't allowed to provide your own definition of `elem`. Instead, you're probably supposed to write `pairs` to satisfy the requirements using the `elem` from Prelude. – kputnam Mar 23 '13 at 06:47
  • Correct. as my original attempt above. I like hammars hint. Believe that's how we are to do it. – john stamos Mar 23 '13 at 06:50
1

I first posted

Prelude> let pairs = [(m, n) | t <- [0..]
                     , let m = head $ take 1 $ drop t [0..] 
                     , let n = head $ take 1 $ drop (t + 1) [0..]]

Which, I believed answered the three conditions set by the professor. But hammar pointed out that if I chose this list as an answer, that is, the list of pairs of the form (t, t+1), then I might as well choose the list

repeat [(0,0)] 

Well, both of these do seem to answer the professor's question, considering there seems to be no mention of the list having to contain all combinations of [0..] and [0..].

That aside, hammer helped me see how you can list all combinations, facilitating the evaluation of elem in finite time by building the infinite list from finite lists. Here are two other finite lists - less succinct than Hammar's suggestion of the diagonals - that seem to build all combinations of [0..] and [0..]:

edges = concat [concat [[(m,n),(n,m)] | let m = t, n <- take m [0..]] ++ [(t,t)] 
      | t <- [0..]]


*Main> take 9 edges
[(0,0),(1,0),(0,1),(1,1),(2,0),(0,2),(2,1),(1,2),(2,2)]

which construct the edges (t, 0..t) (0..t, t), and

oddSpirals size = concat [spiral m size' | m <- n] where
  size' = if size < 3 then 3 else if even size then size - 1 else size
  n = map (\y -> (fst y * size' + div size' 2, snd y * size' + div size' 2)) 
          [(x, t-x) | let size' = 5, t <- [0..], x <- [0..t]]
  spiral seed size = spiral' (size - 1) "-" 1 [seed]
  spiral' limit op count result
    | count == limit =
       let op' = if op == "-" then (-) else (+)
           m = foldl (\a b -> a ++ [(op' (fst $ last a) b, snd $ last a)]) result (replicate count 1)
           nextOp = if op == "-" then "+" else "-"
           nextOp' = if op == "-" then (+) else (-)
           n = foldl (\a b -> a ++ [(fst $ last a, nextOp' (snd $ last a) b)]) m (replicate count 1)
           n' = foldl (\a b -> a ++ [(nextOp' (fst $ last a) b, snd $ last a)]) n (replicate count 1)
       in n'
    | otherwise      =
        let op' = if op == "-" then (-) else (+)
            m = foldl (\a b -> a ++ [(op' (fst $ last a) b, snd $ last a)]) result (replicate count 1)
            nextOp = if op == "-" then "+" else "-"
            nextOp' = if op == "-" then (+) else (-)
            n = foldl (\a b -> a ++ [(fst $ last a, nextOp' (snd $ last a) b)]) m (replicate count 1)
        in spiral' limit nextOp (count + 1) n


*Main> take 9 $ oddSpirals 3
[(1,1),(0,1),(0,2),(1,2),(2,2),(2,1),(2,0),(1,0),(0,0)]

which build clockwise spirals of length 'size' squared, superimposed on hammar's diagonals algorithm.

גלעד ברקן
  • 21,095
  • 3
  • 19
  • 57
  • This only generates pairs of the form `(t, t+1)`. – hammar Mar 23 '13 at 12:59
  • The problem is to generate _all_ pairs of natural numbers, such that for any given pair it is found at some finite index in the list. – hammar Mar 23 '13 at 13:01
  • @hammar I believe I answered the three conditions: (1) infinite list pairs :: [(Integer, Integer)], (2) containing pairs of the form (m,n), where each of m and n is a member of [0 ..], and (3) elem (m,n) pairs) should return True in finite time. Did I not? – גלעד ברקן Mar 23 '13 at 13:03
  • For example, `elem (0, 0) pairs` does not return `True` in finite time. – hammar Mar 23 '13 at 13:08
  • @hammar that's because it is not true. If it is True, it does. – גלעד ברקן Mar 23 '13 at 13:09
  • If that was the task, any infinite list of the appropriate type would work. – hammar Mar 23 '13 at 13:10
  • `repeat (0, 0)`, for example, or even `pairs = pairs`. `elem` will only ever return `False` for a finite list. – hammar Mar 23 '13 at 13:12
  • @hammar I see what you mean. You can generate (potentially) all combinations and produce an answer to elem in finite time? by the way, where are m and n in your example? – גלעד ברקן Mar 23 '13 at 13:14
  • 1
    Since it's clearly homework, I've been trying to avoid giving the solution, but here it is: `[(x, t-x) | t – hammar Mar 23 '13 at 13:15
  • @hammar nice. it seems that n in this case is drawn from [0..m], though, not from [0..] – גלעד ברקן Mar 23 '13 at 13:20
  • No, it will hit all the pairs. If you imagine `(m, n)` as cartesian coordinates in an infinite square grid, this list comprehension hits them all one diagonal at a time. Each diagonal corresponds to a value of `t`, which we then run through from `(0, t)` to `(t, 0)`. Try drawing it on paper if you're having trouble. – hammar Mar 23 '13 at 13:26
  • @hammar hammar, I understand that it will generate all pairs, I'm just pointing out that, technically, n in your solution is coming from [0..m] and not from [0..] – גלעד ברקן Mar 23 '13 at 13:27
  • No, that would imply that I only generate pairs where `n <= m`, which is not the case. – hammar Mar 23 '13 at 13:29
  • @hammar my mistake, in your solution, m is defined as from [0..t], n is defined as t-m. But that is a technicality; m and n are indeed members of [0..] in your solution. I focused on the technical part, thinking m and n should be expressed directly from [0..] – גלעד ברקן Mar 23 '13 at 13:35
  • @hammar Your solution seems to handle False just like mine, by the way. Try elem (-1,2) pairs – גלעד ברקן Mar 23 '13 at 13:39
  • Yes, but `-1` is not a member of `[0..]`. – hammar Mar 23 '13 at 13:40
  • @hammar thanks for the valuable lesson, I had fun trying different finite lists http://stackoverflow.com/questions/15583975/haskell-infinite-list-of-incrementing-pairs/15586940#15586940 – גלעד ברקן Mar 24 '13 at 17:11
0

I believe the solution to your task is:

pairs = [(x,y) | u <- [0..], x <- [0..u], y <-[0..u] , u == x+y]

  • @ali_homsi The pattern of the output of your functions is, 1st digit: `0, 0 1, 0 1 2, 0 1 2 3` and the 2nd digit `0, 1 0, 2 1 0, 3 2 1 0`. When zipped they are your output. It is a Cartesian product and fits perfectly. `diag xs ys = [ (m,n) | i – fp_mora Mar 24 '21 at 16:05