Skip to content

Commit

Permalink
Merge pull request #544 from jackfirth/multiset-batch-contains
Browse files Browse the repository at this point in the history
Add more batch multiset queries
  • Loading branch information
jackfirth authored Apr 21, 2024
2 parents d883149 + b02d319 commit fc4924c
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 0 deletions.
41 changes: 41 additions & 0 deletions collection/multiset.rkt
Original file line number Diff line number Diff line change
Expand Up @@ -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?)]
Expand Down Expand Up @@ -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)))
Expand All @@ -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)])
Expand Down
20 changes: 20 additions & 0 deletions collection/multiset.scrbl
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down

0 comments on commit fc4924c

Please sign in to comment.