所以我一直在尝试解决这个问题:
给定一个元素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)))
)
如果有人对如何以不同的方式提出建议,我很高兴听到。
答案 0 :(得分:1)
我不会做索引,因为它效率很低。而是颠倒输入列表,并从头到尾构建列表,从而以相反的顺序生成结果。您有一个当前列表,您可以使用cons
向其中添加元素,该列表用于向结果中添加新添加的内容,并且每个存在的每个结果级别也会添加一个元素。
作为参数,您具有状态。当我进行引用时,我使用了result
和cur
,通常我的迭代对于(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}}将增长并被共享,因此只有插入元素之前的元素对该子结果而言是唯一的。
我有一个可行的实现,但是过早获得解决方案并不有趣。玩得开心。