Nth weekday meetups
MediumOnline Assessment
Expand a community hall's recurring bookings, such as "every second Tuesday", into the dates that fall inside a calendar window.
Each rule is a string "label ordinal weekday interval start", for example "board 2 Tue 1 2024-01-01". A rule occurs on the ordinal-th weekday of a month: ordinal is 1 to 5 (the 2nd Tuesday, the 5th Friday, ...) or last (the last such weekday of the month). Weekdays are written Mon Tue Wed Thu Fri Sat Sun.
- The rule applies to the month containing
startand then to everyinterval-th month after it (interval1 is every month, 3 is every third month, and so on). - A month that has no such occurrence (for instance a month with only four Fridays and ordinal
5) produces nothing. The occurrence is never moved to a different date. - An occurrence earlier than
startis not produced; one exactly onstartis. - Only occurrences with
window_start <= date <= window_endare reported (both ends inclusive), and any occurrence on a date listed inskipsis removed (for all rules).
Input: rules, a list of such strings; window_start and window_end, dates "YYYY-MM-DD"; and skips, a list of dates in the same format.
Output: a list of strings "YYYY-MM-DD label", one per remaining occurrence, ordered by date; occurrences on the same date follow the order of their rules in rules. If there are none, return [].
Example 1
- Input:
- [["board 2 Tue 1 2024-01-01","audit last Fri 3 2024-02-10"],"2024-01-01","2024-06-30",["2024-03-12"]]
- Output:
- ["2024-01-09 board","2024-02-13 board","2024-02-23 audit","2024-04-09 board","2024-05-14 board","2024-05-31 audit","2024-06-11 board"]
- Explanation
- "board" is the 2nd Tuesday of every month: Jan 9, Feb 13, Mar 12, Apr 9, May 14, Jun 11; March 12 is a skipped date, so it is removed. "audit" starts on 2024-02-10 and runs every 3 months (Feb, May, Aug...): the last Friday of February is Feb 23 and of May is May 31. Results are ordered by date.
Example 2
- Input:
- [["payday 5 Fri 1 2024-03-29","kickoff 1 Mon 2 2024-01-10"],"2024-01-01","2024-12-31",[]]
- Output:
- ["2024-03-04 kickoff","2024-03-29 payday","2024-05-06 kickoff","2024-05-31 payday","2024-07-01 kickoff","2024-08-30 payday","2024-09-02 kickoff","2024-11-04 kickoff","2024-11-29 payday"]
- Explanation
- "payday" is the 5th Friday of every month from 2024-03-29, a date that is itself the 5th Friday of March, so it counts. Months with only four Fridays produce nothing (the occurrence is not moved to the last Friday): that leaves May 31, Aug 30 and Nov 29. "kickoff" is the 1st Monday every 2 months from Jan 10 (Jan, Mar, May, ...): January's first Monday (Jan 1) is before the start date, so it is skipped, and the series continues with Mar 4, May 6, Jul 1, Sep 2 and Nov 4.
Example 3
- Input:
- [["zeta 1 Thu 5 2023-11-02","alpha 1 Thu 4 2023-12-01"],"2023-11-02","2024-04-04",[]]
- Output:
- ["2023-11-02 zeta","2023-12-07 alpha","2024-04-04 zeta","2024-04-04 alpha"]
- Explanation
- Both window ends are inclusive and the start date itself counts. "zeta" is the 1st Thursday every 5 months from Nov 2023 (Nov 2, then April 4); "alpha" is the 1st Thursday every 4 months from Dec 2023 (Dec 7, then April 4). On the shared date April 4, rules are listed in the order they appear in
rules: zeta before alpha.
Constraints
1 <= rules.length <= 20- Each rule is
"label ordinal weekday interval start"with a label of 1 to 12 lowercase letters,ordinalone of1to5orlast,weekdayone ofMon Tue Wed Thu Fri Sat Sun,1 <= interval <= 12, andstarta valid date from2000-01-01to2100-12-31 window_start <= window_end, both valid dates in the same range, at most 3,700 days apart;0 <= skips.length <= 100- All dates are written
YYYY-MM-DD