Example #1
0
        /// <summary>
        /// Computes the difference of this bag with another bag. The difference of these two bags
        /// is all items that appear in this bag, but not in <paramref name="otherBag"/>. If an item appears X times in this bag,
        /// and Y times in the other bag, the difference contains the item X - Y times (zero times if Y >= X). This bag receives
        /// the difference of the two bags; the other bag is unchanged.
        /// </summary>
        /// <remarks>
        /// <para>The difference of two bags is computed in time O(M), where M is the size of the
        /// other bag.</para>
        /// </remarks>
        /// <param name="otherBag">Bag to difference with.</param>
        /// <exception cref="InvalidOperationException">This bag and <paramref name="otherBag"/> don't use the same method for comparing items.</exception>
        public void DifferenceWith(Bag <T> otherBag)
        {
            CheckConsistentComparison(otherBag);

            if (this == otherBag)
            {
                Clear();
                return;
            }

            // Enumerate each of the items in the other bag. Remove items that need to be
            // removed from this bag.
            foreach (T item in otherBag.DistinctItems())
            {
                var copiesInThis  = NumberOfCopies(item);
                var copiesInOther = otherBag.NumberOfCopies(item);
                var copies        = copiesInThis - copiesInOther;

                if (copies < 0)
                {
                    copies = 0;
                }

                ChangeNumberOfCopies(item, copies);
            }
        }
Example #2
0
        /// <summary>
        /// Determines if this bag is a superset of another bag. Neither bag is modified.
        /// This bag is a superset of <paramref name="otherBag"/> if every element in
        /// <paramref name="otherBag"/> is also in this bag, at least the same number of
        /// times.
        /// </summary>
        /// <remarks>IsSupersetOf is computed in time O(M), where M is the number of unique items in
        /// <paramref name="otherBag"/>.</remarks>
        /// <param name="otherBag">Bag to compare to.</param>
        /// <returns>True if this is a superset of <paramref name="otherBag"/>.</returns>
        /// <exception cref="InvalidOperationException">This bag and <paramref name="otherBag"/> don't use the same method for comparing items.</exception>
        public bool IsSupersetOf(Bag <T> otherBag)
        {
            CheckConsistentComparison(otherBag);

            if (otherBag.Count > Count)
            {
                return(false); // Can't be a superset of a bigger set
            }
            // Check each item in the other set to make sure it is in this set.
            return(otherBag.DistinctItems().All(item => NumberOfCopies(item) >= otherBag.NumberOfCopies(item)));
        }
Example #3
0
        /// <summary>
        /// Determines if this bag is equal to another bag. This bag is equal to
        /// <paramref name="otherBag"/> if they contain the same number of
        /// of copies of equal elements.
        /// </summary>
        /// <remarks>IsSupersetOf is computed in time O(N), where N is the number of unique items in
        /// this bag.</remarks>
        /// <param name="otherBag">Bag to compare to</param>
        /// <returns>True if this bag is equal to <paramref name="otherBag"/>, false otherwise.</returns>
        /// <exception cref="InvalidOperationException">This bag and <paramref name="otherBag"/> don't use the same method for comparing items.</exception>
        public bool IsEqualTo(Bag <T> otherBag)
        {
            CheckConsistentComparison(otherBag);

            // Must be the same size.
            if (otherBag.Count != Count)
            {
                return(false);
            }

            // Check each item to make sure it is in this set the same number of times.
            return(otherBag.DistinctItems().All(item => NumberOfCopies(item) == otherBag.NumberOfCopies(item)));
        }
Example #4
0
        public void CloneContents()
        {
            var bag1 = new Bag <MyInt>();

            MyInt mi = new MyInt(9);

            bag1.Add(new MyInt(14));
            bag1.Add(new MyInt(143));
            bag1.Add(new MyInt(2));
            bag1.Add(mi);
            bag1.Add(null);
            bag1.Add(new MyInt(14));
            bag1.Add(new MyInt(111));
            bag1.Add(mi);
            Bag <MyInt> bag2 = bag1.CloneContents();

            CompareClones(bag1, bag2);

            var bag3 = new Bag <int>(new int[] { 144, 1, 5, 23, 1, 8 });
            var bag4 = bag3.CloneContents();

            CompareClones(bag3, bag4);

            var bag5 = new Bag <UtilFixture.CloneableStruct>
            {
                new UtilFixture.CloneableStruct(143),
                new UtilFixture.CloneableStruct(1),
                new UtilFixture.CloneableStruct(23),
                new UtilFixture.CloneableStruct(1),
                new UtilFixture.CloneableStruct(8)
            };
            var bag6 = bag5.CloneContents();

            Assert.AreEqual(bag5.Count, bag6.Count);

            // Check that the bags are equal, but not identical (e.g., have been cloned via ICloneable).
            foreach (var item in bag5)
            {
                var found = 0;
                foreach (var other in bag6)
                {
                    if (Equals(item, other))
                    {
                        found += 1;
                        // Assert.IsFalse(item.Identical(other));
                    }
                }
                Assert.AreEqual(bag5.NumberOfCopies(item), found);
            }
        }
Example #5
0
        public void RandomAddDelete()
        {
            const int SIZE  = 5000;
            var       count = new int[SIZE];
            var       rand  = new Random(3);
            var       bag1  = new Bag <int>();
            bool      b;

            // Add and delete values at random.
            for (int i = 0; i < SIZE * 100; ++i)
            {
                int v = rand.Next(SIZE);

                Assert.AreEqual(count[v], bag1.NumberOfCopies(v));
                if (count[v] > 0)
                {
                    Assert.IsTrue(bag1.Contains(v));
                }

                if (count[v] == 0 || rand.Next(2) == 1)
                {
                    // Add to the bag.
                    bag1.Add(v);
                    count[v] += 1;
                }
                else
                {
                    // Remove from the bag.
                    b = bag1.Remove(v);
                    Assert.IsTrue(b);
                    count[v] -= 1;
                }
            }

            // Make sure the bag has all the correct values, not necessarily in order.
            int c = count.Sum();

            Assert.AreEqual(c, bag1.Count);

            foreach (var v in bag1)
            {
                --count[v];
            }

            foreach (var x in count)
            {
                Assert.AreEqual(0, x);
            }
        }
Example #6
0
        private void CompareClones <T>(Bag <T> s1, Bag <T> s2)
        {
            Assert.AreEqual(s1.Count, s2.Count);

            // Check that the sets are equal, but not reference equals (e.g., have been cloned).
            foreach (T item in s1)
            {
                var found = 0;

                foreach (T other in s2)
                {
                    if (Equals(item, other))
                    {
                        found += 1;
                        //if(item != null)
                        //    Assert.IsFalse(ReferenceEquals(item, other));
                    }
                }
                Assert.AreEqual(s1.NumberOfCopies(item), found);
            }
        }
Example #7
0
        /// <summary>
        /// Computes the sum of this bag with another bag. The sum of two bags
        /// is all items from both of the bags. If an item appears X times in one bag,
        /// and Y times in the other bag, the sum contains the item (X+Y) times. This bag receives
        /// the sum of the two bags, the other bag is unchanged.
        /// </summary>
        /// <remarks>
        /// <para>The sum of two bags is computed in time O(M), where M is the size of the
        /// other bag..</para>
        /// </remarks>
        /// <param name="otherBag">Bag to sum with.</param>
        /// <exception cref="InvalidOperationException">This bag and <paramref name="otherBag"/> don't use the same method for comparing items.</exception>
        public void SumWith(Bag <T> otherBag)
        {
            CheckConsistentComparison(otherBag);

            if (this == otherBag)
            {
                // Not very efficient, but an uncommon case.
                AddMany(otherBag);
                return;
            }

            // Enumerate each of the items in the other bag. Add items that need to be
            // added to this bag.
            foreach (var item in otherBag.DistinctItems())
            {
                var copiesInThis  = NumberOfCopies(item);
                var copiesInOther = otherBag.NumberOfCopies(item);

                ChangeNumberOfCopies(item, copiesInThis + copiesInOther);
            }
        }
Example #8
0
        /// <summary>
        /// Computes the union of this bag with another bag. The union of two bags
        /// is all items from both of the bags. If an item appears X times in one bag,
        /// and Y times in the other bag, the union contains the item Maximum(X,Y) times. This bag receives
        /// the union of the two bags, the other bag is unchanged.
        /// </summary>
        /// <remarks>
        /// <para>The union of two bags is computed in time O(M+N), where M and N are the size of the
        /// two bags.</para>
        /// </remarks>
        /// <param name="otherBag">Bag to union with.</param>
        /// <exception cref="InvalidOperationException">This bag and <paramref name="otherBag"/> don't use the same method for comparing items.</exception>
        public void UnionWith(Bag <T> otherBag)
        {
            CheckConsistentComparison(otherBag);

            if (otherBag == this)
            {
                return; // Nothing to do
            }
            // Enumerate each of the items in the other bag. Add items that need to be
            // added to this bag.
            foreach (var item in otherBag.DistinctItems())
            {
                int copiesInThis  = NumberOfCopies(item);
                int copiesInOther = otherBag.NumberOfCopies(item);

                if (copiesInOther > copiesInThis)
                {
                    ChangeNumberOfCopies(item, copiesInOther);
                }
            }
        }
Example #9
0
        /// <summary>
        /// Computes the symmetric difference of this bag with another bag. The symmetric difference of two bags
        /// is all items that appear in either of the bags, but not both. If an item appears X times in one bag,
        /// and Y times in the other bag, the symmetric difference contains the item AbsoluteValue(X - Y) times. This bag receives
        /// the symmetric difference of the two bags; the other bag is unchanged.
        /// </summary>
        /// <remarks>
        /// <para>The symmetric difference of two bags is computed in time O(M + N), where M is the size of the
        /// larger bag, and N is the size of the smaller bag.</para>
        /// </remarks>
        /// <param name="otherBag">Bag to symmetric difference with.</param>
        /// <exception cref="InvalidOperationException">This bag and <paramref name="otherBag"/> don't use the same method for comparing items.</exception>
        public void SymmetricDifferenceWith(Bag <T> otherBag)
        {
            CheckConsistentComparison(otherBag);

            if (this == otherBag)
            {
                Clear();
                return;
            }

            // Enumerate each of the items in the other bag. Add items that need to be
            // added to this bag.
            foreach (var item in otherBag.DistinctItems())
            {
                var copiesInThis  = NumberOfCopies(item);
                var copiesInOther = otherBag.NumberOfCopies(item);
                var copies        = Math.Abs(copiesInThis - copiesInOther);

                if (copies != copiesInThis)
                {
                    ChangeNumberOfCopies(item, copies);
                }
            }
        }
Example #10
0
        public void NumberOfCopies()
        {
            var bag1 = new Bag <string>(StringComparer.InvariantCultureIgnoreCase)
            {
                null, "hello", "foo"
            };

            Assert.AreEqual(1, bag1.NumberOfCopies("hello"));
            Assert.AreEqual(1, bag1.NumberOfCopies("FOO"));
            Assert.AreEqual(1, bag1.NumberOfCopies(null));
            bag1.Add(null);
            bag1.Add("HELLO");
            bag1.Add("Hello");
            Assert.AreEqual(3, bag1.NumberOfCopies("hello"));
            Assert.AreEqual(2, bag1.NumberOfCopies(null));
            bag1.Remove(null);
            bag1.Remove(null);
            Assert.AreEqual(0, bag1.NumberOfCopies(null));
        }