0

I want to create a list of pairs (a . b) with 1 < a < b <= n up to n, e.g. n = 5:

((2 . 3) (2 . 4) (3 . 4) (2 . 5) (3 . 5) (4 . 5))

(The order of the pairs is not critical.)

I came up with the code

(defun create-pairs (upper-bound)
  (loop for i from 3 to upper-bound
        for j from 2 to (1- upper-bound)
          collecting (cons j i)))

but that doesn't do what I wanted

* (create-pairs 5)
((2 . 3) (3 . 4) (4 . 5))

since the loops are incrementing at the same time.

Therefore I tried this

(defun create-pairs (upper-bound)
  (loop for i from 3 to upper-bound do
    (loop for j from 2 to (1- upper-bound)
      collecting (cons j i))))

with the result:

* (create-pairs 5)

NIL

I don't remember where but I read that it's not possible to use collecting in constructs like my second try.

So how do I get the result I want to have? Isn't it possible to solve this with loop for?

nicksheen
  • 550
  • 6
  • 23

1 Answers1

4

You are almost there - you just need to accumulate the results of the inner loop:

(defun create-pairs (upper-bound)
  (loop for i from 3 to upper-bound nconc
    (loop for j from 2 below i
      collect (cons j i))))
(create-pairs 5)
==> ((2 . 3) (2 . 4) (3 . 4) (2 . 5) (3 . 5) (4 . 5))
sds
  • 58,617
  • 29
  • 161
  • 278