Begin forwarded message:

> From: "Roland Swingler" <roland.swingler / gmail.com>
> Date: August 28, 2006 3:07:36 PM CDT
> To: submission / rubyquiz.com
> Subject: Please Forward: Ruby Quiz Submission
>
> Hi,
>
> Here is my solution. I have added start accessor methods so one can
> set the day the week starts - a lot of uses for this might want a more
> weekend focused week, i.e. Thu-Mon. I had just been reading the first
> couple of pages of "Programming Pearls" by Jon Bentley, and that gave
> me the idea of using a "bit array" approach to the problem of sorting
> the days. One stylistic approach I wanted to play with was using ||
> and && in assignment - they might be used slightly too heavily
>
> dayrange.rb:
>
> require 'parsedate'
>
> class DayRange
>  WEEK = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]
>
>  def initialize(*days)
>    @start = 0
>    @days = Array.new(7, nil)
>    days.each do |day|
>      i = int_for day
>      @days[i] = WEEK[i]
>    end
>  end
>
>  def to_s
>    # Convert any middle days to "-"
>    output = [@days[0]] + (1..6).map do |i|
>      (@days[i] &&
>       (WEEK.include?(@days[i-1]) || @days[i-1] == "-") &&
>       WEEK.include?(@days[i+1]) &&
>       "-") || @days[i]
>    end
>    # remove nils, duplicate dashes and any commas surounding them
>    output.compact.join(", ").gsub(/(, )?-, /, '-').squeeze
>  end
>
>  def start=(day)
>    i = int_for(day) - @start
>    if i != 0
>      @start += i
>      # shift days from the front or back of the array to the other
> end
>      # so as to get the start day to index 0
>      index, shift_len = (i > 0) ? [0, i] : [i, -i]
>      mv_days = @days.slice!(index, shift_len)
>      @days = (i > 0) ? @days + mv_days : mv_days + @days
>    end
>  end
>
>  def start
>    WEEK[@start]
>  end
>
>  private
>
>  def int_for(day)
>    # Get the day as an integer regardless of input
>    i = ((day.is_a?(String) && ParseDate.parsedate(day)[7]) || day) - 1
>    # ParseDate thinks that Sunday is the 0th day of the week
>    i = 6 if -1 == i
>    raise ArgumentError unless (0..6).include?(i)
>    i
>  end
> end
>
> And my test case - tc_dayrange.rb:
>
> require 'dayrange'
> require 'test/unit'
>
> class TestDays < Test::Unit::TestCase
>  def test_all
>    d = DayRange.new(1,2,3,4,5,6,7)
>    assert_equal("Mon-Sun", d.to_s)
>  end
>
>  def test_end
>    d = DayRange.new(1,2,3,4,5,6)
>    assert_equal("Mon-Sat", d.to_s)
>  end
>
>  def test_start
>    d = DayRange.new(2,3,4,5,6,7)
>    assert_equal("Tue-Sun", d.to_s)
>  end
>
>  def test_alternate
>    d = DayRange.new(1,3,4,6,7)
>    assert_equal("Mon, Wed, Thu, Sat, Sun", d.to_s)
>  end
>
>  def test_no_wrap
>    d = DayRange.new(1,2,3,6,7)
>    assert_equal("Mon-Wed, Sat, Sun", d.to_s)
>  end
>
>  def test_order_unimportant
>    d = DayRange.new(4,1,5,6,3)
>    assert_equal("Mon, Wed-Sat", d.to_s)
>  end
>
>  def test_single
>    d = DayRange.new(7)
>    assert_equal("Sun", d.to_s)
>  end
>
>  def test_two
>    d = DayRange.new(7,1)
>    assert_equal("Mon, Sun", d.to_s)
>  end
>
>  def test_two_names
>    d = DayRange.new("Monday", "Sun")
>    assert_equal("Mon, Sun", d.to_s)
>  end
>
>  def test_error_raised
>    assert_raise(ArgumentError){
>      d = DayRange.new(1, 8)
>    }
>  end
>
>  def test_week_start_friday
>    d = DayRange.new(5,6,7,1)
>    d.start = "Fri"
>    assert_equal("Fri-Mon", d.to_s)
>  end
>
>  def test_week_start_can_be_changed
>    d = DayRange.new(5,6,7,1)
>    assert_equal "Mon", d.start
>    d.start = 5
>    assert_equal("Fri-Mon", d.to_s)
>    d.start = "Sat"
>    assert_equal("Sat-Mon, Fri", d.to_s)
>    d.start = "Monday"
>    assert_equal("Mon, Fri-Sun", d.to_s)
>  end
> end
>
>  end