## Lab 7 (Ruby)

### Part 1

#### Problem 1 (4 points)

Write a Ruby method that, given an array, returns another array that consists of all odd-numbered elements of the first array. For instance, given an array [1, 5, 'yes', 'no', 2.7], it returns [1, 'yes', 2.7].

#### Problem 2 (2 points)

Modify the method in the first problem so that it takes an optional second parameter. If this parameter is an even integer, even-numbered elements should be returned, instead of odd-numbered.

#### Problem 3 (4 points)

Write a method that takes an array of strings and a block and calls this block on each string. Recall that the keyword to call a block is `yield`. The syntax for the call is the following:

``````

method(["blah", "Blah"]) {...}
``````
Test the method by passing it a block that prints the result of applying `reverse` to each string. Print out the original array after the call.
Test it again by passing a block that calls `reverse!`. Print out the original array. Observe the differences, explain them in comments.

#### Problem 4 (6 points)

Write a method that takes an array and a block and returns a new array where elements are the result of applying the block to each element of the original array. Test it on an array of integers and a method that squares each element. Also test it on an array of a different type and a different block.

#### Problem 5 (15 points)

Use methods of the class Enumerable to do the following:

1. Select all strings from a mixed array
2. Select all non-strings from a mixed array
3. Select all odd numbers from a range of numbers
4. Find the shortest string in an array of strings
5. Concatenate all strings in an array of strings

### Part 2 (40 points)

Define a ruby class `Multiset` that implements the mathematical notion of a multiset: http://en.wikipedia.org/wiki/Multiset. Multisets are like sets, but can have multiple occurrences of the same element. For instance, X = {1, 2, 2, 3, 4, 4} is a multiset.

The number of times a given element occurs in a multiset is called its multiplicity. Multiplicity of x in a multiset X is denoted as m(x, X). For instance, in the above set X the multiplicity of 4 is 2, the multiplicity of 1 is 1, and the multiplicity of 5 is 0.

Two multisets are equal if and only if they contain the same elements with the same multiplicities. For instance, the following multiset if not equal to X above: `X = {1, 2, 3, 3, 4, 4}`.

A multiset X is a subset of a multiset Y if for every element x of X m(x,X) <= m(x, Y).

The intersection of two multisets X, Y is a multiset Z such that for every possible element x: m(x,Z) = min(m(x, X), m(x, Y)). For instance, if X = {1, 1, 2, 4}\$ and Y = {1, 2, 2, 2}, then the intersection of X and Y is {1, 2}.

The union of two multisets X, Y is a multiset Z such that for every possible element x: m(x,Z) = max(m(x, X), m(x, Y)). For instance, if X = {1, 1, 2, 4}\$ and Y = {1, 2, 2, 2}, then the union of X and Y is {1, 1, 2, 2, 2, 4}.

Your task is to define a ruby class `Multiset` such that it provides the following methods:

• a constructor that creates an empty multiset.
• `to_s` a method that prints the multiset (i.e. prints all of its elements as many times as they occur in the multiset, in {} braces). The order of elements doesn't matter.
• `mult` for multiplicity. For instance, if mset1 is an object representing a multiset {1, 2, 3, 3, 4, 4} then `mset1.mult 4` should return 2 (recall that parentheses are optional in ruby for method parameters).
• `add` to add an element to a multiset. ```mset1.add 5``` would add 5 to a multiset mset1. If the element is already in the multiset, its multiplicity is increased by 1.
• `addAll` that takes an array and adds all of its elements to the multiset. The number of times an element occurs in the array is the number of times it is added.
• `includes?` that takes an element and returns true if the element is present in the multiset and false otherwise. For instance, for the above multiset `mset1.includes? 6` returns false
• `intersect` -- intersection of two multisets as defined above. The method is called on one multiset and takes another one as a parameter.
• `union` -- union of two multisets as defined above. The method is called on one multiset and takes another one as a parameter.
• `equals?` -- a method that is called on a multiset, takes another multiset as a parameter, and returns true if the two multisets are equal and false otherwise.
• `subset?` -- a method that is called on a multiset, takes another multiset as a parameter, and returns true if the first multiset is a subset of the second one and false otherwise.

Make sure to test your methods carefully. You might want to add methods to the class one by one, each method followed by its testing code.