gib*_*ian 3 lisp scheme functional-programming
如何在 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))
Run Code Online (Sandbox Code Playgroud)从列表 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))))
Run Code Online (Sandbox Code Playgroud)然后,这就是我的问题:我如何递归这个过程以获得预期的程序?我应该使用for/list粘贴此过程 1. 和 2. 获得的所有子列表吗?
如果我们把问题分成几块,那就更容易了。首先,让我们编写几个过程,允许我们n从列表中获取或删除元素,如果列表中没有足够的元素,就会得到适当的结果(如果不是这样,我们可以使用内置的takeand 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))))
Run Code Online (Sandbox Code Playgroud)
有了上述两个过程,很容易创建另一个过程来将列表中的元素分组为 n 大小的子列表:
(define (group lst n)
(if (null? lst)
'()
(cons (take-up-to lst n)
(group (drop-up-to lst n) n))))
Run Code Online (Sandbox Code Playgroud)
最后,我们将我们的分组过程与 结合起来shuffle,这会随机化列表的内容:
(define (random-groups lst n)
(group (shuffle lst) n))
Run Code Online (Sandbox Code Playgroud)
它按预期工作:
(random-groups '(a e i o u) 2)
=> '((e a) (u i) (o))
Run Code Online (Sandbox Code Playgroud)