With strict I/O and outputting NA
when the date goes beyond the given input month+year: 204 bytes:
"Y`т‰0Kθ4ÖUD<i\28X+ë<7%É31α}‹iY¬>0ëY1¾ǝDÅsD12‹i>1ë\1Dǝ¤>2}}ǝV"ˆ$”‚應…ä†ï€¿…Ë…ê†Ä…æ…Ì…Í……”#s#©1èk>Dˆ®н)V®2ô¦RvyθFNĀi¯н.V}[Y`UD3‹©12*+>₂*T÷®Xα©т%D4÷®т÷©4÷®·(O7%”ŒÍ‹Ó‹ŽŒ¹ŒêŒÛН”#yнkQ#¯н.V]YÂT‰J'-ýsÅs¯θÊi„NA
The cumbersome I/O and 05AB1E's lack of date builtins make for a pretty big program. 🙃
Try it online or verify all test cases.
With flexible I/O and just continue calculating instead of outputting NA
: 126 bytes:
"Y`т‰0Kθ4ÖUD<i\28X+ë<7%É31α}‹iY¬>0ëY1¾ǝDÅsD12‹i>1ë\1Dǝ¤>2}}ǝV"ˆ1šVvyθFNĀi¯н.V}[Y`UD3‹©12*+>₂*T÷®Xα©т%D4÷®т÷©4÷®·(O7%yнQ#¯н.V]Y
Two inputs in the formats [month,year]
and [[weekday2,amount2],[weekday1,amount1]]
, where month
is an integer 1-12
and weekday
are integers 0-6
for Saturday to Friday.
Outputs in the format [day,month,year]
.
Still pretty big with the manual calculations, but apparently more than 1/3rd of my top program's bytes are to deal with just the I/O formats.
Try it online.
Explanation (of the larger strict I/O version):
Step 0: Create a function to go to the next day, which we'll re-use later on (see this 05AB1E answer of mine for an in-depth explanation of how we're going to the next day manually of a given date):
"Y`т‰0Kθ4ÖUD<i\28X+ë<7%É31α}‹iY¬>0ëY1¾ǝDÅsD12‹i>1ë\1Dǝ¤>2}}ǝV"
# Push this string to act as function later on with an eval
ˆ # Add it to the global array†
† The reason I use the global array instead of a variable: I'm already using all three U/X
, V/Y
, and ©®
variable setters/getters in the actual manual date calculations.
Step 1: Extract the year and month from the input, and parse it as [1,m,y]
triplet-list:
$ # Push 1 and the input-string
”‚應…ä†ï€¿…Ë…ê†Ä…æ…Ì…Í……”
# Push dictionary string "January February March April May June July August September October November December"
# # Split it on spaces to a list
s # Swap so the input-string is at the top of the stack
# # Split it on spaces as well
© # Store this sextuple input-list in variable `®` (without popping)
1è # Pop and get the Month at (0-based) index 1
k # Get the (0-based) index of this month in the list
> # Increase it by 1 to a 1-based index
Dˆ # Add a copy to the global array as well
® # Push the input-list of variable `®` again
н # Pop and leave its first item (the year)
) # Wrap all three values into a list: [1,m,y]
V # Pop and store it in variable `Y`
Step 2: Parse the remainder of the input-string, and start looping:
® # Push the input-list from variable `®` again
2ô # Split it into parts of size 2
¦ # Remove the first part (the [year,"Month"])
R # Reverse the other two parts
v # For each over the pairs `y` in the pair:
yθ # Push the last item of the current pair (the amount of days)
F # Pop and inner loop that many times:
NĀi # If it's NOT the first iteration:
¯н.V # Go to the next day
# by evaluating the first item of the global array of step 0
} # Close the if-statement
[ # Start an inner infinite loop:
Step 3a: Calculate the DayOfWeek of the current date as [0,1,2,3,4,5,6]
for [Saturday,Sunday,Monday,Tuesday,Wednesday,Thursday,Friday]
respectively (see again this 05AB1E answer of mine for an in-depth explanation of how I calculate the Day of the Week manually of a given date):
Y`UD3‹©12*+>₂*T÷®Xα©т%D4÷®т÷©4÷®·(O7%
Step 3b+c: If this day is equal to the input-date of the current pair y
, stop the infinite loop. If not, go to the next day and continue looping.
”ŒÍ‹Ó‹ŽŒ¹ŒêŒÛН” # Push dictionary string "Saturday Sunday Monday Tuesday Wednesday Thursday Friday"
# # Split it on spaces to a list
yн # Push the first item of the current pair (the day)
k # Get its 0-based index in the list of weekdays
Q # Check whether it's equal to the calculated DayOfWeek from step 3a
# # If they're equal:
# # Stop the inner infinite loop
¯н.V # (Else) Go to the next day by evaluating step 0 again
Step 4: Format the resulting date to the desired output-format:
] # Close the three loops
Y # Push the resulting date `Y`
 # Bifurcate this triplet; short for Duplicate & Reverse copy
T‰J # Format the day/month with leading 0:
T‰ # Divmod each inner value by 10
J # Join each inner pair together
'-ý '# Join the triplet-list with "-" delimiter
s # Swap the triplet to the top of the stack again
Ås # Only leave its middle item (the month)
¯θ # Push the last item of the global array (the parsed input-month)
Êi # If they are NOT equal:
„NA # Push string "NA"
# (after which the top of the stack is output implicitly as result)
See this 05AB1E tip of mine (section How to use the dictionary?) to understand why ”‚應…ä†ï€¿…Ë…ê†Ä…æ…Ì…Í……”
is "January February March April May June July August September October November December"
and ”ŒÍ‹Ó‹ŽŒ¹ŒêŒÛН”
is "Saturday Sunday Monday Tuesday Wednesday Thursday Friday"
.
Both "ˆ$”‚應…ä†ï€¿…Ë…ê†Ä…æ…Ì…Í……”#I#1èk>
and ”ŒÍ‹Ó‹ŽŒ¹ŒêŒÛН”#yнk
can probably be golfed a bit with magic numbers of some sort, but since I suck at those and I also couldn't really be bothered in an answer already this big because of manual date calculations, the indexing into dictionary strings will do for now.
2021 November Monday 1 Tuesday 1
is asking for "the first Tuesday that is after the first Monday in November, 2021". You should mentally parse it as (2021 November) (Monday 1) (Tuesday 1) \$\endgroup\$