### Q1: Palindromes

Adapt your solution from the “palindromes” question so that instead of writing palindrome?(“foo”)you can write “foo”.palindrome?

#### My Example Code

```
# add new method to String class
class String
def palindrome?()
s = self.downcase.gsub(/\W*/,"")
s == s.reverse
end
end
# or we can use method_missing
class String
def method_missing(m,*args,&block)
# m is method name(a symbol), use id2name or to_s
# self is foo in this case
if m.id2name == "palindrome?"
s = self.downcase.gsub(/\W/,"")
s == s.reverse
else
# if no match here, retrun to ancestor
super
end
end
end
puts "foo".palindrome? # => false
word = "foof"
puts word.palindrome? # =>true
```

### Q2: Enumerable Palindrome

Adapt your palindrome solution so that it works on Enumerables. That is:

`[1,2,3,2,1].palindrome? # => true`

(It is not necessary for the collection’s elements to be palindromes themselves - only that the top-level collection be a palindrome.) Although hashes are considered Enumerables, your solution does not need to make sense for hashes (though it should not produce an error).

#### My Example Code

```
module Enumerable
def palindrome?
if self.kind_of?(Array)
self == self.reverse
else
temp = self.to_a
temp == temp.reverse
end
end
end
a = [1,2,[1,2],2,1]
b = [["a"],"b","b",["a"]]
puts a.palindrome?
puts b.palindrome?
```

### Q3: Cartesian Product (use yield)

Given two collections (of possibly different lengths), we want to get the Cartesian product of the sequence - in other words, every possible pair of N elements where one element is drawn from each collection.

For example, the Cartesian product of the sequences`a=[:a,:b,:c]`

and`b=[4,5]`

is:`a×b = [[:a,4],[:a,5],[:b,4],[:b,5],[:c,4],[:c,5]]`

Create a method that accepts two sequences and returns an iterator that will yield the elements of the Cartesian product, one at a time, as a two-element array.

- It doesn’t matter what order the elements are returned in. So for the above example, the ordering [[:a,4], [:b,4], [:c,4], [:a,5], [:b,5], [:c,5]] would be correct, as would any other ordering.
- It does matter that within each pair, the order of the elements matches the order in which the original sequences were provided. That is, [:a,4] is a member of the Cartesian product a×b, but [4,:a] is not. (Although [4,:a] is a member of the Cartesian product b×a.)

To start you off, here is a pastebin link to skeleton code (http://pastebin.com/cgSuhtPf) showing possible correct results. For your convenience the code is also shown below

```
class CartesianProduct
include Enumerable
# your code here
end
# Examples of use
c = CartesianProduct.new([:a,:b], [4,5])
c.each { |elt| puts elt.inspect }
# [:a, 4]
# [:a, 5]
# [:b, 4]
# [:b, 5]
c = CartesianProduct.new([:a,:b], [])
c.each { |elt| puts elt.inspect }
# (nothing printed since Cartesian product
# of anything with an empty collection is empty)
```

#### My Example Code

```
class CartesianProduct
include Enumerable
def initialize(arr_1,arr_2)
@arr_1 = arr_1
@arr_2 = arr_2
end
def each()
if block_given?
len1, len2 = @arr_1.size, @arr_2.size
(0...len1).each do |i|
(0...len2).each do |j|
element = [@arr_1[i],@arr_2[j]]
yield element
end
end
else
return "Blcok missing!"
end
end
end
c = CartesianProduct.new([:a,:b,:c], [4,5])
c.each {|elt| puts elt.inspect}
puts c.each
```