0

I'm new to Scheme language and I'm trying to build a method which gets as parameters a list and a number 'n' and returns all sublists sized n.

for example, if the method receives '(a b c d) and 2, it will return '('(a b) '(b c) '(c d)).

the method must be recursive.

I have managed to get the first sized n list but am stuck from there.

thanks in advance.

(define sub-lists
  (lambda (lst n)
    (if (zero?  n)
        '()
        (cons (car los) (sub-lists (cdr lst) (- n 1))))))
Will Ness
  • 70,110
  • 9
  • 98
  • 181
Avishai Yaniv
  • 420
  • 5
  • 15

1 Answers1

0

Here's a way you can do it using append and map -

(define (choose n l)
  (cond ((zero? n)
         (list null))
        ((null? l)
         null)
        (else
         (append (map (lambda (comb)
                        (cons (car l) comb))
                      (choose (- n 1)
                              (cdr l)))
                 (choose n
                         (cdr l))))))

It provides a valid result for any natural n, including zero -

(choose 3 '(a b c))
;; '((a b c))

(choose 2 '(a b c))
;; '((a b) (a c) (b c))

(choose 1 '(a b c))
;; '((a) (b) (c))

(choose 0 '(a b c))
;; '(())

It provides a valid result when n exceeds the size of l too -

(choose 4 '(a b c))
;; '()

Possible implementations for append and map -

(define (append a b)
  (if (null? a)
      b
      (cons (car a)
            (append (cdr a)
                    b))))

(define (map f l)
  (if (null? l)
      null
      (cons (f (car l))
            (map f
                 (cdr l)))))

If you wish for elements to be repeated, you only need change one expression -

(define (choose n l)
  (cond ((zero? n)
         (list null))
        ((null? l)
         null)
        (else
         (append (map (lambda (comb)
                        (cons (car l) comb))
                      (choose (- n 1)
                              l)) ;; change (cdr l) to l
                 (choose n
                         (cdr l))))))

The combinations now contain repeated elements -

(choose 3 '(a b c))
;; '((a a a) (a a b) (a a c) (a b b) (a b c) (a c c) (b b b) (b b c) (b c c) (c c c))

(choose 2 '(a b c))
;; '((a a) (a b) (a c) (b b) (b c) (c c))

(choose 1 '(a b c))
;; '((a) (b) (c))

(choose 0 '(a b c))
;; '(())

Notice the significant difference in the scenario where n exceeds l -

(choose 4 '(a b c))
;; '((a a a a)
;;   (a a a b)
;;   (a a a c)
;;   (a a b b)
;;   (a a b c)
;;   (a a c c)
;;   (a b b b)
;;   (a b b c)
;;   (a b c c)
;;   (a c c c)
;;   (b b b b)
;;   (b b b c)
;;   (b b c c)
;;   (b c c c)
;;   (c c c c))
Mulan
  • 129,518
  • 31
  • 228
  • 259
  • First of all thanks so much for the detailed answer! second, it is not what I was asking. for (a b c) and 2 the result should be '('(a b) '(b c) '(c d)). – Avishai Yaniv Mar 16 '19 at 08:59
  • How can there be a `'d` when the input is `'(a b c)`? The answer for `(choose 2 '(a b c d))` is `'((a b) (a c) (a d) (b c) (b d) (c d))`, which this program produces. Did I overlook something else? – Mulan Mar 16 '19 at 17:25
  • cf. [this entry](https://stackoverflow.com/q/54129886/849891) for another lisp-y language, incl. the [answer](https://stackoverflow.com/a/54166678/849891) by @dfeuer which I still have to work through after all this time.... :) apparently this is a popular problem, there's lots of linked entries there (transitively speaking). ---- apparently here the OP meant something different, just `\n -> foldr (zipWith (:)) (repeat []) . take n . iterate tail` (a [popular](https://stackoverflow.com/a/24609264/849891) [problem](https://stackoverflow.com/a/40449148/849891) in its own right.... ). – Will Ness May 20 '20 at 17:32