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.