Будет проще, если мы разделим проблему на куски.Во-первых, давайте напишем пару процедур, которые позволят нам брать или удалять 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))