diff --git a/.tool-versions b/.tool-versions new file mode 100644 index 00000000..179f2a8c --- /dev/null +++ b/.tool-versions @@ -0,0 +1 @@ +scarb 2.6.5 diff --git a/concepts/operator-overload/.meta/config.json b/concepts/operator-overload/.meta/config.json new file mode 100644 index 00000000..52914445 --- /dev/null +++ b/concepts/operator-overload/.meta/config.json @@ -0,0 +1,7 @@ +{ + "blurb": "", + "authors": [ + "misicnenad" + ], + "contributors": [] +} diff --git a/concepts/operator-overload/about.md b/concepts/operator-overload/about.md new file mode 100644 index 00000000..19c307b1 --- /dev/null +++ b/concepts/operator-overload/about.md @@ -0,0 +1 @@ +# Operator Overload diff --git a/concepts/operator-overload/introduction.md b/concepts/operator-overload/introduction.md new file mode 100644 index 00000000..e10b99d0 --- /dev/null +++ b/concepts/operator-overload/introduction.md @@ -0,0 +1 @@ +# Introduction diff --git a/concepts/operator-overload/links.json b/concepts/operator-overload/links.json new file mode 100644 index 00000000..fe51488c --- /dev/null +++ b/concepts/operator-overload/links.json @@ -0,0 +1 @@ +[] diff --git a/concepts/structs/.meta/config.json b/concepts/structs/.meta/config.json new file mode 100644 index 00000000..52914445 --- /dev/null +++ b/concepts/structs/.meta/config.json @@ -0,0 +1,7 @@ +{ + "blurb": "", + "authors": [ + "misicnenad" + ], + "contributors": [] +} diff --git a/concepts/structs/about.md b/concepts/structs/about.md new file mode 100644 index 00000000..c88ba870 --- /dev/null +++ b/concepts/structs/about.md @@ -0,0 +1 @@ +# Structs diff --git a/concepts/structs/introduction.md b/concepts/structs/introduction.md new file mode 100644 index 00000000..e10b99d0 --- /dev/null +++ b/concepts/structs/introduction.md @@ -0,0 +1 @@ +# Introduction diff --git a/concepts/structs/links.json b/concepts/structs/links.json new file mode 100644 index 00000000..fe51488c --- /dev/null +++ b/concepts/structs/links.json @@ -0,0 +1 @@ +[] diff --git a/config.json b/config.json index 06fdcba9..256b635f 100644 --- a/config.json +++ b/config.json @@ -103,10 +103,28 @@ "slug": "low-power-embedded-game", "name": "low-power-embedded-game", "uuid": "f3b7ce44-1667-42b4-b792-401d36aee2f1", - "practices": ["tuples", "traits", "control-flow"], + "practices": [ + "tuples", + "traits" + ], "prerequisites": [], "difficulty": 2 + }, + { + "slug": "custom-set", + "name": "Custom Set", + "uuid": "aad80498-750c-4a7d-b82a-f52f90c54e11", + "practices": [ + "structs", + "traits", + "operator-overload" + ], + "prerequisites": [], + "difficulty": 4 } + ], + "foregone": [ + "hangman" ] }, "concepts": [ @@ -164,6 +182,16 @@ "uuid": "fe83c9a6-cf50-47b1-9993-21ddd1e895ee", "slug": "traits", "name": "Traits" + }, + { + "uuid": "4e1f6433-3125-4428-837d-47b0c10fddea", + "slug": "structs", + "name": "Structs" + }, + { + "uuid": "0b069f59-f8b4-4979-935a-c3172538f4c9", + "slug": "operator-overload", + "name": "Operator Overload" } ], "key_features": [ diff --git a/exercises/practice/custom-set/.docs/instructions.md b/exercises/practice/custom-set/.docs/instructions.md new file mode 100644 index 00000000..33b90e28 --- /dev/null +++ b/exercises/practice/custom-set/.docs/instructions.md @@ -0,0 +1,7 @@ +# Instructions + +Create a custom set type. + +Sometimes it is necessary to define a custom data structure of some type, like a set. +In this exercise you will define your own set. +How it works internally doesn't matter, as long as it behaves like a set of unique elements. diff --git a/exercises/practice/custom-set/.meta/config.json b/exercises/practice/custom-set/.meta/config.json new file mode 100644 index 00000000..e93f4796 --- /dev/null +++ b/exercises/practice/custom-set/.meta/config.json @@ -0,0 +1,18 @@ +{ + "authors": [ + "misicnenad" + ], + "files": { + "solution": [ + "src/lib.cairo", + "Scarb.toml" + ], + "test": [ + "src/tests.cairo" + ], + "example": [ + ".meta/example.cairo" + ] + }, + "blurb": "Create a custom set type." +} diff --git a/exercises/practice/custom-set/.meta/example.cairo b/exercises/practice/custom-set/.meta/example.cairo new file mode 100644 index 00000000..3c3f5bf7 --- /dev/null +++ b/exercises/practice/custom-set/.meta/example.cairo @@ -0,0 +1,175 @@ +use core::clone::Clone; +use core::array::ArrayTrait; +use core::box::BoxTrait; + +#[derive(Drop, Debug)] +pub struct CustomSet { + pub collection: Array, +} + +pub impl CustomSetEq< + T, +Copy, +Drop, +PartialEq, +core::fmt::Display +> of PartialEq> { + fn eq(lhs: @CustomSet, rhs: @CustomSet) -> bool { + if lhs.collection.len() != rhs.collection.len() { + return false; + } + lhs.is_subset(rhs) && rhs.is_subset(lhs) + } + + fn ne(lhs: @CustomSet, rhs: @CustomSet) -> bool { + !(lhs == rhs) + } +} + +#[generate_trait] +pub impl CustomSetImpl< + T, +Copy, +Drop, +core::fmt::Display, +PartialEq +> of CustomSetTrait { + fn new(inputs: @Array) -> CustomSet { + let mut set = CustomSet:: { collection: array![], }; + let mut i = 0; + while let Option::Some(val) = inputs + .get(i) { + let unboxed = val.unbox(); + set.add(unboxed.clone()); + i += 1; + }; + set + } + + fn add(ref self: CustomSet, element: T) { + if !self.contains(@element) { + self.collection.append(element) + } + } + + fn contains(self: @CustomSet, other: @T) -> bool { + let mut is_contained = false; + let mut i = 0; + while let Option::Some(boxed) = self + .collection + .get(i) { + let val = boxed.unbox(); + if val == other { + is_contained = true; + break; + } + i += 1; + }; + is_contained + } + + fn is_empty(self: @CustomSet) -> bool { + self.collection.is_empty() + } + + fn is_subset(self: @CustomSet, other: @CustomSet) -> bool { + if self.collection.len() > other.collection.len() { + return false; + } + let mut result = true; + let mut i = 0; + while let Option::Some(val) = self + .collection + .get(i) { + if !other.contains(val.unbox()) { + result = false; + break; + } + i += 1; + }; + result + } + + fn is_disjoint(self: @CustomSet, other: @CustomSet) -> bool { + let mut are_disjoint = true; + + // a more efficient way is to iterate the smaller set + let mut to_iterate = self; + let mut to_compare = other; + if to_iterate.collection.len() > to_compare.collection.len() { + to_iterate = other; + to_compare = self; + }; + + let mut i = 0; + while let Option::Some(val) = to_iterate + .collection + .get(i) { + if to_compare.contains(val.unbox()) { + are_disjoint = false; + break; + } + i += 1; + }; + + are_disjoint + } + + #[must_use] + fn intersection(self: @CustomSet, other: @CustomSet) -> CustomSet { + let mut collection: Array = array![]; + + // a more efficient way is to iterate the smaller set + let mut to_iterate = self; + let mut to_compare = other; + if to_iterate.collection.len() > to_compare.collection.len() { + to_iterate = other; + to_compare = self; + }; + + let mut i = 0; + while let Option::Some(val) = to_iterate + .collection + .get(i) { + let unboxed = val.unbox(); + if to_compare.contains(unboxed) { + collection.append(*unboxed); + } + i += 1; + }; + + CustomSetImpl::::new(@collection) + } + + #[must_use] + fn union(self: @CustomSet, other: @CustomSet) -> CustomSet { + let mut collection: Array = array![]; + let mut i = 0; + while let Option::Some(val) = self + .collection + .get(i) { + collection.append(*val.unbox()); + i += 1; + }; + i = 0; + while let Option::Some(val) = other + .collection + .get(i) { + collection.append(*val.unbox()); + i += 1; + }; + CustomSetImpl::::new(@collection) + } + + #[must_use] + fn difference(self: @CustomSet, other: @CustomSet) -> CustomSet { + let mut collection: Array = array![]; + let mut i = 0; + while let Option::Some(val) = self + .collection + .get(i) { + let unboxed = val.unbox(); + if !other.contains(unboxed) { + collection.append(unboxed.clone()); + } + i += 1; + }; + CustomSetImpl::::new(@collection) + } +} + + +#[cfg(test)] +mod tests; diff --git a/exercises/practice/custom-set/.meta/tests.toml b/exercises/practice/custom-set/.meta/tests.toml new file mode 100644 index 00000000..430c139e --- /dev/null +++ b/exercises/practice/custom-set/.meta/tests.toml @@ -0,0 +1,130 @@ +# This is an auto-generated file. +# +# Regenerating this file via `configlet sync` will: +# - Recreate every `description` key/value pair +# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications +# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion) +# - Preserve any other key/value pair +# +# As user-added comments (using the # character) will be removed when this file +# is regenerated, comments can be added via a `comment` key. + +[20c5f855-f83a-44a7-abdd-fe75c6cf022b] +description = "Returns true if the set contains no elements -> sets with no elements are empty" + +[d506485d-5706-40db-b7d8-5ceb5acf88d2] +description = "Returns true if the set contains no elements -> sets with elements are not empty" + +[759b9740-3417-44c3-8ca3-262b3c281043] +description = "Sets can report if they contain an element -> nothing is contained in an empty set" + +[f83cd2d1-2a85-41bc-b6be-80adbff4be49] +description = "Sets can report if they contain an element -> when the element is in the set" + +[93423fc0-44d0-4bc0-a2ac-376de8d7af34] +description = "Sets can report if they contain an element -> when the element is not in the set" + +[c392923a-637b-4495-b28e-34742cd6157a] +description = "A set is a subset if all of its elements are contained in the other set -> empty set is a subset of another empty set" + +[5635b113-be8c-4c6f-b9a9-23c485193917] +description = "A set is a subset if all of its elements are contained in the other set -> empty set is a subset of non-empty set" + +[832eda58-6d6e-44e2-92c2-be8cf0173cee] +description = "A set is a subset if all of its elements are contained in the other set -> non-empty set is not a subset of empty set" + +[c830c578-8f97-4036-b082-89feda876131] +description = "A set is a subset if all of its elements are contained in the other set -> set is a subset of set with exact same elements" + +[476a4a1c-0fd1-430f-aa65-5b70cbc810c5] +description = "A set is a subset if all of its elements are contained in the other set -> set is a subset of larger set with same elements" + +[d2498999-3e46-48e4-9660-1e20c3329d3d] +description = "A set is a subset if all of its elements are contained in the other set -> set is not a subset of set that does not contain its elements" + +[7d38155e-f472-4a7e-9ad8-5c1f8f95e4cc] +description = "Sets are disjoint if they share no elements -> the empty set is disjoint with itself" + +[7a2b3938-64b6-4b32-901a-fe16891998a6] +description = "Sets are disjoint if they share no elements -> empty set is disjoint with non-empty set" + +[589574a0-8b48-48ea-88b0-b652c5fe476f] +description = "Sets are disjoint if they share no elements -> non-empty set is disjoint with empty set" + +[febeaf4f-f180-4499-91fa-59165955a523] +description = "Sets are disjoint if they share no elements -> sets are not disjoint if they share an element" + +[0de20d2f-c952-468a-88c8-5e056740f020] +description = "Sets are disjoint if they share no elements -> sets are disjoint if they share no elements" + +[4bd24adb-45da-4320-9ff6-38c044e9dff8] +description = "Sets with the same elements are equal -> empty sets are equal" + +[f65c0a0e-6632-4b2d-b82c-b7c6da2ec224] +description = "Sets with the same elements are equal -> empty set is not equal to non-empty set" + +[81e53307-7683-4b1e-a30c-7e49155fe3ca] +description = "Sets with the same elements are equal -> non-empty set is not equal to empty set" + +[d57c5d7c-a7f3-48cc-a162-6b488c0fbbd0] +description = "Sets with the same elements are equal -> sets with the same elements are equal" + +[dd61bafc-6653-42cc-961a-ab071ee0ee85] +description = "Sets with the same elements are equal -> sets with different elements are not equal" + +[06059caf-9bf4-425e-aaff-88966cb3ea14] +description = "Sets with the same elements are equal -> set is not equal to larger set with same elements" + +[d4a1142f-09aa-4df9-8b83-4437dcf7ec24] +description = "Sets with the same elements are equal -> set is equal to a set constructed from an array with duplicates" + +[8a677c3c-a658-4d39-bb88-5b5b1a9659f4] +description = "Unique elements can be added to a set -> add to empty set" + +[0903dd45-904d-4cf2-bddd-0905e1a8d125] +description = "Unique elements can be added to a set -> add to non-empty set" + +[b0eb7bb7-5e5d-4733-b582-af771476cb99] +description = "Unique elements can be added to a set -> adding an existing element does not change the set" + +[893d5333-33b8-4151-a3d4-8f273358208a] +description = "Intersection returns a set of all shared elements -> intersection of two empty sets is an empty set" + +[d739940e-def2-41ab-a7bb-aaf60f7d782c] +description = "Intersection returns a set of all shared elements -> intersection of an empty set and non-empty set is an empty set" + +[3607d9d8-c895-4d6f-ac16-a14956e0a4b7] +description = "Intersection returns a set of all shared elements -> intersection of a non-empty set and an empty set is an empty set" + +[b5120abf-5b5e-41ab-aede-4de2ad85c34e] +description = "Intersection returns a set of all shared elements -> intersection of two sets with no shared elements is an empty set" + +[af21ca1b-fac9-499c-81c0-92a591653d49] +description = "Intersection returns a set of all shared elements -> intersection of two sets with shared elements is a set of the shared elements" + +[c5e6e2e4-50e9-4bc2-b89f-c518f015b57e] +description = "Difference (or Complement) of a set is a set of all elements that are only in the first set -> difference of two empty sets is an empty set" + +[2024cc92-5c26-44ed-aafd-e6ca27d6fcd2] +description = "Difference (or Complement) of a set is a set of all elements that are only in the first set -> difference of empty set and non-empty set is an empty set" + +[e79edee7-08aa-4c19-9382-f6820974b43e] +description = "Difference (or Complement) of a set is a set of all elements that are only in the first set -> difference of a non-empty set and an empty set is the non-empty set" + +[c5ac673e-d707-4db5-8d69-7082c3a5437e] +description = "Difference (or Complement) of a set is a set of all elements that are only in the first set -> difference of two non-empty sets is a set of elements that are only in the first set" + +[20d0a38f-7bb7-4c4a-ac15-90c7392ecf2b] +description = "Difference (or Complement) of a set is a set of all elements that are only in the first set -> difference removes all duplicates in the first set" + +[c45aed16-5494-455a-9033-5d4c93589dc6] +description = "Union returns a set of all elements in either set -> union of empty sets is an empty set" + +[9d258545-33c2-4fcb-a340-9f8aa69e7a41] +description = "Union returns a set of all elements in either set -> union of an empty set and non-empty set is the non-empty set" + +[3aade50c-80c7-4db8-853d-75bac5818b83] +description = "Union returns a set of all elements in either set -> union of a non-empty set and empty set is the non-empty set" + +[a00bb91f-c4b4-4844-8f77-c73e2e9df77c] +description = "Union returns a set of all elements in either set -> union of non-empty sets contains all unique elements" diff --git a/exercises/practice/custom-set/Scarb.toml b/exercises/practice/custom-set/Scarb.toml new file mode 100644 index 00000000..f86dddc8 --- /dev/null +++ b/exercises/practice/custom-set/Scarb.toml @@ -0,0 +1,4 @@ +[package] +name = "custom_set" +version = "0.1.0" +edition = "2023_11" diff --git a/exercises/practice/custom-set/src/lib.cairo b/exercises/practice/custom-set/src/lib.cairo new file mode 100644 index 00000000..70907bc7 --- /dev/null +++ b/exercises/practice/custom-set/src/lib.cairo @@ -0,0 +1,61 @@ +#[derive(Drop, Debug)] +pub struct CustomSet {} + +pub impl CustomSetEq< + T, +Copy, +Drop, +PartialEq, +core::fmt::Display +> of PartialEq> { + fn eq(lhs: @CustomSet, rhs: @CustomSet) -> bool { + panic!() + } + + fn ne(lhs: @CustomSet, rhs: @CustomSet) -> bool { + panic!() + } +} + +#[generate_trait] +pub impl CustomSetImpl< + T, +Copy, +Drop, +core::fmt::Display, +PartialEq +> of CustomSetTrait { + fn new(_input: @Array) -> CustomSet { + panic!() + } + + fn contains(self: @CustomSet, element: @T) -> bool { + panic!() + } + + fn add(ref self: CustomSet, element: T) { + panic!(); + } + + fn is_subset(self: @CustomSet, other: @CustomSet) -> bool { + panic!() + } + + fn is_empty(self: @CustomSet) -> bool { + panic!() + } + + fn is_disjoint(self: @CustomSet, other: @CustomSet) -> bool { + panic!() + } + + #[must_use] + fn intersection(self: @CustomSet, other: @CustomSet) -> CustomSet { + panic!() + } + + #[must_use] + fn difference(self: @CustomSet, other: @CustomSet) -> CustomSet { + panic!() + } + + #[must_use] + fn union(self: @CustomSet, other: @CustomSet) -> CustomSet { + panic!() + } +} + +#[cfg(test)] +mod tests; diff --git a/exercises/practice/custom-set/src/tests.cairo b/exercises/practice/custom-set/src/tests.cairo new file mode 100644 index 00000000..2a188796 --- /dev/null +++ b/exercises/practice/custom-set/src/tests.cairo @@ -0,0 +1,297 @@ +use custom_set::{CustomSet, CustomSetImpl}; + +// impl alias +impl U32Set = CustomSetImpl::; + +#[test] +fn sets_with_no_elements_are_empty() { + let set = U32Set::new(@array![]); + assert!(set.is_empty()); +} + +#[test] +fn sets_with_elements_are_not_empty() { + let set = U32Set::new(@array![1]); + assert!(!set.is_empty()); +} + +#[test] +fn nothing_is_contained_in_an_empty_set() { + let set = U32Set::new(@array![]); + assert!(!set.contains(@1)); +} + +#[test] +fn when_the_element_is_in_the_set() { + let set = U32Set::new(@array![1, 2, 3]); + assert!(set.contains(@1)); +} + +#[test] +fn when_the_element_is_not_in_the_set() { + let set = U32Set::new(@array![1, 2, 3]); + assert!(!set.contains(@4)); +} + +#[test] +fn empty_set_is_a_subset_of_another_empty_set() { + let set_1 = U32Set::new(@array![]); + let set_2 = U32Set::new(@array![]); + assert!(set_1.is_subset(@set_2)); +} + +#[test] +fn empty_set_is_a_subset_of_non_empty_set() { + let set_1 = U32Set::new(@array![]); + let set_2 = U32Set::new(@array![1]); + assert!(set_1.is_subset(@set_2)); +} + +#[test] +fn non_empty_set_is_not_a_subset_of_empty_set() { + let set_1 = U32Set::new(@array![1]); + let set_2 = U32Set::new(@array![]); + assert!(!set_1.is_subset(@set_2)); +} + +#[test] +fn set_is_a_subset_of_set_with_exact_same_elements() { + let set_1 = U32Set::new(@array![1, 2, 3]); + let set_2 = U32Set::new(@array![1, 2, 3]); + assert!(set_1.is_subset(@set_2)); +} + +#[test] +fn set_is_a_subset_of_larger_set_with_same_elements() { + let set_1 = U32Set::new(@array![1, 2, 3]); + let set_2 = U32Set::new(@array![4, 1, 2, 3]); + assert!(set_1.is_subset(@set_2)); +} + +#[test] +fn set_is_not_a_subset_of_set_that_does_not_contain_its_elements() { + let set_1 = U32Set::new(@array![1, 2, 3]); + let set_2 = U32Set::new(@array![4, 1, 3]); + assert!(!set_1.is_subset(@set_2)); +} + +#[test] +fn the_empty_set_is_disjoint_with_itself() { + let set_1 = U32Set::new(@array![]); + let set_2 = U32Set::new(@array![]); + assert!(set_1.is_disjoint(@set_2)); +} + +#[test] +fn empty_set_is_disjoint_with_non_empty_set() { + let set_1 = U32Set::new(@array![]); + let set_2 = U32Set::new(@array![1]); + assert!(set_1.is_disjoint(@set_2)); +} + +#[test] +fn non_empty_set_is_disjoint_with_empty_set() { + let set_1 = U32Set::new(@array![1]); + let set_2 = U32Set::new(@array![]); + assert!(set_1.is_disjoint(@set_2)); +} + +#[test] +fn sets_are_not_disjoint_if_they_share_an_element() { + let set_1 = U32Set::new(@array![1, 2]); + let set_2 = U32Set::new(@array![2, 3]); + assert!(!set_1.is_disjoint(@set_2)); +} + +#[test] +fn sets_are_disjoint_if_they_share_no_elements() { + let set_1 = U32Set::new(@array![1, 2]); + let set_2 = U32Set::new(@array![3, 4]); + assert!(set_1.is_disjoint(@set_2)); +} + +#[test] +fn empty_sets_are_equal() { + let set_1 = U32Set::new(@array![]); + let set_2 = U32Set::new(@array![]); + assert_eq!(set_1, set_2); +} + +#[test] +fn empty_set_is_not_equal_to_non_empty_set() { + let set_1 = U32Set::new(@array![]); + let set_2 = U32Set::new(@array![1, 2, 3]); + assert_ne!(set_1, set_2); +} + +#[test] +fn non_empty_set_is_not_equal_to_empty_set() { + let set_1 = U32Set::new(@array![1, 2, 3]); + let set_2 = U32Set::new(@array![]); + assert_ne!(set_1, set_2); +} + +#[test] +fn sets_with_the_same_elements_are_equal() { + let set_1 = U32Set::new(@array![1, 2]); + let set_2 = U32Set::new(@array![2, 1]); + assert_eq!(set_1, set_2); +} + +#[test] +fn sets_with_different_elements_are_not_equal() { + let set_1 = U32Set::new(@array![1, 2, 3]); + let set_2 = U32Set::new(@array![1, 2, 4]); + assert_ne!(set_1, set_2); +} + +#[test] +fn set_is_not_equal_to_larger_set_with_same_elements() { + let set_1 = U32Set::new(@array![1, 2, 3]); + let set_2 = U32Set::new(@array![1, 2, 3, 4]); + assert_ne!(set_1, set_2); +} + +#[test] +fn set_is_equal_to_a_set_constructed_from_an_array_with_duplicates() { + let set_1 = U32Set::new(@array![1]); + let set_2 = U32Set::new(@array![1, 1]); + assert_eq!(set_1, set_2); +} + +#[test] +fn add_to_empty_set() { + let mut set = U32Set::new(@array![]); + set.add(3); + let expected = U32Set::new(@array![3]); + assert_eq!(set, expected); +} + +#[test] +fn add_to_non_empty_set() { + let mut set = U32Set::new(@array![1, 2, 4]); + set.add(3); + let expected = U32Set::new(@array![1, 2, 3, 4]); + assert_eq!(set, expected); +} + +#[test] +fn adding_an_existing_element_does_not_change_the_set() { + let mut set = U32Set::new(@array![1, 2, 3]); + set.add(3); + let expected = U32Set::new(@array![1, 2, 3]); + assert_eq!(set, expected); +} + +#[test] +fn intersection_of_two_empty_sets_is_an_empty_set() { + let set_1 = U32Set::new(@array![]); + let set_2 = U32Set::new(@array![]); + let expected = U32Set::new(@array![]); + assert_eq!(set_1.intersection(@set_2), expected); +} + +#[test] +fn intersection_of_an_empty_set_and_non_empty_set_is_an_empty_set() { + let set_1 = U32Set::new(@array![]); + let set_2 = U32Set::new(@array![3, 2, 5]); + let expected = U32Set::new(@array![]); + assert_eq!(set_1.intersection(@set_2), expected); +} + +#[test] +fn intersection_of_a_non_empty_set_and_an_empty_set_is_an_empty_set() { + let set_1 = U32Set::new(@array![1, 2, 3, 4]); + let set_2 = U32Set::new(@array![]); + let expected = U32Set::new(@array![]); + assert_eq!(set_1.intersection(@set_2), expected); +} + +#[test] +fn intersection_of_two_sets_with_no_shared_elements_is_an_empty_set() { + let set_1 = U32Set::new(@array![1, 2, 3]); + let set_2 = U32Set::new(@array![4, 5, 6]); + let expected = U32Set::new(@array![]); + assert_eq!(set_1.intersection(@set_2), expected); +} + +#[test] +fn intersection_of_two_sets_with_shared_elements_is_a_set_of_the_shared_elements() { + let set_1 = U32Set::new(@array![1, 2, 3, 4]); + let set_2 = U32Set::new(@array![3, 2, 5]); + let expected = U32Set::new(@array![2, 3]); + assert_eq!(set_1.intersection(@set_2), expected); +} + +#[test] +fn difference_of_two_empty_sets_is_an_empty_set() { + let set_1 = U32Set::new(@array![]); + let set_2 = U32Set::new(@array![]); + let expected = U32Set::new(@array![]); + assert_eq!(set_1.difference(@set_2), expected); +} + +#[test] +fn difference_of_empty_set_and_non_empty_set_is_an_empty_set() { + let set_1 = U32Set::new(@array![]); + let set_2 = U32Set::new(@array![3, 2, 5]); + let expected = U32Set::new(@array![]); + assert_eq!(set_1.difference(@set_2), expected); +} + +#[test] +fn difference_of_a_non_empty_set_and_an_empty_set_is_the_non_empty_set() { + let set_1 = U32Set::new(@array![1, 2, 3, 4]); + let set_2 = U32Set::new(@array![]); + let expected = U32Set::new(@array![1, 2, 3, 4]); + assert_eq!(set_1.difference(@set_2), expected); +} + +#[test] +fn difference_of_two_non_empty_sets_is_a_set_of_elements_that_are_only_in_the_first_set() { + let set_1 = U32Set::new(@array![3, 2, 1]); + let set_2 = U32Set::new(@array![2, 4]); + let expected = U32Set::new(@array![1, 3]); + assert_eq!(set_1.difference(@set_2), expected); +} + +#[test] +fn difference_removes_all_duplicates_in_the_first_set() { + let set_1 = U32Set::new(@array![1, 1]); + let set_2 = U32Set::new(@array![1]); + let expected = U32Set::new(@array![]); + assert_eq!(set_1.difference(@set_2), expected); +} + +#[test] +fn union_of_empty_sets_is_an_empty_set() { + let set_1 = U32Set::new(@array![]); + let set_2 = U32Set::new(@array![]); + let expected = U32Set::new(@array![]); + assert_eq!(set_1.union(@set_2), expected); +} + +#[test] +fn union_of_an_empty_set_and_non_empty_set_is_the_non_empty_set() { + let set_1 = U32Set::new(@array![]); + let set_2 = U32Set::new(@array![2]); + let expected = U32Set::new(@array![2]); + assert_eq!(set_1.union(@set_2), expected); +} + +#[test] +fn union_of_a_non_empty_set_and_empty_set_is_the_non_empty_set() { + let set_1 = U32Set::new(@array![1, 3]); + let set_2 = U32Set::new(@array![]); + let expected = U32Set::new(@array![1, 3]); + assert_eq!(set_1.union(@set_2), expected); +} + +#[test] +fn union_of_non_empty_sets_contains_all_unique_elements() { + let set_1 = U32Set::new(@array![1, 3]); + let set_2 = U32Set::new(@array![2, 3]); + let expected = U32Set::new(@array![3, 2, 1]); + assert_eq!(set_1.union(@set_2), expected); +} +