方案/球拍无处不在功能与子列表

时间:2018-11-06 18:26:23

标签: functional-programming scheme racket

所以我一直在尝试解决这个问题:

给定一个元素E和一个列表L,将E插入列表L中的每个位置(因此结果是一个列表列表)。例: (insert-everywhere 'a '(b c))会给((a b c) (b a c) (b c a))

这很容易,但是我的问题中还有一个条件使我感到困难-如果L的元素本身是列​​表,那么该元素也必须插入子列表的每个位置。例如:

(insert-everywhere 'd '(a (b c)))将返回:((d a (b c)) (a d (b c)) (a (d b c)) (a (b d c)) (a (b c d)) (a (b c) d))

这是我到目前为止拥有的代码(我大多从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))))))

此行:(if (list? (car lst)) (insert-everywhere elmt (car lst))应该可以处理子列表,但是不起作用。 (如果我使用上面的代码运行(insert-everywhere 'd '(a (b c))),则会得到((d a (b c)) (a (d b c) (b d c) (b c d)))

如果有人对如何以不同的方式提出建议,我很高兴听到。

1 个答案:

答案 0 :(得分:1)

我不会做索引,因为它效率很低。而是颠倒输入列表,并从头到尾构建列表,从而以相反的顺序生成结果。您有一个当前列表,您可以使用cons向其中添加元素,该列表用于向结果中添加新添加的内容,并且每个存在的每个结果级别也会添加一个元素。

作为参数,您具有状态。当我进行引用时,我使用了resultcur,通常我的迭代对于(insert-everywhere 'd '(a b c))就是这样的:

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)))

现在添加对子列表的支持只是对它们的处理,然后进行映射,以便您在结果中的每个子列表中创建一个结果,除了将cur添加为元素之外,还添加了cur

请注意,所有新结果都只是添加了一个插入的元素而已,并且所有结果都在fron中获得了一个新元素,它是输入的第一个元素。 {{1}}将增长并被共享,因此只有插入元素之前的元素对该子结果而言是唯一的。

我有一个可行的实现,但是过早获得解决方案并不有趣。玩得开心。