printing pairs from a list in scheme

833 views Asked by At

I'm trying to print pairs from one list kinda like a subset in scheme but with two elements just like this

(1 2 3 4 5)

((1 2) (1 3) (1 4) (1 5) (2 3) (2 4) (2 5) (3 4) (3 5) (4 5))

the code I wrote doesn't work

(define (subset x) 
(if ( null? x) x
    (map cons x (subset (cdr x)))))

this just return an empty list

3

There are 3 answers

2
Nimrod Morag On BEST ANSWER

I prefer to write the lambdas explicitly, makes it easier to understand what arguments are passed:

(define subset
    (lambda (lst)
        (if (null? lst)
            lst
            (append (map (lambda (el) (cons (car lst) el)) (cdr lst))
                    (subset (cdr lst)))
        )))

(subset '(1 2 3 4 5))
=> ((1 . 2) (1 . 3) (1 . 4) (1 . 5) (2 . 3) (2 . 4) (2 . 5) (3 . 4) (3 . 5) (4 . 5))

EDIT: The explanation about map below is only valid in some versions of scheme, read Sylwester's comment to this answer.

map traverses n lists supplied to it and applies proc to the n elements in the same position in the lists. This means it can apply proc no more times than the length of the shortest list, but you keep giving it an empty list (from the last recursive call backwards).

(BTW this is in plain scheme)

0
Sylwester On

In #lang racket that is very easy since we have combinations:

(combinations '(1 2 3 4 5) 2)
; ==> ((1 2) (1 3) (2 3) (1 4) (2 4) (3 4) (1 5) (2 5) (3 5) (4 5))

Now this does not print anything. To get it print to the terminal you can use displayln:

(displayln (combinations '(1 2 3 4 5) 2))
; ==> #<void>, ((1 2) (1 3) (2 3) (1 4) (2 4) (3 4) (1 5) (2 5) (3 5) (4 5)) printed to terminal as side effect
0
rnso On

If order of items is also important, following can be used:

(define (subsets l)
  (let loop ((n 0)                     ; run a loop for each item
             (ol '()))                 ; start with blank output list
    (cond
      [(= n (length l)) (reverse ol)]  ; output ol when last item reached; 
      [else 
       (let* ((x (list-ref l n))       ; get one item
              (jl (for/list ((i l)     ; get remaining list
                             (j (in-naturals))
                             #:unless (= j n))
                    i))
              (kl (for/list ((i jl))   ; make combinations with each of remaining list
                    (list x i))))
         (loop (add1 n) (cons kl ol)))])))

Testing:

(subsets '(1 2 3 4 5))

Output:

'(((1 2) (1 3) (1 4) (1 5))
  ((2 1) (2 3) (2 4) (2 5))
  ((3 1) (3 2) (3 4) (3 5))
  ((4 1) (4 2) (4 3) (4 5))
  ((5 1) (5 2) (5 3) (5 4)))