RPCFN: Business Hours (#10)

by on May 25, 2010

Ruby Programming Challenge For Newbies

RPCFN: Business Hours (#10)

By Ryan Bates

About Ryan Bates

Ryan BatesRyan Bates has been involved in web development since 1998. In 2005 he started working professionally with Ruby and Rails and is now best known for his work on Railscasts, the free Ruby on Rails screencast series.

Ryan has this to say about the challenge:

Sometimes when working in a structured framework environment such as Rails it is easy to forget about the fundamentals of Ruby and how to organize code. The majority of this challenge could be done in one large method, but I encourage you to focus on readability through refactoring. This challenge also exercises working with times and iterations.

Our Awesome Sponsor

This monthly programming challenge is sponsored by Backup My App.

Backup My App

Backup My App is an automatic backup service for Ruby on Rails applications. You simply install the plugin to your Rails application and they handle the rest of the process. They store backup history for several weeks and you can restore any of them automatically. Try out their 1 GB plan for free. Backup My App has sponsored this challenge and is proud to make this contribution to the Ruby community.

Prizes

  • The participant with the best Ruby solution (if there is a tie between answers, then the one who posted first will be the winner) will be awarded any one of PeepCode’s Ruby on Rails screencasts and a free 10 GB account for a year from Backup My App.
  • From the remaining working Ruby solutions, three participants would be selected randomly and each one would be awarded any one of Pragmatic’s The Ruby Object Model and Metaprogramming screencasts.
  • All the participants in this challenge (except the participant with the best Ruby solution) will get a free 5 GB account for 6 months from Backup My App.

The four persons who win, can’t win again in the next immediate challenge but can still participate.

The Ruby Challenge

RPCFN

The Challenge

Chunky Bacon Begone is a dry-cleaning company known for its speedy service. It guarantees to dry-clean anything within two business hours or less. The problem is, when the customer drops off the clothes, he needs to know what time they are guaranteed to be done.

It is your job to write a Ruby script which will determine the guaranteed time given a business hour schedule. You must create a class called BusinessHours which allows one to define the opening and closing time for each day. It should provide the following interface:

hours = BusinessHours.new("9:00 AM", "3:00 PM")
hours.update :fri, "10:00 AM", "5:00 PM"
hours.update "Dec 24, 2010", "8:00 AM", "1:00 PM"
hours.closed :sun, :wed, "Dec 25, 2010"

The update method should change the opening and closing time for a given day. The closed method should specify which days the shop is not open. Notice days can either be a symbol for week days or a string for specific dates. Any given day can only have one opening time and one closing time — there are no off-hours in the middle of the day.

A method called calculate_deadline should determine the resulting business time given a time interval (in seconds) along with a starting time (as a string). The returned object should be an instance of Time. Here are some examples:

hours.calculate_deadline(2*60*60, "Jun 7, 2010 9:10 AM") # => Mon Jun 07 11:10:00 2010
hours.calculate_deadline(15*60, "Jun 8, 2010 2:48 PM") # => Thu Jun 10 09:03:00 2010
hours.calculate_deadline(7*60*60, "Dec 24, 2010 6:45 AM") # => Mon Dec 27 11:00:00 2010

In the first example the time interval is 2 hours (7,200 seconds). Since the 2 hours fall within business hours the day does not change and the interval is simply added to the starting time.

In the second line an interval of 15 minutes (900 seconds) is used. The starting time is 12 minutes before closing time which leaves 3 minutes remaining to be added to the next business day. The next day is Wednesday and therefore closed, so the resulting time is 3 minutes after opening on the following day.

The last example is 7 hours (25200 seconds) which starts before opening on Dec 24th. There are only 5 business hours on Dec 24th which leaves 2 hours remaining for the next business day. The next two days are closed (Dec 25th and Sunday) therefore the deadline is not until 2 hours after opening on Dec 27th.

Tip: Use Time.parse to generate a Time from a string. You may need to require “time” in order to do this.

Requirements: This has to be a pure Ruby script, using only the Ruby Standard Libraries (meaning, no external Gems, libraries). You do not need to build a gem for this. Pure Ruby code is all that is needed. Ryan will mostly be judging by the beauty of your code as long as it satisfies his test case.

How to Enter the Challenge

Read the Challenge Rules. By participating in this challenge, you agree to be bound by these Challenge Rules. It’s free and registration is optional. You can enter the challenge just by posting the following as a comment to this blog post:

  1. Your name:
  2. Country of Residence:
  3. GIST URL of your Solution (i.e. Ruby code) with explanation and / or test cases:
  4. Code works with Ruby 1.8 / 1.9 / Both:
  5. Email address (will not be published):
  6. Brief description of what you do (will not be published):

Note:

  • As soon as we receive your GIST URL, we will fork your submission. This means that your solution is frozen and accepted. Please be sure that is the solution you want, as it is now recorded in time and is the version that will be evaluated.
  • All solutions posted would be hidden to allow participants to come up with their own solutions.
  • You should post your entries before midnight of 27th June 2010 (Indian Standard Time). No new solutions will be accepted from 28th June onwards.
  • On 28th June 2010 all the solutions will be thrown open for everyone to see and comment upon.
  • The winning entries will be announced on this blog before 30th June 2010. The winners will be sent their prizes by email.

More details on the RPCFN?

Please refer to the RPCFN FAQ for answers to the following questions:

Donations

RPCFN is entirely financed by RubyLearning and sometimes sponsors, so if you enjoy solving Ruby problems and would like to give something back by helping with the running costs then any donations are gratefully received.

Click here to lend your support to: Support RubyLearning With Some Love and make a donation at www.pledgie.com !

Acknowledgements

Special thanks to:

  • Ryan Bates.
  • Sponsors Backup My App.
  • GitHub, for giving us access to a private repository on GitHub to store all the submitted solutions.
  • The RubyLearning team.

Questions?

Contact Satish Talim at satish [dot] talim [at] gmail.com OR if you have any doubts / questions about the challenge (the current problem statement), please post them as comments to this post and the author will reply asap.

The Participants

There are two categories of participants. Some are vying for the prizes and some are participating for the fun of it.

In the competition

  1. Simon Menke, Belgium
  2. Colin Casey, Canada
  3. Stephane Tang, France
  4. Juan Villanelo, Chile
  5. Vasko Zdravevski, USA
  6. Sebastián Rabuini, Argentina
  7. Dmitry Lipovoi, Russia
  8. Andy Vanasse, USA
  9. Cary Swoveland, Canada
  10. Jeremy Peterson, USA
  11. Paul Mucur, UK
  12. Delbert Mitten, USA
  13. Theo Mills, USA
  14. Rémy Coutable, France
  15. James Silberbauer, South Africa
  16. Michael Cramm, Canada
  17. Christopher Fortenberry, USA
  18. Tanzeeb Khalili, Canada

Just for Fun

  1. James Edward Gray II, USA
  2. Eric Hutzelman, USA
  3. Benoit Daloze, Belgium

The Winners

Winners

Congratulations to the winners of this Ruby Challenge. They are:

Previous Challenge

RPCFN: Interactive Fiction (#9) by Avdi Grimm.

Note: All the previous challenges, sponsors and winners can be seen on the Ruby Programming Challenge for Newbies page.

Update

  • This challenge is now closed.
  • All the solutions have been tested and the results are available here.
  • The (#11) challenge by Elise Huard, Belgium is scheduled for 1st July 2010.

Technorati Tags: , , , , ,

Posted by Satish Talim

Follow me on Twitter to communicate and stay connected

{ 59 comments… read them below or add one }

Simon Menke May 26, 2010 at 4:58 pm

Solution (#1):

Simon Menke, Belgium
https://gist.github.com/a22be92dd1ebbe85463e

Reply

Ryan Bates June 29, 2010 at 4:35 am

Looks like the gist linked here has been deleted, but I’m assuming this one is correct. https://gist.github.com/05200e30fce9e91713b1

This passes all of my tests. You can improve the int_to_day method by using an array. Other than this, the calculate_deadline method is quite long and complex. Either extract this into more descriptive methods or, better yet, a separate class.

Reply

Colin Casey May 26, 2010 at 7:22 pm

Solution (#2):

Colin Casey, Canada
Here is the GIST URL of my solution: https://gist.github.com/2ab2ac2625ad8d3c9f2d
This code works with both Ruby 1.8 and 1.9.

Reply

Ryan Bates June 29, 2010 at 4:31 am

This fails one of my tests. The “test_start_next_day_when_after_closing_time” found here: http://gist.github.com/456149

Other than this it is a pretty nice solution. The calculate_deadline method is quite complex and a good candidate for moving into a separate class.

Reply

Stephane T. May 27, 2010 at 12:45 am

Solution (#3):

Stephane Tang, France
https://gist.github.com/727e4e6af4b3243adb33
Ruby 1.8 (not tested on 1.9)

Reply

Ryan Bates June 29, 2010 at 4:27 am

This fails one of my tests. The “test_start_next_day_when_after_closing_time” found here: http://gist.github.com/456149

The use of the separate Day class is interesting. However I don’t really think it provides any advantages. It looks like it is there just to update the existing days of the week for the “update” and “closed” calls, but I don’t see what this provides over defining a new day each time.

The calculate_deadline method is quite complex and I think a better candidate for extracting into a separate class.

Reply

r4ito May 27, 2010 at 3:25 am

Solution (#4):

Juan Villanelo, Chile
Works with Ruby 1.9 (tested on 1.9.1p376)
gist: https://gist.github.com/eec8de0008e66e43158d
Not much to explain really. I just hope to get some feedback, thanks.

Reply

Ryan Bates June 29, 2010 at 4:22 am

This fails one of my tests. The “test_start_next_day_when_after_closing_time” found here: http://gist.github.com/456149

However, the solution is very concise and fairly clean. Merging the @times and @closed instances into a single hash can even make things a little more concise. The calculate_deadline method looks fairly complex, but not bad considering how much it’s doing.

Reply

Vasko Zdravevski May 27, 2010 at 9:45 am

Solution (#5):

Vasko Zdravevski, USA
https://gist.github.com/ab23fadbe38ae050efc3

Reply

Ryan Bates June 29, 2010 at 4:17 am

All of my tests pass which is great. However, the calculate_deadline method is quite long and complex. I think this stems from using the #compare method on Time. Since this method is only called once I’m not certain what this gives you. The two methods are communicating based on integers which isn’t very clear.

Reply

Theodore Mills May 29, 2010 at 5:14 am

I wanted to check with you regarding these example calls:

hours.calculate_deadline(15*60, “Jun 8, 2010 2:48 PM”) # => Thu Jun 10 09:03:00 2010
hours.calculate_deadline(7*60*60, “Dec 24, 2010 6:45 AM”) # => Mon Dec 27 11:00:00 2010

I’m having a hard time deriving the rules from these 2 examples whose time interval (in seconds) pushes the supplied start time into “off hours” territory. The 1st and 2nd examples seems to contradict each other. I am assuming in example 1, the opening time is 9:00AM whereas in the 2nd example it’s 11:00 AM. Is that correct?

If so, then why wouldn’t example 1′s result be Thu Jun 10 09:00:00 2010?

Sorry if I am missing something here.

Reply

r4ito May 29, 2010 at 8:40 am

The opening times for the example are all 9 am but those weekdays or dates where it has been updated.

>> hours.calculate_deadline(15*60, “Jun 8, 2010 2:48 PM”)
The time given is 900 seconds, but since that day closes at 3 pm you can only ‘allocate’ 12 minutes(720 sec) in here, the next day is closed because is wednesday, and finally at jun 9 you can put the last 180 seconds from 9am so you end up at 9:03 am.

>> hours.calculate_deadline(7*60*60, “Dec 24, 2010 6:45 AM”)
The time given is 25200 seconds, Dec 24 is open from 8 am to 1 pm, that’s 18000 seconds, 7200 left. The next day 25 dec is closed, 26 dec is wednesday so it’s also closed, 27 dec is open from 9 am, adding the 7200 secs(2 hours) you end up at 11 am.

I hope this helps.

Reply

James Edward Gray II May 29, 2010 at 9:30 pm

Solution (#6):

Here’s my solution, tested in Ruby 1.8.6:

https://gist.github.com/dea97cf5bb014917a797

Thanks for the fun little challenge Ryan. Great problem.

Reply

Ryan Bates June 29, 2010 at 4:11 am

A few of my tests aren’t passing here: test_change_hours_for_specific_dates and test_skip_closed_days at http://gist.github.com/456149.

Other than this it looks like a nice solution with some good error handling. It would be nice if the calculate_deadline method was shorter, but it’s pretty readable still.

Reply

Ryan Bates May 30, 2010 at 12:09 am

@Theodore, the calculate_deadline method is called on the hours defined in the earlier code block, so the opening time would be 9 AM for all days except Friday and Dec 24th. There aren’t any days which open at 11 AM.

If a time goes past the closing time then the remaining time should be applied to the next day and so on.

@r4ito thanks for the clear explanation. That is correct.

Reply

Sebastian Rabuini May 31, 2010 at 1:28 am

Solution (#7):

Sebastián Rabuini, Argentina
https://gist.github.com/5d6f7652bff18cf3ba75
Code works with Ruby 1.8 and 1.9

Reply

Ryan Bates June 29, 2010 at 4:03 am

For some reason this segfaults for me on line 56 when attempting to run my tests. I think it has something to do with the min/max calls on the time range. I’m running Ruby 1.8.7.

The solution looks pretty nice though, and I see the addition of the BusinessDay class helps cut down on parameter passing.

Reply

Ryan Bates June 29, 2010 at 4:06 am

I just realized I was running the tests on an older version of your gist. The latest one does not segfault, however there is still one test which is not passing. It’s called test_skip_full_day here: http://gist.github.com/456149

Reply

Dmitry Lipovoi May 31, 2010 at 3:16 pm

Solution (#8):

Dmitry Lipovoi, Russia
https://gist.github.com/e9c0da1a6e92dd12cbc7
Tested on 1.8.7
I used RSpec for tests here which could be threated as “third-party”. But solution itself works on pure ruby.

Reply

Ryan Bates June 29, 2010 at 3:52 am

A very complete solution which passes my tests and the full set of specs you included. It’s one of the few which properly handles DST changes which I don’t consider a requirement, but it is a great bonus.

The use of the separate OpenHours class is really neat, although I would like to see the calculate_deadline method made cleaner and perhaps some of that logic extracted into another class. Great job overall though.

Reply

Joe Van Dyk June 2, 2010 at 9:22 am

Sorry, still confused as to what BusinessHours#calculate_deadline is supposed to do.

Reply

Joe Van Dyk June 2, 2010 at 9:23 am

Ah, r4ito’s comment made sense. The post should be updated with that example.

Reply

Andy Vanasse June 4, 2010 at 9:48 pm

Solution (#9):

Andy Vanasse, USA
https://gist.github.com/d3ecad12d5f8062de19e
Tested in 1.8.7, 1.9.1

Reply

Ryan Bates June 29, 2010 at 3:45 am

Good solution and passes my tests. The code overall feels verbose and more complex than necessary, but I don’t see any specific points which stand out except for the large calculate_deadline method.

Reply

Ryan Bates June 29, 2010 at 5:02 am

Actually there is one test case which this didn’t end up passing. See “test_start_on_closed_days” here: http://gist.github.com/456149

Reply

Eric Hutzelman June 6, 2010 at 7:11 am

Solution (#10):

Eric Hutzelman, USA
Entry Type: Just for Fun
GIST URL: https://gist.github.com/5848e8202600f6def5d6
Code works with Ruby 1.8 only

Reply

Ryan Bates June 29, 2010 at 2:41 am

Very clean and concise solution which passes all of my tests. You can clean up some of the calculate_deadline method complexity by extracting out a separate class, but this is minor. Great job!

Reply

Cary Swoveland June 8, 2010 at 4:48 am

Solution (#11):

Cary Swoveland, Canada
My submission for this month’s challenge is at: https://gist.github.com/e9894f10229836ac89bf
I included the test code and test cases I used at the end of the file.
I’m retired and have been tinkering with Ruby for the past few months. I did some C programming about 15 years ago, but nothing since. I had a quick look at Python, but thought Ruby was more elegant, and would be more fun to learn. I’m also interested in woodworking, photography and math puzzles. I can recommend three books to other Ruby-newbies: “Beginning Ruby” (Cooper), “The Ruby Programming Language” (Flannagan & Matsumoto) and “Ruby Cookbook” (Clarkson & Richardson).

Reply

Ryan Bates June 29, 2010 at 2:07 am

All tests pass which is excellent. The code could be a little simpler though. The opening/closing schedule is stored across 4 instance variables but it’s possible to do it in a single hash which would clean up a lot of the setting/fetching code.

Reply

Jeremy Peterson June 12, 2010 at 9:17 am

Solution (#12):

Jeremy Peterson, USA
http://github.com/jeremygpeterson/BusinessHours
Code works with Both Ruby 1.8 and 1.9

Reply

Ryan Bates June 28, 2010 at 11:58 pm

Extremely clean and concise solution which passes all of my tests. Great job! It is also nice to see Cucumber used for this kind of problem.

The each method for iterating over the days is a cool idea, but may bring in more complications than necessary. You can also remove some local variables and parameter passing by extracting out a separate class.

These are minor criticisms though. Overall wonderful solution.

Reply

Ryan Bates June 29, 2010 at 3:47 am

One other thing, the use of class method for @@schedule will cause problems when working with multiple instances with different opening/closing times. The schedule really should be an instance variable.

Reply

Ryan Bates June 29, 2010 at 3:48 am

Correction: I meant class variable. Not class method.

Reply

Paul Mucur June 12, 2010 at 6:54 pm

Solution (#13):

Paul Mucur, UK
https://gist.github.com/85341b62c6181ccda5b4
Code works with Ruby 1.8 / 1.9 / Both: Both

Reply

Ryan Bates June 28, 2010 at 11:52 pm

One of my tests aren’t passing, specifically test_start_at_opening_time here http://gist.github.com/456149

The code itself is more complex than necessary. The calculate_deadline method is much longer than need be. Part of this complexity may branch out from using a separate @dates and @days instance variables to store the times. There are ways to simplify this into a single hash.

I also recommend extracting out the complex deadline calculation logic into a separate class which will remove a lot of the local variables and parameter passing.

Reply

Delbert Mitten June 15, 2010 at 2:10 am

Solution (#14):

Delbert Mitten, USA
https://gist.github.com/fa971247e5fe1e287ad4
(code should work with both, but tested in 1.8)

Reply

Ryan Bates June 28, 2010 at 11:44 pm

For some reason one of my tests (test_change_hours_for_specific_dates) is not passing. You can see it here: http://gist.github.com/456149

Otherwise great solution. If you’re looking to improve it, there are ways to make the opening/closing hour storage more concise, and you can also clean up the calculate_deadline method by extracting it into a separate class.

Reply

Theo Mills June 16, 2010 at 7:39 am

Solution (#15):

Theo Mills, USA
GIST URL: git@gist.github.com:08c54fbced452112fb9f.git
Code works with Ruby 1.8: Tested on 1.8 only

Reply

Ryan Bates June 28, 2010 at 11:39 pm

Really great solution which passes all tests. It’s possible to remove local variables and parameter passing by extracting the deadline calculation into a separate class, but overall great job!

Reply

Ryan Bates June 29, 2010 at 5:03 am

Actually there is one test case which this doesn’t pass. See “test_start_on_closed_days” here: http://gist.github.com/456149

Reply

rymai June 20, 2010 at 12:16 am

Solution (#16):

Rémy Coutable, France
GIST URL: https://gist.github.com/29cfef4ef1d308f4194f
Code works with Ruby 1.8 and 1.9.

Reply

Ryan Bates June 28, 2010 at 11:22 pm

Passes all tests and overall clean and well documented solution. However there are more concise and simple ways to store and retrieve the opening/closing hours.

Reply

James Silberbauer June 21, 2010 at 2:57 pm

Solution (#17):

James Silberbauer, South Africa
Freelance Ruby on Rails developer
https://gist.github.com/3b2e5310231f36353707
This code works with Ruby 1.8.7 and Ruby 1.9.1.

Reply

Ryan Bates June 28, 2010 at 11:14 pm

Nice solution which passes all tests and has good use of a DayRule class. However, the instance variables feel a little overly used and it is possible to simplify the BusinessHours#initialize, update, and closed methods. But otherwise great solution.

Reply

Michael Cramm June 24, 2010 at 6:03 am

Solution (#18):

Michael Cramm, Canada.
https://gist.github.com/3a03d223ccbafdb673ed
This code was tested and works with Ruby version 1.8.7

Reply

Ryan Bates June 28, 2010 at 11:05 pm

Great solution which passes all of my tests. Nice use of a Day class to extract some logic. My only criticism is the calculate_deadline method is heavy and more complex than I prefer. When there is a method this long with so many local variables it is usually a sign to extract it into a separate class.

Reply

CPFB June 26, 2010 at 12:12 am

Solution (#19):

Christopher Fortenberry, USA
https://gist.github.com/d3ee24813535433a61ed
Code tested with Ruby 1.8.6

Reply

Ryan Bates June 28, 2010 at 11:01 pm

There is one test case which does not pass for me, and that is when setting the calculate_deadline starting time after the closing time it does not skip to the opening time of the next day. See test_start_next_day_when_after_closing_time test here: http://gist.github.com/456149

Other than this the code feels more complicated than necessary, especially the get_daily_operating_hours method. This can be refactored into something shorter and simpler.

Reply

Benoit Daloze June 26, 2010 at 5:53 pm

Solution (#20):

Benoit Daloze, Belgium
https://gist.github.com/951938000e732ca79825
Code works with Ruby 1.8 and 1.9
I am ‘objectifying’ the rules, which returns a TimeRange (opening/closing hour) and they are then merged (with TimeRange#&).
The spec cover the examples given.
This solution is `Just for fun’

Reply

Ryan Bates June 28, 2010 at 10:54 pm

All of my tests pass, good job! This is a very interesting solution using many different classes. It uses more classes than I consider necessary but it is neat to see this approach.

Reply

Tanzeeb Khalili June 27, 2010 at 10:59 pm

Solution (#21):

Tanzeeb Khalili, Canada
http://gist.github.com/455049
Tested w/ Ruby 1.8
Fairly straightforward, lots of conversion between String and Time.

Reply

Ryan Bates June 28, 2010 at 10:51 pm

Very clean and simple solution, unfortunately it does not meet all of the requirements. The last line in the example here returns 9:45 AM instead of the expected 11:00 AM.

I’m guessing if the starting at time is before the beginning of the day it does not fast-forward to the opening time.

Reply

Ryan Bates June 29, 2010 at 4:41 am

Thank you everyone who participated in this challenge, it has been great to see your solutions. Some of the solutions did not pass all of my tests. You can see the set of tests I’m using here. http://gist.github.com/456149

You’ll notice this test suite does not include daylight savings time changes. This is not a requirement because not everyone lives in an area that is effected by it. However bonus points if you did account for DST.

Congratulations to the (soon-to-be chosen) winners.

Reply

Ryan Bates June 29, 2010 at 5:27 am

Here is my solution to this problem.
http://gist.github.com/456307

Reply

Cary Swoveland June 29, 2010 at 7:05 am

Ryan,

I would like to thank you for preparing and running this challenge. I thought it was excellent. The instructions were clear, the problem was very instructive for we newbies, your comments on the solutions were helpful and the amount of time required by participants was just right. Considering the large number of entrants, I think others might agree. I also learned a lot by reading others’ code, and especially liked your own.

Just one small thing: if we were told the store is normally closed on Sundays, but will have hours of 6:00 AM – 6 PM on December 26, 2010, which happens to be a Sunday, is it not reasonable to assume the store will be open that day? Granted, while it’s not uncommon to hear of a blowout sale the day after Christmas, it’s probably more likely to be, say, a consumer electronics store than a dry cleaner. However, if we do not allow hours open by date to have precedence over days closed by day-of-week, there is no easy way to deal with exceptions to normal day-of-week closures.

Cary

Reply

Ryan Bates June 29, 2010 at 9:15 pm

Cary, that is a great point. Having specific dates take precedence over days of the week definitely makes sense and is how my solution works.

However, I did not mention this in the description of the problem so I don’t consider it a requirement. But good job to those who took this into consideration.

Reply

Dmitry Lipovoi June 29, 2010 at 1:14 pm

I checked up all solutions against my test suite. Maybe someone could find it useful.

=== Solution #1:

Github reports that gist has been deleted.

=== Solution #2:

hours = BusinessHours.new(“9:00 AM”, “3:00 PM”)
hours.calculate_deadline(2*60*60, “Jun 7, 2010 4:00 PM”) # => Tue Jun 08 12:00:00

Should return “Tue Jun 08 11:00:00″

=== Solution #3:

hours = BusinessHours.new(“9:00 AM”, “3:00 PM”)
hours.calculate_deadline(2*60*60, “Jun 7, 2010 4:00 PM”) => Mon Jun 07 11:00:00

Should return “Tue Jun 08 11:00:00″

=== Solution #4:

Originally it printed results instead of returning them from method.
After little tweak from my side I noticed that it fails same test case as Solution #2.

=== Solution #5:

hours = BusinessHours.new(“9:00 AM”, “3:00 PM”)
hours.calculate_deadline(6*60*60, “Jun 7, 2010 9:00 AM”) # => Tue Jun 08 00:00:00

Should return either “Tue Jun 07 15:00:00″ or “Tue Jun 08 09:00:00″

=== Solution #6:

hours = BusinessHours.new(“9:00 AM”, “3:00 PM”)
hours.closed :sun
hours.calculate_deadline(2*60*60, “Jun 5, 2010 2:45 PM”) # => Sun Jun 06 10:45:00

Jun 6th is Sun, so should be skipped. Right answer is “Mon Jun 07 10:45:00″

=== Solution #7:

hours = BusinessHours.new(“9:00 AM”, “3:00 PM”)
hours.calculate_deadline(20*60*60, “Jun 7, 2010 10:45 AM”) # => Tue Jun 08 06:45:00

Should return “Thu Jun 10 12:45:00″

=== Solution #8:

Mine :)

=== Solution #9:

hours = BusinessHours.new(“9:00 AM”, “3:00 PM”)
hours.closed “Dec 25, 2010″
hours.calculate_deadline(2*60*60, “Dec 25, 2010 11:45 AM”)
ArgumentError: comparison of Fixnum with nil failed
from ./lib/business_hours.rb:49:in ` Mon Jun 07 10:45:00

Should return “Mon Jun 07 11:00:00″

=== Solution #14:

Doesn’t pass original tests.

=== Solution #15:

hours = BusinessHours.new(“9:00 AM”, “3:00 PM”)
hours.closed :sun
hours.calculate_deadline(2*60*60, “Jun 6, 2010 11:45 AM”)
ArgumentError: comparison of Time with nil failed
from ./lib/business_hours.rb:78:in ` Sat Jun 05 11:00:00

Jun 3rd is Thu. Should return “Sat Jun 05 10:00:00″

=== Solution #17:

See test case in Solution #5
Also infinite loop on dst changes

=== Solution #18:

hours = BusinessHours.new(“9:00 AM”, “3:00 PM”)
hours.calculate_deadline(2*60*60, “Jun 7, 2010 10:45 PM”) # => Mon Jun 28 11:00:00

Should return “Tue Jun 08 11:00:00″
Actually it didn’t pass any test cases. Need to take a closer look. Maybe I’m doing something wrong.

=== Solution #19:

hours = BusinessHours.new(“9:00 AM”, “3:00 PM”)
hours.calculate_deadline(2*60*60, “Jun 7, 2010 10:45 PM”) # => Wed Jun 09 12:45:00

Should return “Tue Jun 08 11:00:00″

=== Solution #20:

Failing changing to dst.
Other tests pass.

=== Solution #21:

Many cases are not covered. For example:

hours = BusinessHours.new(“9:00 AM”, “3:00 PM”)
hours.calculate_deadline(2*60*60, “Jun 7, 2010 8:45 AM”) # => Mon Jun 07 10:45:00

Should return “Mon Jun 07 11:00:00″

Reply

Dmitry Lipovoi June 29, 2010 at 1:19 pm

Whoops. Parser broke part of message (solutions 9 to 13) :-\

=== Solution #9:

hours = BusinessHours.new(“9:00 AM”, “3:00 PM”)
hours.closed “Dec 25, 2010″
hours.calculate_deadline(2*60*60, “Dec 25, 2010 11:45 AM”)
ArgumentError: comparison of Fixnum with nil failed

=== Solution #10:

My test suite passed completely. Congratulations!

Btw, like this solution very much. Except passing date as string to calculate_deadline in tail recursion to parse it again every iteration. But it may be fixed easily.

=== Solution #11:

Test suite passed completely. Congratulations!

=== Solution #12:

Using class-level variable to store schedule may produce absolutely insane results.

=== Solution #13:

hours = BusinessHours.new(“9:00 AM”, “3:00 PM”)
hours.calculate_deadline(2*60*60, “Jun 7, 2010 8:45 AM”) # => Mon Jun 07 10:45:00

Should return “Mon Jun 07 11:00:00″

Reply

Dmitry Lipovoi June 30, 2010 at 1:55 pm

As Cary Swoveland noticed (thanks), message was broken in another one place (around solutions 15th and 16th):

=== Solution #15:

hours = BusinessHours.new(“9:00 AM”, “3:00 PM”)
hours.closed :sun
hours.calculate_deadline(2*60*60, “Jun 6, 2010 11:45 AM”)
ArgumentError: comparison of Time with nil failed

Jun 6th is Sun.

=== Solution #16:

hours = BusinessHours.new(“9:00 AM”, “3:00 PM”)
hours.update :fri, “10:00 AM”, “5:00 PM”
hours.calculate_deadline(14*60*60, “Jun 3, 2010 9:00 AM”) # => Sat Jun 05 11:00:00

Jun 3rd is Thu. Should return “Sat Jun 05 10:00:00″

Reply

Leave a Comment

{ 38 trackbacks }

Previous post:

Next post: