Как сделать powerset в DrRacket?
Я использую начальный язык со списком сокращений для DrRacket и хочу рекурсивно сделать powerset, но не могу понять, как это сделать. У меня сейчас так много
(define
(powerset aL)
(cond
[(empty? aL) (list)]
любая помощь будет хорошей.
4 ответа
Что в powerset? Подмножества набора. Пустой набор является подмножеством любого набора, так что powerset пустого набора не пуст. Единственный его элемент - это пустой набор:
(define
(powerset aL)
(cond
[(empty? aL) (list empty)]
[else
Что касается непустых множеств, есть выбор, для каждого элемента набора, будь то или не быть включенным в подмножество который является членом powerset.
Таким образом, мы продвигаемся по списку ввода, объединяя каждый элемент с результирующим набором, то, что мы получаем рекурсивно наша процедура для остальной части ввода:
(add-into (powerset (rest aL))
(first aL))]))
(define
(add-into r a) ; `r` is recursive result, `a` is first element
(cond
[(empty? r) empty] ; nothing to add `a` to
[else
(cons (cons a (first r)) ; either add `a`,
(cons (first r) ; or not, to the first in `r`
(add-into ; and recursively proceed
(rest r) ; to add `a` into the rest of `r`
a )))]))
"Там нет ответов, только выбор". Скорее, сделанный выбор - вот из чего сделан ответ.
В ракетке,
#lang racket
(define (power-set xs)
(cond
[(empty? xs) (list empty)] ; the empty set has only empty as subset
[(cons? xs) (define x (first xs)) ; a constructed list has a first element
(define ys (rest xs)) ; and a list of the remaining elements
;; There are two types of subsets of xs, thouse that
;; contain x and those without x.
(define with-out-x ; the power sets without x
(power-set ys))
(define with-x ; to get the power sets with x we
(cons-all x with-out-x)) ; we add x to the power sets without x
(append with-out-x with-x)])) ; Now both kind of subsets are returned.
(define (cons-all x xss)
; xss is a list of lists
; cons x onto all the lists in xss
(cond
[(empty? xss) empty]
[(cons? xss) (cons (cons x (first xss)) ; cons x to the first sublist
(cons-all x (rest xss)))])) ; and to the rest of the sublists
Тестировать:
(power-set '(a b c))
Вот еще одна реализация, после нескольких тестов она кажется быстрее, чем ответ Криса для больших списков. Он был протестирован с использованием стандартной ракетки:
(define (powerset aL)
(if (empty? aL)
'(())
(let ((rst (powerset (rest aL))))
(append (map (lambda (x) (cons (first aL) x))
rst)
rst))))
Вот моя реализация набора мощности (хотя я тестировал его только на стандартном языке Racket, а не на Beginning Student):
(define (powerset lst)
(if (null? lst)
'(())
(append-map (lambda (x)
(list x (cons (car lst) x)))
(powerset (cdr lst)))))
(Спасибо Sam Tobin-Hochstadt за напоминание, что flatmap называется append-map
в ракетку!)
Вы можете просто использовать побочный эффект:
(define res '())
(define
(pow raw leaf)
(cond
[(empty? raw) (set! res (cons leaf res))
res]
[else (pow (cdr raw) leaf)
(pow (cdr raw) (cons (car raw) leaf))]))
(pow '(1 2 3) '())