Last active
August 24, 2016 11:52
-
-
Save ToniRib/7d2bd0b93646592f067c94f512dfe0c8 to your computer and use it in GitHub Desktop.
Set implementation using Ruby, based on the Array class (repo: https://github.com/ToniRib/ruby_set_with_arrays)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| class SimpleSet | |
| attr_reader :elements | |
| def initialize(elements = []) | |
| @elements = elements.uniq | |
| end | |
| def contains?(element) | |
| elements.include?(element) | |
| end | |
| def empty? | |
| elements.empty? | |
| end | |
| def size | |
| elements.size | |
| end | |
| def insert(element) | |
| @elements << element unless element_should_not_be_added(element) | |
| end | |
| def insert_multiple(new_elements) | |
| @elements.concat(new_elements.uniq.compact).uniq! | |
| end | |
| def ==(other) | |
| check_argument(other) | |
| equal_size(other) && sorted_elements_match(other) | |
| end | |
| def subset?(other) | |
| check_argument(other) | |
| same_size_or_smaller(other) && contains_all_elements(other) | |
| end | |
| def union(other) | |
| check_argument(other) | |
| new((elements + other.elements).uniq) | |
| end | |
| def intersection(other) | |
| check_argument(other) | |
| new(elements & other.elements) | |
| end | |
| def difference(other) | |
| check_argument(other) | |
| new(elements - other.elements) | |
| end | |
| private | |
| def check_argument(other) | |
| raise_non_set_argument_error unless argument_is_a_simple_set(other) | |
| end | |
| def raise_non_set_argument_error | |
| raise ArgumentError, "Argument must be a SimpleSet" | |
| end | |
| def argument_is_a_simple_set(other) | |
| other.class == self.class | |
| end | |
| def equal_size(set) | |
| size == set.size | |
| end | |
| def sorted_elements_match(set) | |
| elements.sort == set.elements.sort | |
| end | |
| def same_size_or_smaller(set) | |
| size <= set.size | |
| end | |
| def element_should_not_be_added(element) | |
| element.nil? || contains?(element) | |
| end | |
| def contains_all_elements(set) | |
| elements.all? { |element| set.contains?(element) } | |
| end | |
| def new(elements) | |
| self.class.new(elements) | |
| end | |
| end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| require "simple_set" | |
| require "pry" | |
| RSpec.describe SimpleSet do | |
| describe ".new" do | |
| let(:non_repeated_elements) { [1, 2] } | |
| let(:repeated_elements) { [1, 1] } | |
| it "initializes with no elements if none are passed in" do | |
| empty_set = SimpleSet.new | |
| expect(empty_set.elements).to eq Array.new | |
| end | |
| it "can be initialized with an array of non-repeated elements" do | |
| set = SimpleSet.new(non_repeated_elements) | |
| expect(set.elements).to include *non_repeated_elements | |
| end | |
| it "removes repeated elements when initialized" do | |
| set = SimpleSet.new(repeated_elements) | |
| expect(set.elements).to eq [1] | |
| end | |
| end | |
| describe "#contains?" do | |
| let(:element) { 2 } | |
| it "returns false when queried on an empty set" do | |
| empty_set = SimpleSet.new | |
| response = empty_set.contains?(element) | |
| expect(response).to be false | |
| end | |
| it "returns false if the element is not in the set" do | |
| single_element_set = SimpleSet.new([5]) | |
| response = single_element_set.contains?(element) | |
| expect(response).to be false | |
| end | |
| it "returns true if the element is in the set" do | |
| single_element_set = SimpleSet.new([element]) | |
| response = single_element_set.contains?(element) | |
| expect(response).to be true | |
| end | |
| end | |
| describe "#insert" do | |
| context "when the set is empty" do | |
| let(:empty_set) { SimpleSet.new } | |
| it "remains empty when nil is added" do | |
| empty_set.insert(nil) | |
| expect(empty_set.elements).to eq Array.new | |
| end | |
| it "adds the new element" do | |
| empty_set.insert(1) | |
| expect(empty_set.elements).to eq [1] | |
| end | |
| end | |
| context "when the set does not contain the added element" do | |
| let(:set) { SimpleSet.new([1]) } | |
| it "adds the new element" do | |
| set.insert(2) | |
| expect(set.elements).to match_array [1, 2] | |
| end | |
| end | |
| context "when the set contains the added element" do | |
| let(:set) { SimpleSet.new([1]) } | |
| it "does not add the new element" do | |
| set.insert(1) | |
| expect(set.elements).to eq [1] | |
| end | |
| end | |
| end | |
| describe "#empty?" do | |
| it "returns true if the set has no elements" do | |
| empty_set = SimpleSet.new | |
| expect(empty_set.empty?).to be true | |
| end | |
| it "returns false if the set has one or more elements" do | |
| set = SimpleSet.new([1]) | |
| expect(set.empty?).to be false | |
| end | |
| end | |
| describe "#size" do | |
| it "returns 0 if the set is empty" do | |
| empty_set = SimpleSet.new | |
| expect(empty_set.size).to eq 0 | |
| end | |
| it "returns the total number of elements" do | |
| set = SimpleSet.new([1]) | |
| expect(set.size).to eq 1 | |
| end | |
| end | |
| describe "#insert_multiple" do | |
| context "when the set is empty" do | |
| let(:empty_set) { SimpleSet.new } | |
| it "ignores nil elements" do | |
| empty_set.insert_multiple([nil, 1]) | |
| expect(empty_set.elements).to eq [1] | |
| end | |
| it "adds the new elements" do | |
| new_elements = [1, 2] | |
| empty_set.insert_multiple(new_elements) | |
| expect(empty_set.elements).to match_array new_elements | |
| end | |
| it "ignores duplicate new elements" do | |
| new_elements = [1, 1] | |
| empty_set.insert_multiple(new_elements) | |
| expect(empty_set.elements).to eq [1] | |
| end | |
| end | |
| context "when the set does not contain the added elements" do | |
| let(:set) { SimpleSet.new([1]) } | |
| it "adds the new elements" do | |
| new_elements = [2, 3] | |
| set.insert_multiple([2, 3]) | |
| expect(set.elements).to match_array [1, 2, 3] | |
| end | |
| end | |
| context "when the set contains the added elements" do | |
| let(:set) { SimpleSet.new([1]) } | |
| it "only adds the elements not already in the set" do | |
| set.insert_multiple([1, 2]) | |
| expect(set.elements).to match_array [1, 2] | |
| end | |
| end | |
| end | |
| describe "#==" do | |
| it "returns true if the two sets are both empty" do | |
| empty_set = SimpleSet.new | |
| another_empty_set = SimpleSet.new | |
| equality = empty_set == another_empty_set | |
| expect(equality).to be true | |
| end | |
| it "returns false if the sets are of different sizes" do | |
| empty_set = SimpleSet.new | |
| single_element_set = SimpleSet.new([1]) | |
| equality = empty_set == single_element_set | |
| expect(equality).to be false | |
| end | |
| it "returns false if the sets contain different elements" do | |
| set_with_element_one = SimpleSet.new([1]) | |
| set_with_element_two = SimpleSet.new([2]) | |
| equality = set_with_element_one == set_with_element_two | |
| expect(equality).to be false | |
| end | |
| it "returns true if the sets contain the same elements in the same order" do | |
| set_one = SimpleSet.new([1, 2]) | |
| set_two = SimpleSet.new([1, 2]) | |
| equality = set_one == set_two | |
| expect(equality).to be true | |
| end | |
| it "returns true if the sets contain the same elements in a different order" do | |
| set_one = SimpleSet.new([1, 2]) | |
| set_two = SimpleSet.new([2, 1]) | |
| equality = set_one == set_two | |
| expect(equality).to be true | |
| end | |
| it "raises an ArgumentError if the argument is not a SimpleSet" do | |
| set = SimpleSet.new | |
| array = [1] | |
| expect { set == array } | |
| .to raise_error(ArgumentError, "Argument must be a SimpleSet") | |
| end | |
| end | |
| describe "#subset?" do | |
| it "returns true if both sets are empty" do | |
| empty_set = SimpleSet.new | |
| another_empty_set = SimpleSet.new | |
| expect(empty_set.subset?(another_empty_set)).to be true | |
| end | |
| it "returns true if an empty set is passed to a set with elements" do | |
| set = SimpleSet.new([1]) | |
| empty_set = SimpleSet.new | |
| expect(empty_set.subset?(set)).to be true | |
| end | |
| it "returns false if a set with elements is passed to an empty set" do | |
| set = SimpleSet.new([1]) | |
| empty_set = SimpleSet.new | |
| expect(set.subset?(empty_set)).to be false | |
| end | |
| it "returns false if the set contains different elements" do | |
| set = SimpleSet.new([1]) | |
| other_set = SimpleSet.new([2, 3]) | |
| expect(set.subset?(other_set)).to be false | |
| end | |
| it "returns true if the set contains all of the elements" do | |
| subset = SimpleSet.new([2, 1]) | |
| set = SimpleSet.new([1, 2, 3]) | |
| expect(subset.subset?(set)).to be true | |
| end | |
| it "raises an ArgumentError if the argument is not a SimpleSet" do | |
| set = SimpleSet.new | |
| array = [1] | |
| expect { set.subset?(array) } | |
| .to raise_error(ArgumentError, "Argument must be a SimpleSet") | |
| end | |
| end | |
| describe "#union" do | |
| it "returns a new set" do | |
| set = SimpleSet.new([1]) | |
| other_set = SimpleSet.new([2]) | |
| new_set = set.union(other_set) | |
| expect(new_set).to be_a SimpleSet | |
| expect(new_set).to_not be set | |
| expect(new_set).to_not be other_set | |
| end | |
| it "does not modify the original set" do | |
| set = SimpleSet.new([1]) | |
| other_set = SimpleSet.new([2]) | |
| set.union(other_set) | |
| expect(set.elements).to match_array [1] | |
| end | |
| it "does not modify the passed in set" do | |
| set = SimpleSet.new([1]) | |
| other_set = SimpleSet.new([2]) | |
| set.union(other_set) | |
| expect(other_set.elements).to match_array [2] | |
| end | |
| it "returns an empty set if both sets are empty" do | |
| first_empty_set = SimpleSet.new | |
| second_empty_set = SimpleSet.new | |
| new_set = first_empty_set.union(second_empty_set) | |
| expect(new_set).to be_empty | |
| end | |
| it "returns a new set with non-duplicate elements from both sets" do | |
| set = SimpleSet.new([1, 2]) | |
| other_set = SimpleSet.new([2, 3]) | |
| new_set = set.union(other_set) | |
| expect(new_set.elements).to match_array [1, 2, 3] | |
| end | |
| it "raises an ArgumentError if the argument is not a SimpleSet" do | |
| set = SimpleSet.new | |
| array = [1] | |
| expect { set.union(array) } | |
| .to raise_error(ArgumentError, "Argument must be a SimpleSet") | |
| end | |
| end | |
| describe "#intersection" do | |
| it "returns a new set" do | |
| set = SimpleSet.new([1]) | |
| other_set = SimpleSet.new([2]) | |
| new_set = set.intersection(other_set) | |
| expect(new_set).to be_a SimpleSet | |
| expect(new_set).to_not be set | |
| expect(new_set).to_not be other_set | |
| end | |
| it "does not modify the original set" do | |
| set = SimpleSet.new([1]) | |
| other_set = SimpleSet.new([2]) | |
| set.intersection(other_set) | |
| expect(set.elements).to match_array [1] | |
| end | |
| it "does not modify the passed in set" do | |
| set = SimpleSet.new([1]) | |
| other_set = SimpleSet.new([2]) | |
| set.intersection(other_set) | |
| expect(other_set.elements).to match_array [2] | |
| end | |
| it "returns an empty set if both sets are empty" do | |
| first_empty_set = SimpleSet.new | |
| second_empty_set = SimpleSet.new | |
| new_set = first_empty_set.intersection(second_empty_set) | |
| expect(new_set).to be_empty | |
| end | |
| it "returns a new set with only elements that are in both sets" do | |
| set = SimpleSet.new([1, 2]) | |
| other_set = SimpleSet.new([2, 3]) | |
| new_set = set.intersection(other_set) | |
| expect(new_set.elements).to match_array [2] | |
| end | |
| it "returns an empty set if no elements are in both sets" do | |
| set = SimpleSet.new([1, 2]) | |
| other_set = SimpleSet.new([3, 4]) | |
| new_set = set.intersection(other_set) | |
| expect(new_set).to be_empty | |
| end | |
| it "raises an ArgumentError if the argument is not a SimpleSet" do | |
| set = SimpleSet.new | |
| array = [1] | |
| expect { set.intersection(array) } | |
| .to raise_error(ArgumentError, "Argument must be a SimpleSet") | |
| end | |
| end | |
| describe "#difference" do | |
| it "returns a new set" do | |
| set = SimpleSet.new([1]) | |
| other_set = SimpleSet.new([2]) | |
| new_set = set.difference(other_set) | |
| expect(new_set).to be_a SimpleSet | |
| expect(new_set).to_not be set | |
| expect(new_set).to_not be other_set | |
| end | |
| it "does not modify the original set" do | |
| set = SimpleSet.new([1]) | |
| other_set = SimpleSet.new([2]) | |
| set.difference(other_set) | |
| expect(set.elements).to match_array [1] | |
| end | |
| it "does not modify the passed in set" do | |
| set = SimpleSet.new([1]) | |
| other_set = SimpleSet.new([2]) | |
| set.difference(other_set) | |
| expect(other_set.elements).to match_array [2] | |
| end | |
| it "returns an empty set if both sets are empty" do | |
| first_empty_set = SimpleSet.new | |
| second_empty_set = SimpleSet.new | |
| new_set = first_empty_set.difference(second_empty_set) | |
| expect(new_set).to be_empty | |
| end | |
| it "returns a new set with only unique elements from the original set" do | |
| set = SimpleSet.new([1, 2]) | |
| other_set = SimpleSet.new([2, 3]) | |
| new_set = set.difference(other_set) | |
| expect(new_set.elements).to match_array [1] | |
| end | |
| it "returns an empty set called on an empty set" do | |
| empty_set = SimpleSet.new | |
| other_set = SimpleSet.new([3, 4]) | |
| new_set = empty_set.difference(other_set) | |
| expect(new_set).to be_empty | |
| end | |
| it "returns a set with the same elements if called with an empty set" do | |
| empty_set = SimpleSet.new | |
| other_set = SimpleSet.new([3, 4]) | |
| new_set = other_set.difference(empty_set) | |
| expect(new_set.elements).to match_array other_set.elements | |
| end | |
| it "raises an ArgumentError if the argument is not a SimpleSet" do | |
| set = SimpleSet.new | |
| array = [1] | |
| expect { set.difference(array) } | |
| .to raise_error(ArgumentError, "Argument must be a SimpleSet") | |
| end | |
| end | |
| end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| RSpec.configure do |config| | |
| config.expect_with :rspec do |expectations| | |
| expectations.include_chain_clauses_in_custom_matcher_descriptions = true | |
| end | |
| config.mock_with :rspec do |mocks| | |
| mocks.verify_partial_doubles = true | |
| end | |
| end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment