aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md3
-rw-r--r--src/gleam/set.gleam41
-rw-r--r--test/gleam/set_test.gleam12
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])
+}