moved contents of unstable/set to racket/set
This commit is contained in:
parent
ccc70fca73
commit
459cce23be
|
@ -8,13 +8,16 @@
|
||||||
set? set-eq? set-eqv? set-equal?
|
set? set-eq? set-eqv? set-equal?
|
||||||
set-empty? set-count
|
set-empty? set-count
|
||||||
set-member? set-add set-remove
|
set-member? set-add set-remove
|
||||||
set-union set-intersect set-subtract
|
set-union set-intersect set-subtract set-symmetric-difference
|
||||||
subset?
|
subset? proper-subset?
|
||||||
set-map set-for-each
|
set-map set-for-each
|
||||||
(rename-out [*in-set in-set])
|
(rename-out [*in-set in-set])
|
||||||
for/set for/seteq for/seteqv
|
for/set for/seteq for/seteqv
|
||||||
for*/set for*/seteq for*/seteqv
|
for*/set for*/seteq for*/seteqv
|
||||||
set/c)
|
set/c
|
||||||
|
set=?
|
||||||
|
set->list
|
||||||
|
list->set list->seteq list->seteqv)
|
||||||
|
|
||||||
(define-serializable-struct set (ht)
|
(define-serializable-struct set (ht)
|
||||||
#:omit-define-syntaxes
|
#:omit-define-syntaxes
|
||||||
|
@ -222,17 +225,27 @@
|
||||||
(for/fold ([set set]) ([set2 (in-list sets)])
|
(for/fold ([set set]) ([set2 (in-list sets)])
|
||||||
(set-subtract set set2))]))
|
(set-subtract set set2))]))
|
||||||
|
|
||||||
(define (subset? set2 set1)
|
(define (subset* who set2 set1 proper?)
|
||||||
(unless (set? set2) (raise-type-error 'subset? "set" 0 set2 set1))
|
(unless (set? set2) (raise-type-error who "set" 0 set2 set1))
|
||||||
(unless (set? set1) (raise-type-error 'subset? "set" 0 set2 set1))
|
(unless (set? set1) (raise-type-error who "set" 0 set2 set1))
|
||||||
(let ([ht1 (set-ht set1)]
|
(let ([ht1 (set-ht set1)]
|
||||||
[ht2 (set-ht set2)])
|
[ht2 (set-ht set2)])
|
||||||
(unless (and (eq? (hash-eq? ht1) (hash-eq? ht2))
|
(unless (and (eq? (hash-eq? ht1) (hash-eq? ht2))
|
||||||
(eq? (hash-eqv? ht1) (hash-eqv? ht2)))
|
(eq? (hash-eqv? ht1) (hash-eqv? ht2)))
|
||||||
(raise-mismatch-error 'set-subset? "second set's equivalence predicate is not the same as the first set: "
|
(raise-mismatch-error who
|
||||||
|
"second set's equivalence predicate is not the same as the first set: "
|
||||||
set2))
|
set2))
|
||||||
(for/and ([v (in-hash-keys ht2)])
|
(and (for/and ([v (in-hash-keys ht2)])
|
||||||
(hash-ref ht1 v #f))))
|
(hash-ref ht1 v #f))
|
||||||
|
(if proper?
|
||||||
|
(< (hash-count ht2) (hash-count ht1))
|
||||||
|
#t))))
|
||||||
|
|
||||||
|
(define (subset? one two)
|
||||||
|
(subset* 'subset? one two #f))
|
||||||
|
|
||||||
|
(define (proper-subset? one two)
|
||||||
|
(subset* 'proper-subset? one two #t))
|
||||||
|
|
||||||
(define (set-map set proc)
|
(define (set-map set proc)
|
||||||
(unless (set? set) (raise-type-error 'set-map "set" 0 set proc))
|
(unless (set? set) (raise-type-error 'set-map "set" 0 set proc))
|
||||||
|
@ -356,3 +369,55 @@
|
||||||
blame
|
blame
|
||||||
s
|
s
|
||||||
"expected a <~a>, got ~v" (get-name c))))))))))
|
"expected a <~a>, got ~v" (get-name c))))))))))
|
||||||
|
|
||||||
|
;; ----
|
||||||
|
|
||||||
|
(define (set=? one two)
|
||||||
|
(unless (set? one) (raise-type-error 'set=? "set" 0 one two))
|
||||||
|
(unless (set? two) (raise-type-error 'set=? "set" 1 one two))
|
||||||
|
;; Sets implement prop:equal+hash
|
||||||
|
(equal? one two))
|
||||||
|
|
||||||
|
(define set-symmetric-difference
|
||||||
|
(case-lambda
|
||||||
|
[(set)
|
||||||
|
(unless (set? set) (raise-type-error 'set-symmetric-difference "set" 0 set))
|
||||||
|
set]
|
||||||
|
[(set set2)
|
||||||
|
(unless (set? set) (raise-type-error 'set-symmetric-difference "set" 0 set set2))
|
||||||
|
(unless (set? set2) (raise-type-error 'set-symmetric-difference "set" 1 set set2))
|
||||||
|
(let ([ht1 (set-ht set)]
|
||||||
|
[ht2 (set-ht set2)])
|
||||||
|
(unless (and (eq? (hash-eq? ht1) (hash-eq? ht2))
|
||||||
|
(eq? (hash-eqv? ht1) (hash-eqv? ht2)))
|
||||||
|
(raise-mismatch-error 'set-symmetric-difference
|
||||||
|
"set's equivalence predicate is not the same as the first set: "
|
||||||
|
set2))
|
||||||
|
(let-values ([(big small)
|
||||||
|
(if (>= (hash-count ht1) (hash-count ht2))
|
||||||
|
(values ht1 ht2)
|
||||||
|
(values ht2 ht1))])
|
||||||
|
(make-set
|
||||||
|
(for/fold ([ht big]) ([e (in-hash-keys small)])
|
||||||
|
(if (hash-ref ht e #f)
|
||||||
|
(hash-remove ht e)
|
||||||
|
(hash-set ht e #t))))))]
|
||||||
|
[(set . sets)
|
||||||
|
(for ([s (in-list (cons set sets))]
|
||||||
|
[i (in-naturals)])
|
||||||
|
(unless (set? s) (apply raise-type-error 'set-symmetric-difference "set" i (cons s sets))))
|
||||||
|
(for/fold ([set set]) ([set2 (in-list sets)])
|
||||||
|
(set-symmetric-difference set set2))]))
|
||||||
|
|
||||||
|
(define (set->list set)
|
||||||
|
(unless (set? set) (raise-type-error 'set->list "set" 0 set))
|
||||||
|
(for/list ([elem (in-hash-keys (set-ht set))]) elem))
|
||||||
|
(define (list->set elems)
|
||||||
|
(unless (list? elems) (raise-type-error 'list->set "list" 0 elems))
|
||||||
|
(apply set elems))
|
||||||
|
(define (list->seteq elems)
|
||||||
|
(unless (list? elems) (raise-type-error 'list->seteq "list" 0 elems))
|
||||||
|
(apply seteq elems))
|
||||||
|
(define (list->seteqv elems)
|
||||||
|
(unless (list? elems) (raise-type-error 'list->seteqv "list" 0 elems))
|
||||||
|
(apply seteqv elems))
|
||||||
|
|
|
@ -62,9 +62,6 @@
|
||||||
(define (clause-predicate c)
|
(define (clause-predicate c)
|
||||||
(literal-predicate (clause-head c)))
|
(literal-predicate (clause-head c)))
|
||||||
|
|
||||||
(define (set->list s)
|
|
||||||
(for/list ([e (in-set s)]) e))
|
|
||||||
|
|
||||||
(define literal-variables
|
(define literal-variables
|
||||||
(match-lambda
|
(match-lambda
|
||||||
[(literal _ _ ts)
|
[(literal _ _ ts)
|
||||||
|
|
|
@ -110,13 +110,64 @@ runs in time proportional to the total size of all given
|
||||||
@racket[st]s except the first one.}
|
@racket[st]s except the first one.}
|
||||||
|
|
||||||
|
|
||||||
|
@defproc[(set-symmetric-difference [st set?] ...+) set?]{
|
||||||
|
|
||||||
|
Produces a set containing only those elements found in each
|
||||||
|
@racket[st] an odd number of times. All of the given @racket[st]s must
|
||||||
|
use the same equivalence predicate (@racket[equal?], @racket[eq?], or
|
||||||
|
@racket[eqv?]). This operation runs in time proportional to the total
|
||||||
|
size of all given @racket[st]s except the first one.
|
||||||
|
|
||||||
|
@examples[#:eval set-eval
|
||||||
|
(set-symmetric-difference (set 1) (set 1 2) (set 1 2 3))
|
||||||
|
]}
|
||||||
|
|
||||||
|
|
||||||
|
@defproc[(set=? [st set?] [st2 set?]) boolean?]{
|
||||||
|
|
||||||
|
Returns @racket[#t] if @racket[st] and @racket[st2] contain the same
|
||||||
|
members, @racket[#f] otherwise. The @racket[st] and @racket[st2] must
|
||||||
|
use the same equivalence predicate (@racket[equal?], @racket[eq?], or
|
||||||
|
@racket[eqv?]). This operation runs in time proportional to the size
|
||||||
|
of @racket[st].
|
||||||
|
|
||||||
|
Equivalent to @racket[(equal? st st2)].
|
||||||
|
|
||||||
|
@examples[#:eval set-eval
|
||||||
|
(set=? (set 1) (set 1 2 3))
|
||||||
|
(set=? (set 1 2 3) (set 1))
|
||||||
|
(set=? (set 1 2 3) (set 1 2 3))
|
||||||
|
]}
|
||||||
|
|
||||||
@defproc[(subset? [st set?] [st2 set?]) boolean?]{
|
@defproc[(subset? [st set?] [st2 set?]) boolean?]{
|
||||||
|
|
||||||
Returns @racket[#t] if every member of @racket[st] is in
|
Returns @racket[#t] if every member of @racket[st] is in
|
||||||
@racket[st2], @racket[#f] otherwise. The @racket[st] and
|
@racket[st2], @racket[#f] otherwise. The @racket[st] and
|
||||||
@racket[st2] must use the same equivalence predicate
|
@racket[st2] must use the same equivalence predicate
|
||||||
(@racket[equal?], @racket[eq?], or @racket[eqv?]). This operation
|
(@racket[equal?], @racket[eq?], or @racket[eqv?]). This operation
|
||||||
runs in time proportional to the size of @racket[st].}
|
runs in time proportional to the size of @racket[st].
|
||||||
|
|
||||||
|
@examples[#:eval set-eval
|
||||||
|
(subset? (set 1) (set 1 2 3))
|
||||||
|
(subset? (set 1 2 3) (set 1))
|
||||||
|
(subset? (set 1 2 3) (set 1 2 3))
|
||||||
|
]}
|
||||||
|
|
||||||
|
|
||||||
|
@defproc[(proper-subset? [st set?] [st2 set?]) boolean?]{
|
||||||
|
|
||||||
|
Returns @racket[#t] if every member of @racket[st] is in @racket[st2]
|
||||||
|
and there is some member of @racket[st2] that is not a member of
|
||||||
|
@racket[st], @racket[#f] otherwise. The @racket[st] and @racket[st2]
|
||||||
|
must use the same equivalence predicate (@racket[equal?],
|
||||||
|
@racket[eq?], or @racket[eqv?]). This operation runs in time
|
||||||
|
proportional to the size of @racket[st].
|
||||||
|
|
||||||
|
@examples[#:eval set-eval
|
||||||
|
(proper-subset? (set 1) (set 1 2 3))
|
||||||
|
(proper-subset? (set 1 2 3) (set 1))
|
||||||
|
(proper-subset? (set 1 2 3) (set 1 2 3))
|
||||||
|
]}
|
||||||
|
|
||||||
|
|
||||||
@defproc[(set-map [st set?]
|
@defproc[(set-map [st set?]
|
||||||
|
@ -182,7 +233,27 @@ other forms.}
|
||||||
Analogous to @racket[for/list] and @racket[for*/list], but to
|
Analogous to @racket[for/list] and @racket[for*/list], but to
|
||||||
construct a set instead of a list.}
|
construct a set instead of a list.}
|
||||||
|
|
||||||
|
|
||||||
|
@deftogether[(
|
||||||
|
@defproc[(list->set [lst list?]) set?]
|
||||||
|
@defproc[(list->seteq [lst list?]) set?]
|
||||||
|
@defproc[(list->seteqv [lst list?]) set?]
|
||||||
|
)]{
|
||||||
|
|
||||||
|
Produces the appropriate type of set containing the elements of the
|
||||||
|
given list. Equivalent to @racket[(apply set lst)], @racket[(apply
|
||||||
|
seteq lst)], and @racket[(apply seteqv lst)], respectively.
|
||||||
|
}
|
||||||
|
|
||||||
|
@defproc[(set->list [st set?]) list?]{
|
||||||
|
|
||||||
|
Produces a list containing the elements of @scheme[st].}
|
||||||
|
|
||||||
|
|
||||||
@close-eval[set-eval]
|
@close-eval[set-eval]
|
||||||
|
|
||||||
@(define i #'set)
|
@(define i #'set)
|
||||||
@(define i2 #'set-union)
|
@(define i2 #'set-union)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#lang racket
|
#lang racket
|
||||||
|
|
||||||
(require rackunit rackunit/text-ui unstable/set "helpers.rkt")
|
(require rackunit rackunit/text-ui racket/set "helpers.rkt")
|
||||||
|
|
||||||
(define (check/set a-set a-list #:= [== equal?])
|
(define (check/set a-set a-list #:= [== equal?])
|
||||||
(check/sort (set->list a-set) a-list #:= ==))
|
(check/sort (set->list a-set) a-list #:= ==))
|
||||||
|
@ -32,7 +32,7 @@
|
||||||
(test (check-false (proper-subset? (set 1 2 3) (set 1))))
|
(test (check-false (proper-subset? (set 1 2 3) (set 1))))
|
||||||
(test (check-false (proper-subset? (set 1 2 3) (set 1 2 3))))))
|
(test (check-false (proper-subset? (set 1 2 3) (set 1 2 3))))))
|
||||||
(test-suite "Combinations"
|
(test-suite "Combinations"
|
||||||
(test-suite "set-exclusive-or"
|
(test-suite "set-symmetric-difference"
|
||||||
(test/set (set-exclusive-or (set 1) (set 1 2) (set 1 2 3)) (list 1 3))
|
(test/set (set-symmetric-difference (set 1) (set 1 2) (set 1 2 3)) (list 1 3))
|
||||||
(test/set (set-exclusive-or (set 1) (set 2) (set 3)) (list 1 2 3))
|
(test/set (set-symmetric-difference (set 1) (set 2) (set 3)) (list 1 2 3))
|
||||||
(test/set (set-exclusive-or (set 1 2) (set 2 3) (set 1 3)) (list))))))
|
(test/set (set-symmetric-difference (set 1 2) (set 2 3) (set 1 3)) (list))))))
|
||||||
|
|
|
@ -1,80 +0,0 @@
|
||||||
#lang scribble/manual
|
|
||||||
@(require scribble/eval "utils.rkt" (for-label racket unstable/set))
|
|
||||||
|
|
||||||
@title{Sets}
|
|
||||||
|
|
||||||
@defmodule[unstable/set]
|
|
||||||
|
|
||||||
@unstable[@author+email["Carl Eastlund" "cce@racket-lang.org"]]
|
|
||||||
|
|
||||||
This module provides tools for representing finite sets.
|
|
||||||
|
|
||||||
@deftogether[(
|
|
||||||
@defproc[(list->set [lst list?]) set?]
|
|
||||||
@defproc[(list->seteq [lst list?]) set?]
|
|
||||||
@defproc[(list->seteqv [lst list?]) set?]
|
|
||||||
)]{
|
|
||||||
|
|
||||||
Produces the appropriate type of set containing the elements of the given list.
|
|
||||||
|
|
||||||
@defexamples[
|
|
||||||
#:eval (eval/require 'racket/set 'unstable/set)
|
|
||||||
(define lst
|
|
||||||
(list 'atom (expt 2 100) (list 'compound)
|
|
||||||
'atom (expt 2 100) (list 'compound)))
|
|
||||||
(list->set lst)
|
|
||||||
(list->seteqv lst)
|
|
||||||
(list->seteq lst)
|
|
||||||
]
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@defproc[(set=? [a set?] [b set?]) boolean?]{
|
|
||||||
|
|
||||||
Reports whether two sets contain the same elements.
|
|
||||||
|
|
||||||
@defexamples[
|
|
||||||
#:eval (eval/require 'racket/set 'unstable/set)
|
|
||||||
(set=? (set 1) (set 1 2 3))
|
|
||||||
(set=? (set 1 2 3) (set 1))
|
|
||||||
(set=? (set 1 2 3) (set 1 2 3))
|
|
||||||
]
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@defproc[(proper-subset? [a set?] [b set?]) boolean?]{
|
|
||||||
|
|
||||||
Reports whether @scheme[b] contains all of the elements of @scheme[a], and at
|
|
||||||
least one element not in @scheme[a].
|
|
||||||
|
|
||||||
@defexamples[
|
|
||||||
#:eval (eval/require 'racket/set 'unstable/set)
|
|
||||||
(proper-subset? (set 1) (set 1 2 3))
|
|
||||||
(proper-subset? (set 1 2 3) (set 1))
|
|
||||||
(proper-subset? (set 1 2 3) (set 1 2 3))
|
|
||||||
]
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@defproc[(set->list [s set?]) list?]{
|
|
||||||
|
|
||||||
Produces a list containing the elements of @scheme[s].
|
|
||||||
|
|
||||||
@defexamples[
|
|
||||||
#:eval (eval/require 'racket/set 'unstable/set)
|
|
||||||
(set->list (set 1 2 3))
|
|
||||||
]
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@defproc[(set-exclusive-or [s set?] ...+) set?]{
|
|
||||||
|
|
||||||
Produces a set containing only those elements found in each @scheme[s] an odd
|
|
||||||
number of times.
|
|
||||||
|
|
||||||
@defexamples[
|
|
||||||
#:eval (eval/require 'racket/set 'unstable/set)
|
|
||||||
(set-exclusive-or (set 1) (set 1 2) (set 1 2 3))
|
|
||||||
]
|
|
||||||
|
|
||||||
}
|
|
|
@ -96,7 +96,6 @@ Keep documentation and tests up to date.
|
||||||
@include-section["pretty.scrbl"]
|
@include-section["pretty.scrbl"]
|
||||||
@include-section["require.scrbl"]
|
@include-section["require.scrbl"]
|
||||||
@include-section["sequence.scrbl"]
|
@include-section["sequence.scrbl"]
|
||||||
@include-section["set.scrbl"]
|
|
||||||
@include-section["sexp-diff.scrbl"]
|
@include-section["sexp-diff.scrbl"]
|
||||||
@include-section["string.scrbl"]
|
@include-section["string.scrbl"]
|
||||||
@include-section["struct.scrbl"]
|
@include-section["struct.scrbl"]
|
||||||
|
|
|
@ -1,43 +0,0 @@
|
||||||
#lang racket/base
|
|
||||||
(require racket/set racket/contract)
|
|
||||||
|
|
||||||
(define (set->list set)
|
|
||||||
(for/list ([elem (in-set set)]) elem))
|
|
||||||
|
|
||||||
(define (list->set elems) (apply set elems))
|
|
||||||
(define (list->seteq elems) (apply seteq elems))
|
|
||||||
(define (list->seteqv elems) (apply seteqv elems))
|
|
||||||
|
|
||||||
(define (set=? one two)
|
|
||||||
;; Sets implement prop:equal+hash
|
|
||||||
(equal? one two))
|
|
||||||
|
|
||||||
(define (proper-subset? one two)
|
|
||||||
(and (< (set-count one) (set-count two))
|
|
||||||
(subset? one two)))
|
|
||||||
|
|
||||||
(define (set-exclusive-or s0 . rest)
|
|
||||||
(for/fold ([s s0]) ([s* (in-list rest)])
|
|
||||||
(define-values [ big small ]
|
|
||||||
(if (>= (set-count s) (set-count s*))
|
|
||||||
(values s s*)
|
|
||||||
(values s* s)))
|
|
||||||
(for/fold ([s big]) ([e (in-set small)])
|
|
||||||
(if (set-member? s e)
|
|
||||||
(set-remove s e)
|
|
||||||
(set-add s e)))))
|
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
||||||
;;
|
|
||||||
;; Exports
|
|
||||||
;;
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
||||||
|
|
||||||
(provide/contract
|
|
||||||
[list->set (-> list? set?)]
|
|
||||||
[list->seteq (-> list? set?)]
|
|
||||||
[list->seteqv (-> list? set?)]
|
|
||||||
[set->list (-> set? list?)]
|
|
||||||
[set=? (-> set? set? boolean?)]
|
|
||||||
[proper-subset? (-> set? set? boolean?)]
|
|
||||||
[set-exclusive-or (->* [set?] [] #:rest (listof set?) set?)])
|
|
Loading…
Reference in New Issue
Block a user