diff --git a/collection/multiset.rkt b/collection/multiset.rkt index ddb4e75..bcb3538 100644 --- a/collection/multiset.rkt +++ b/collection/multiset.rkt @@ -18,6 +18,8 @@ [multiset-set-frequency (-> multiset? any/c natural? multiset?)] [multiset-contains? (-> multiset? any/c boolean?)] [multiset-contains-all? (-> multiset? multiset-coercible-sequence/c boolean?)] + [multiset-contains-any? (-> multiset? multiset-coercible-sequence/c boolean?)] + [multiset-contains-none? (-> multiset? multiset-coercible-sequence/c boolean?)] [multiset-frequency (-> multiset? any/c natural?)] [multiset-frequencies (-> multiset? (immutable-hash/c any/c exact-positive-integer?))] [multiset-size (-> multiset? natural?)] @@ -346,6 +348,7 @@ (module+ test (test-case (name-string multiset-contains-all?) (define letters (multiset 'a 'b 'b 'b 'c 'c 'd)) + (check-true (multiset-contains-all? letters (list))) (check-true (multiset-contains-all? letters (list 'a 'b))) (check-true (multiset-contains-all? letters (list 'a 'a 'a 'a 'a))) (check-false (multiset-contains-all? letters (list 'c 'd 'e 'f))) @@ -356,6 +359,44 @@ (check-false (multiset-contains-all? letters (multiset 'e 'e 'e))))) +(define (multiset-contains-any? set seq) + (let* ([seq (if (multiset? seq) (multiset-unique-elements seq) seq)]) + (for/or ([v seq]) + (multiset-contains? set v)))) + + +(module+ test + (test-case (name-string multiset-contains-any?) + (define letters (multiset 'a 'b 'b 'b 'c 'c 'd)) + (check-false (multiset-contains-any? letters (list))) + (check-true (multiset-contains-any? letters (list 'a 'b))) + (check-true (multiset-contains-any? letters (list 'a 'a 'a 'a 'a))) + (check-true (multiset-contains-any? letters (list 'c 'd 'e 'f))) + (check-false (multiset-contains-any? letters (list 'e 'e 'e))) + (check-true (multiset-contains-any? letters (multiset 'a 'b))) + (check-true (multiset-contains-any? letters (multiset 'a 'a 'a 'a 'a))) + (check-true (multiset-contains-any? letters (multiset 'c 'd 'e 'f))) + (check-false (multiset-contains-any? letters (multiset 'e 'e 'e))))) + + +(define (multiset-contains-none? set seq) + (not (multiset-contains-any? set seq))) + + +(module+ test + (test-case (name-string multiset-contains-none?) + (define letters (multiset 'a 'b 'b 'b 'c 'c 'd)) + (check-true (multiset-contains-none? letters (list))) + (check-false (multiset-contains-none? letters (list 'a 'b))) + (check-false (multiset-contains-none? letters (list 'a 'a 'a 'a 'a))) + (check-false (multiset-contains-none? letters (list 'c 'd 'e 'f))) + (check-true (multiset-contains-none? letters (list 'e 'e 'e))) + (check-false (multiset-contains-none? letters (multiset 'a 'b))) + (check-false (multiset-contains-none? letters (multiset 'a 'a 'a 'a 'a))) + (check-false (multiset-contains-none? letters (multiset 'c 'd 'e 'f))) + (check-true (multiset-contains-none? letters (multiset 'e 'e 'e))))) + + (define (frequency-hash->list frequencies) (for*/list ([(elem freq) (in-hash frequencies)] [_ (in-range freq)]) diff --git a/collection/multiset.scrbl b/collection/multiset.scrbl index 4041ba0..38b3608 100644 --- a/collection/multiset.scrbl +++ b/collection/multiset.scrbl @@ -108,6 +108,26 @@ except it can contain duplicate elements. Elements are always compared with (multiset-contains-all? (multiset 1 1 1 2 3 3) (list 1 1 1 1 1 1 1)))} +@defproc[(multiset-contains-any? [set multiset?] [seq (sequence/c any/c)]) boolean?]{ + Returns @racket[#true] if @racket[set] contains at least one element of @racket[seq], returns + @racket[#false] otherwise. Returns @racket[#false] if @racket[seq] is empty. + + @(examples + #:eval (make-evaluator) #:once + (multiset-contains-any? (multiset 1 2 3) (list 2 4 6)) + (multiset-contains-any? (multiset 1 2 3) (list 10 20 30)))} + + +@defproc[(multiset-contains-none? [set multiset?] [seq (sequence/c any/c)]) boolean?]{ + Returns @racket[#true] if @racket[set] does not contain any element of @racket[seq], returns + @racket[#false] otherwise. Returns @racket[#true] if @racket[seq] is empty. + + @(examples + #:eval (make-evaluator) #:once + (multiset-contains-none? (multiset 1 2 3) (list 2 4 6)) + (multiset-contains-none? (multiset 1 2 3) (list 10 20 30)))} + + @defproc[(multiset-unique-elements [set multiset?]) set?]{ Removes all duplicate elements from @racket[set], returning the resulting set.