From: Robin Stocker Date: 2006-08-28T05:34:59+09:00 Subject: Re: [QUIZ] DayRange (#92) Hi, Here's my solution (tests included). It's a little long, but I wanted it to have these features: * Input can consist of numbers and day name abbreviations of any length * It is easy to make a localised version (a German one is included) * Length of abbreviated output names can be specified Cheers, Robin ---- require 'abbrev' require 'test/unit' class DayRange def self.use_day_names(week, abbrev_length=3) @day_numbers = {} @day_abbrevs = {} week.abbrev.each do |abbr, day| num = week.index(day) + 1 @day_numbers[abbr] = num if abbr.length == abbrev_length @day_abbrevs[num] = abbr end end end use_day_names \ %w(Monday Tuesday Wednesday Thursday Friday Saturday Sunday) def day_numbers; self.class.class_eval{ @day_numbers } end def day_abbrevs; self.class.class_eval{ @day_abbrevs } end attr_reader :days def initialize(days) @days = days.collect{ |d| day_numbers[d] or d } if not (@days - day_abbrevs.keys).empty? raise ArgumentError end end def to_s ranges = [] number_ranges.each do |range| case range[1] - range[0] when 0; ranges << day_abbrevs[range[0]] when 1; ranges.concat day_abbrevs.values_at(*range) else ranges << day_abbrevs.values_at(*range).join('-') end end ranges.join(', ') end def number_ranges @days.inject([]) do |l, d| if l.last and l.last[1] + 1 == d l.last[1] = d else l << [d, d] end l end end end class DayRangeGerman < DayRange use_day_names \ %w(Montag Dienstag Mittwoch Donnerstag Freitag Samstag Sonntag), 2 end class DayRangeTest < Test::Unit::TestCase def test_english tests = { [1,2,3,4,5,6,7] => 'Mon-Sun', [1,2,3,6,7] => 'Mon-Wed, Sat, Sun', [1,3,4,5,6] => 'Mon, Wed-Sat', [2,3,4,6,7] => 'Tue-Thu, Sat, Sun', [1,3,4,6,7] => 'Mon, Wed, Thu, Sat, Sun', [7] => 'Sun', [1,7] => 'Mon, Sun', %w(Mon Tue Wed) => 'Mon-Wed', %w(Frid Saturd Sund) => 'Fri-Sun', %w(Monday Wednesday Thursday Friday) => 'Mon, Wed-Fri', [1, 'Tuesday', 3] => 'Mon-Wed' } tests.each do |days, expected| assert_equal expected, DayRange.new(days).to_s end end def test_german tests = { [1,2,3,4,5,6,7] => 'Mo-So', [1,2,3,6,7] => 'Mo-Mi, Sa, So', [1,3,4,5,6] => 'Mo, Mi-Sa', [2,3,4,6,7] => 'Di-Do, Sa, So', [1,3,4,6,7] => 'Mo, Mi, Do, Sa, So', [7] => 'So', [1,7] => 'Mo, So', %w(Mo Di Mi) => 'Mo-Mi', %w(Freit Samst Sonnt) => 'Fr-So', %w(Montag Mittwoch Donnerstag Freitag) => 'Mo, Mi-Fr', [1, 'Dienstag', 3] => 'Mo-Mi' } tests.each do |days, expected| assert_equal expected, DayRangeGerman.new(days).to_s end end def test_translation eng = %w(Mon Tue Wed Fri) assert_equal 'Mo-Mi, Fr', DayRangeGerman.new(DayRange.new(eng).days).to_s end def test_should_raise assert_raise ArgumentError do DayRange.new([1, 8]) end end end