diff options
-rw-r--r-- | CHANGELOG.md | 3 | ||||
-rw-r--r-- | src/gleam/set.gleam | 41 | ||||
-rw-r--r-- | test/gleam/set_test.gleam | 12 |
3 files changed, 55 insertions, 1 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index b06925a..c53ab7b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,8 @@ `from_list`, `fold`, `run`, `to_list`, `take`, `drop`, `map`, `filter`, `cycle`, and `range` functions. - Created the `set` module with the `new`, `insert`, `delete`, `to_list`, - `from_list`, `fold`, `take`, and `contains` functions. + `from_list`, `fold`, `take`, `union`, `intersection`, and `contains` + functions. - Created the `io` module with the `print`, `println`, and `debug` functions. - Created the `queue` module with the `new`, `from_list`, `to_list`, `is_empty`, `length`, `push_back`, `push_front`, `pop_back`, `pop_front`, diff --git a/src/gleam/set.gleam b/src/gleam/set.gleam index ea0d5c6..a023bae 100644 --- a/src/gleam/set.gleam +++ b/src/gleam/set.gleam @@ -169,3 +169,44 @@ pub fn take( ) -> Set(member) { Set(map.take(from: set.map, keeping: desired)) } + +fn order( + first: Set(member), + second: Set(member), +) -> tuple(Set(member), Set(member)) { + case map.size(first.map) > map.size(second.map) { + True -> tuple(first, second) + False -> tuple(second, first) + } +} + +/// Create a new set that contains all members of both given sets. +/// +/// This function runs in loglinear time. +/// +/// ## Examples +/// +/// > union(from_list([1, 2]), from_list([2, 3])) |> to_list +/// [1, 2, 3] +/// +pub fn union(of first: Set(member), and second: Set(member)) -> Set(member) { + let tuple(larger, smaller) = order(first, second) + fold(over: smaller, from: larger, with: fn(m, a) { insert(a, m) }) +} + +/// Create a new set that contains members that are present in both given sets. +/// +/// This function runs in loglinear time. +/// +/// ## Examples +/// +/// > intersection(from_list([1, 2]), from_list([2, 3])) |> to_list +/// [2] +/// +pub fn intersection( + of first: Set(member), + and second: Set(member), +) -> Set(member) { + let tuple(larger, smaller) = order(first, second) + take(from: larger, keeping: to_list(smaller)) +} diff --git a/test/gleam/set_test.gleam b/test/gleam/set_test.gleam index efbdcfc..871c0b6 100644 --- a/test/gleam/set_test.gleam +++ b/test/gleam/set_test.gleam @@ -79,3 +79,15 @@ pub fn take_test() { |> set.take([1, 3, 5]) |> should.equal(set.from_list([1, 3])) } + +pub fn union_test() { + set.union(set.from_list([1, 2]), set.from_list([2, 3])) + |> set.to_list + |> should.equal([1, 2, 3]) +} + +pub fn intersection_test() { + set.intersection(set.from_list([1, 2]), set.from_list([2, 3])) + |> set.to_list + |> should.equal([2]) +} |