简体   繁体   中英

Scheme / Racket insert-everywhere function with sublists

So I've been trying to solve this problem:

Given an element E and a list L insert E into every position in the list L (so the result is a list of lists). Example: (insert-everywhere 'a '(bc)) would give ((abc) (bac) (bca))

This is easy enough but there is one other condition in my problem that is making it difficult for me - if an element of L is a list itself then the element must also be inserted into every position in the sublist. For example:

(insert-everywhere 'd '(a (bc))) would return: ((da (bc)) (ad (bc)) (a (dbc)) (a (bdc)) (a (bcd)) (a (bc) d)) .

This is the code I have so far (which I mostly lifted from here ):

#lang racket
(define (insert-at pos elmt lst) 
 (if (empty? lst) (list elmt)
 (if (list? (car lst)) (insert-everywhere elmt (car lst))
 (if (= 1 pos)
  (cons elmt lst)
  (cons (first lst) 
        (insert-at (- pos 1) elmt (rest lst)))))))

(define (insert-everywhere sym lst)
  (remove-duplicates
    (map (lambda (i)
      (insert-at i sym lst))
        (range 1 (+ 2 (length lst))))))

where this line: (if (list? (car lst)) (insert-everywhere elmt (car lst)) is supposed to handle the sublists but it isn't working. (If I run (insert-everywhere 'd '(a (bc))) with the above code I get ((da (bc)) (a (dbc) (bdc) (bcd))) )

If anyone has suggestions on how to approach this differently I'd be happy to hear.

I wouldn't do indexing as it is very inefficient. Rather reverse the input list and build the list from end to beginning making the results in reverse order. You have a current list that you add elements to with cons that you use to add new additions to the results and each level each result that existed gets the one element added too.

As parameters you have state. When i made a reference I used result and cur and typically my iteration did like this for (insert-everywhere 'd '(abc)) :

lst     cur     results
(c b a) ()      ((d))
(b a)   (c)     ((d c) (c d))
(a)     (b c)   ((d b c) (b d c) (b c d))
()      (a b c) ((d a b c) (a d b c) (a b d c) (a b c d)))

Now adding support for sublists are just doing the same with them and then do a map such that you create one result per sublist in the result, adding cur in addition to adding it as an element.

Notice all new results are just cur with an added inserted element and all th erest gets a new element in fron which is the first element of the input. cur will grow and it is shared so only the elements up to the inserted element will be unique to that sub result.

I have a working implementation, but it's no fun getting the solution prematurely. Have fun.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM