3

Given chars - a list of characters and words - and list of words. I wish to find all possible permutations of sentences from given words list that use all chars.

For example:

chars = '(i l o v e t e l e v i s i o n)

words = '((i) (l o v e) (v i s i o n) (t e l e) (t e l e v i s i o n))

So running (find-permutations '(i l o v e t e l e v i s i o n) '((i) (l o v e) (v i s i o n) (t e l e) (t e l e v i s i o n))) will yield the following result:

(((i) (l o v e) (t e l e) (v i s i o n)) ((i) (l o v e) (t e l e v i s i o n)))

I wrote the following code using Scheme language:

(define (substr sub str)
  (cond ((null? sub) str)
        ((null? str) #f)
        ((eq? (car sub) (car str)) (substr (cdr sub) (cdr str)))
        (else #f)))

(define (find-permutations chars words)

  (define (helper chars words1 result)
    (cond ((null? chars) (reverse result))
          ((null? words1) null)
          ((eq? chars #f) #f)
          (else (let* (
                       (x (substr (car words1) chars))
                       (y (helper x words (cons (car words1) result)))
                       (w (helper chars (cdr words1) result))
                       )
                  (if x
                      (cons y w)
                      w)
                  )
                )

          )
    )

  (trace helper)
  (helper chars words ())
  )

but i got too many brackets: ((((((i) (l o v e) (t e l e) (v i s i o n))) ((i) (l o v e) (t e l e v i s i o n)))))

I can't find why. Can anyone have an idea?

1 Answers1

1

You should use append rather than cons

(define (substr? sub str)
  (cond ((null? sub) str)
        ((null? str) #f)
        ((eq? (car sub) (car str)) (substr? (cdr sub) (cdr str)))
        (else #f)))

(define (find-permutations chars words)
  (define (helper chars words1 result)
    (cond ((null? chars)  (reverse result))
          ((null? words1) #nil)
          ((eq? chars #f) #f)
          (else (let* ((chars-substr? (substr?
                           (car words1) chars))
                       (head (helper chars-substr? words (cons (car words1) result)))
                       (tails (helper chars (cdr words1) result)))
                  (if chars-substr?
                      (append head tails)
                      tails)))))

  (helper chars words '()))

When you cons together two lists as you did in your final predicate (cons x y), you are creating a "nested" structure by assigning your new results to a deeper and deeper chain of car pointers.

You might not notice this subtle difference because convention dictates omitting the 'true' structure of an S-expression list because the car cell is where associated list data is typically held.

The following diagram shows the list (1 . (2 . (3 . (4 . ()), which would be printed as (1 2 3 4) because of this convention.

basic cons cell list

Conversely, when car holds another list (rather than a value like 1), it frequently represents a hierarchical structure, which is formatted with multiple enclosing parenthesis.

zetavolt
  • 2,989
  • 1
  • 23
  • 33