我如何在Scheme中实现一个程序,该程序采用给定列表的元素并返回一个新列表,其中的元素是前一个列表的随机集合?我希望它可以工作任何长度。例如:
输入:'(a e i o u)
,输出:'((a e) (i o) (u))
,长度为2。
我的尝试(使用for / list)很笨拙,并且基于递归。我按照Óscar的建议划分了任务:
从列表l中随机选择n个元素:
(define (pick-n-random l n)
(take (shuffle l) n))
从列表l1中删除列表l2:
(define (cut l1 l2)
(cond ((null? l1)
'())
((not (member (car l1) l2))
(cons (car l1) (cut (cdr l1) l2)))
(else
(cut (cdr l1) l2))))
然后,这就是我的问题:如何在此过程中递归以获得所需的程序?我是否应该使用for/list
粘贴此过程1.和2.获得的所有子列表?
答案 0 :(得分:4)
将问题分成多个部分会更容易。首先,让我们编写一些过程,这些过程将允许我们从列表中取出或删除n
元素,如果列表中没有足够的元素,则可以得到适当的结果(如果不是,则可以使用内置take
和drop
):
(define (take-up-to lst n)
(if (or (<= n 0) (null? lst))
'()
(cons (car lst) (take-up-to (cdr lst) (sub1 n)))))
(define (drop-up-to lst n)
(if (or (<= n 0) (null? lst))
lst
(drop-up-to (cdr lst) (sub1 n))))
有了上述两个过程,就很容易创建另一个过程来将列表中的元素分组为n个大小的子列表:
(define (group lst n)
(if (null? lst)
'()
(cons (take-up-to lst n)
(group (drop-up-to lst n) n))))
最后,我们将分组过程与shuffle
结合使用,这会随机化列表的内容:
(define (random-groups lst n)
(group (shuffle lst) n))
它按预期工作:
(random-groups '(a e i o u) 2)
=> '((e a) (u i) (o))