/// <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; } int copiesInThis, copiesInOther, copies; // 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()) { copiesInThis = this.NumberOfCopies(item); copiesInOther = otherBag.NumberOfCopies(item); copies = copiesInThis - copiesInOther; if (copies < 0) { copies = 0; } ChangeNumberOfCopies(item, copies); } }
/// <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; } int copiesInThis, copiesInOther, copies; // Enumerate each of the items in the other bag. Add items that need to be // added to this bag. foreach (T item in otherBag.DistinctItems()) { copiesInThis = this.NumberOfCopies(item); copiesInOther = otherBag.NumberOfCopies(item); copies = System.Math.Abs(copiesInThis - copiesInOther); if (copies != copiesInThis) { ChangeNumberOfCopies(item, copies); } } }
/// <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 > this.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. foreach (T item in otherBag.DistinctItems()) { if (this.NumberOfCopies(item) < otherBag.NumberOfCopies(item)) { return(false); } } return(true); }
/// <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 != this.Count) { return(false); } // Check each item to make sure it is in this set the same number of times. foreach (T item in otherBag.DistinctItems()) { if (this.NumberOfCopies(item) != otherBag.NumberOfCopies(item)) { return(false); } } return(true); }
/// <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; } int copiesInThis, copiesInOther; // Enumerate each of the items in the other bag. Add items that need to be // added to this bag. foreach (T item in otherBag.DistinctItems()) { copiesInThis = this.NumberOfCopies(item); copiesInOther = otherBag.NumberOfCopies(item); ChangeNumberOfCopies(item, copiesInThis + copiesInOther); } }
/// <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 } int copiesInThis, copiesInOther; // Enumerate each of the items in the other bag. Add items that need to be // added to this bag. foreach (T item in otherBag.DistinctItems()) { copiesInThis = this.NumberOfCopies(item); copiesInOther = otherBag.NumberOfCopies(item); if (copiesInOther > copiesInThis) { ChangeNumberOfCopies(item, copiesInOther); } } }