Speed up writing: Improve #strings performance

 #strings now returns a Hash representing the string frequency:
  "bob" => 1,
  "mary" => 50

 This is significantly more efficient than arrays, especially for
 cases where content repeats in multiple cells.  Further operations such
 as counting uniques, and set subtraction, are also more efficient.

 Given a simple test program on my laptop:

  book = Spreadsheet::Workbook.new
  sheet = book.create_worksheet(:name => "Foo")
  (1..15000).each do |i|
    row = sheet.row(i)
    row.concat(%w(hello hello hello hello hello hello hello hello hello hello hello hello))
  end
  book.write("book.xls")

Runtime before change:
  real  0m37.723s

Runtime after change:
  real  0m11.922s
Speed up writing: Improve Format#is_(date/time/datetime/date_time)

This commit caches the regexes used for these methods inside the Format
instance.  This provides a roughly 25% speed increase at write time, as
they're consumed heavily by format_dates!

Test program:

  book = Spreadsheet::Workbook.new
  sheet = book.create_worksheet(:name => "Foo")
  (1..15000).each do |i|
    row = sheet.row(i)
    row.concat(%w(hello hello hello hello hello hello hello hello hello hello hello hello))
  end
  x= Benchmark.measure do
    book.write("book.xls")
  end
  puts "#{Time.now} writing done in #{x.real} seconds"

Before change:
  writing done in 10.20752740377256 seconds

After change:
  writing done in 7.55835294723511 seconds
Speed up writing: Faster Workbook#add_format

The above method is (indirectly) used heavily by format_dates!, and
prior to this patch exhibited O(n) behavior.

This patches keeps @formats as an array, but introduces a secondary
@formats_set Hash to represent the same list as a Hash for quick member
lookup to avoid @formats.include?(x)
Speed up writing: Faster Writer::Workbook#xf_index

The above method is invoked for every single cell written, and
previously exhibited terrible performance when there were lots of
formats in the workbook (whether added manually or automatically).

This commit makes its performance O(1)
Bugfix: Proper SST partial vs. complete writing

This was broken by 175523d6879353596310bedaefb06d12fe35049c - the bug
caused "partial" to always be chosen.

The net effect was slightly larger SST tables, nothing more...
Minor optimization
Fix failing test suite

See related discussion at
https://groups.google.com/d/msg/rubyspreadsheet/SAAWYAVa2x8/s41fmMdELkMJ
Speed up writing: Faster Writer::Workbook#write_fonts

Previously this method called #key (expensive) on each format->font in
the sheet.  This is inefficient as quite often, many formats share the
same font.

This commit makes it invoke it once per distinct ruby instance of Format
Speed up writing: Faster Font#key

This method is consumed at write time for each distinct format (not each
distinct font - typically much less)

This commit introduces a mini internal cache to avoid expensive key
computation
Speed up writing: More efficient #format_dates!

This method was very liberal with the number of new formats it created.
Roughly, it created a new format for each Date/Time cell it detected.

In a large sheet with many date/time cells, the high number of
generated formats meant much slower writing, specifically when it the
writers enter the #write_xfs and #write_rows methods.

This commit makes format_dates! less liberal with generating new
formats.  Essentially, when it needs to generate a new format to assign
to a date/time cell, it will re-use an existing format that matches the
needed characteristics.
New and updated test cases

This provides coverage for my previous few commits which centered around
optimizing writing sheets.
Fix error in test suite under ruby 1.9
spreadsheet-0.7.2.gem released