Ed:

> I found Sununda's algorithm challenge to be very interesting. I'm often
>  amazed by the different approaches to a given problem.

Thanks. I was amazed too at the range of responses.

Here's my offering for your exercise.

My tweaks are:

1. Avoid the sort as we have only two items (I haven't timed that doing it by 
hand is faster than letting REBOL set up a sort for just two items -- it may 
be worth someone running a benchmark on that one day,

2. Avoid the loop around *all* the days in the period. I reckoned if I could 
round the first date down to the nearest Monday while rounding the second date 
up to the next nearest Monday, I was half way there. The tricky part was 
tracking how many countable days I'd added in by the rounding -- hence the 
blocks 
of obscure negative numbers. This theoretically makes it faster -- especially 
for very wide date ranges.

3. That left me needing to run a loop against the extra holiday days, 
checking each if was in range and not a weekend. And I had to do that before 
Step 2 
so it was on the original dates, not the rounded ones. This may counteract the 
theoretical speed improvements in Step 2, especially if there are many holiday 
dates for a narrow date range.


calc-workdays: func [
 date1 [date!]
 date2 [date!]
 holidays [block!]
/non
 /local
  dates
  offset
  hol-count
 working-days
][

 ;; Put dates in order
 ;; ------------------
 dates: copy reduce [date1]
 either date1 < date2 [append dates date2] [insert dates date2]

 ;; count holidays in range
 ;; -----------------------
 hol-count: 0
 foreach hd holidays [
  if all [
      hd/weekday <= 5   ;; got to be a weekday to count
      hd >= dates/1
      hd <= dates/2][
         hol-count: hol-count + 1
     ]
  ]

  ;; Round dates to Mondays
  ;; ----------------------
 offset: 0
 offset: offset + pick [0 -1 -2 -3 -4 -4 -4] dates/1/weekday
 dates/1: dates/1 + 1 - dates/1/weekday

 offset: offset + pick [-5 -4 -3 -2 -1 -1 -1] dates/2/weekday
 dates/2: dates/2 + 8 - dates/2/weekday

  ;; Calculate the working / non-working days
  ;; --------------------------------

 working-days: (dates/2 - dates/1) / 7 * 5 + offset - hol-count
 if non [return (abs (date1 - date2)) - working-days]
 return working-days
]


That was fun -- thanks!
Sunanda.
-- 
To unsubscribe from the list, just send an email to 
lists at rebol.com with unsubscribe as the subject.

Reply via email to