Skip to main content
We’ve updated our Terms of Service. A new AI Addendum clarifies how Stack Overflow utilizes AI interactions.
Code Golf

Return to Revisions

14 of 14
Another -1 byte (2Q to <)
Kevin Cruijssen
  • 136.2k
  • 14
  • 154
  • 394

05AB1E, (削除) 130 (削除ここまで) (削除) 128 (削除ここまで) (削除) 133 (削除ここまで) (削除) 131 (削除ここまで) (削除) 124 (削除ここまで) (削除) 123 (削除ここまで) (削除) 122 (削除ここまで) (削除) 121 (削除ここまで) 120 bytes

žežfžg)V0[Y`UD3‹©12*+>2*T÷®Xα©т%D4÷®т÷©4÷®·()ćsO7%2@+Y`т‰0Kθ4ÖUD<i28円X+ë<7%É31α}‹iY¬>0ëY13⁄4ǝDÅsD12‹i>1ë1円Dǝ¤>2}}ǝVYI'.¡Q#

I'm out of my mind..

For the golfing language 05AB1E it doesn't matter at all whether the input is with . or -. However, 05AB1E doesn't have any builtins for Date objects or calculations. The only builtin regarding dates it has is today's year/month/day/hours/minutes/seconds/microseconds.

So because of that, almost all of the code you see are manual calculations to go to the next day, and calculating the day of the week.

+5 bytes due to a part I forgot in Zeller's formula (year-1 for months January and February)..
-1 byte thanks to @Grimmy, by changing \$\left\lfloor{\frac{13(m+1)}{5}}\right\rfloor\$ to \$\left\lfloor{\frac{26(m+1)}{10}}\right\rfloor\$ in the code, since 05AB1E has single-byte builtins for both 26 and 10 (being 2 and T respectively), as opposed to the 3 bytes of 13 and 5.

Try it online or Try it online with an emulated self-specified date of 'today'.

Explanation:

Wall of text incoming.

In general, the code follows the following pseudo-code:

1 Date currentDate = today;
2 Integer counter = 0;
3 Start an infinite loop:
4* If(currentDate is NOT a Saturday and currentDate is NOT a Sunday):
5 Counter += 1;
6* currentDate += 1; // Set currentDate to the next day in line
7 If(currentDate == parsed input-string):
8 Stop the infinite loop, and output the counter

1) Date currentDate = today; is this part of the 05AB1E program:

že # Push today's day
 žf # Push today's month
 žg # Push today's year
 ) # Wrap them into a single list
 V # Pop and store this list in variable `Y`

2) Integer counter = 0; and 3) Start an infinite loop: are straight-forward in the 05AB1E program:

0 # Push 0 to the stack
 [ # Start an infinite loop

4) If(currentDate is NOT a Saturday and currentDate is NOT a Sunday): is the first hard part with manual calculations. Since 05AB1E has no Date builtins, we'll have to calculate the Day of the Week manually.

The general formula to do this is:

$${\displaystyle h=\left(q+\left\lfloor{\frac{13(m+1)}{5}}\right\rfloor+K+\left\lfloor{\frac{K}{4}}\right\rfloor+\left\lfloor{\frac{J}{4}}\right\rfloor-2J\right){\bmod{7}}}$$

Where for the months March through December:

  • \$q\$ is the \$day\$ of the month ([1, 31])
  • \$m\$ is the 1-indexed \$month\$ ([3, 12])
  • \$K\$ is the year of the century (\$year \bmod 100\$)
  • \$J\$ is the 0-indexed century (\$\left\lfloor {\frac {year}{100}}\right\rfloor\$)

And for the months January and February:

  • \$q\$ is the \$day\$ of the month ([1, 31])
  • \$m\$ is the 1-indexed \$month + 12\$ ([13, 14])
  • \$K\$ is the year of the century for the previous year (\$(year - 1) \bmod 100\$)
  • \$J\$ is the 0-indexed century for the previous year (\$\left\lfloor {\frac {year-1}{100}}\right\rfloor\$)

Resulting in in the day of the week \$h\$, where 0 = Saturday, 1 = Sunday, ..., 6 = Friday.
Source: Zeller's congruence

We can see this in this part of the 05AB1E program:

Y # Push variable `Y`
 ` # Push the day, month, and year to the stack
 U # Pop and save the year in variable `X`
 D # Duplicate the month
 3‹ # Check if the month is below 3 (Jan. / Feb.),
 # resulting in 1 or 0 for truthy/falsey respectively
 © # Store this in variable `®` (without popping)
 12* # Multiply it by 12 (either 0 or 12)
 + # And add it to the month
 # This first part was to make Jan. / Feb. 13 and 14
> # Month + 1
 2* # Multiplied by 26
 T÷ # Integer-divided by 10
® # Push month<3 from variable `®` again
 Xα # Take the absolute difference with the year
 © # Store this potentially modified year as new `®` (without popping)
 т% # mYear modulo-100
D4÷ # mYear modulo-100, integer-divided by 4
®т÷©4÷ # mYear integer-divided by 100, and then integer-divided by 4
®·( # mYear integer-divided by 100, doubled, and then made negative
) # Wrap the entire stack into a list
 ć # Extract the head (the counter variable that was also on the stack)
 s # Swap so the calculated values above are as list at the top
 O # Take the sum of this entire list
 7% # And then take modulo-7 to complete the formula,
 # resulting in 0 for Saturday, 1 for Sunday, and [2, 6] for [Monday, Friday]
2@ # Check if the day is greater than or equal to 2 (so a working day)

5) Counter += 1; is straight-forward again:

 # The >=2 check with `2@` results in either 1 for truthy and 0 for falsey
+ # So just adding it to the counter variable is enough

6) currentDate += 1; // Set currentDate to the next day in line is again more complex, because we have to do it manually. So this will be expanded to the following pseudo-code:

a Integer isLeapYear = ...;
b Integer daysInCurrentMonth = currentDate.month == 2 ?
c 28 + isLeapYear
d :
e 31 - (currentDate.month - 1) % 7 % 2;
f If(currentDate.day < daysInCurrentMonth):
g nextDate.day += 1;
h Else:
i nextDate.day = 1;
j If(currentDate.month < 12):
k nextDate.month += 1;
l Else:
m nextDate.month = 1;
n nextDate.year += 1;

Sources:
(削除) Algorithm for determining if a year is a leap year. (削除ここまで) (EDIT: No longer relevant, since I use an alternative method to check leap years which saved 7 bytes.)
Algorithm for determining the number of days in a month.

6a) Integer isLeapYear = ...; is done like this in the 05AB1E program:

Y # Push variable `Y`
 ` # Push the days, month and year to the stack
 т‰ # Divmod the year by 100
 0K # Remove all items "00" (or 0 when the year is below 100)
 θ # Pop the list, and leave the last item
 4Ö # Check if this number is visible by 4
 U # Pop and save the result in variable `X`

Also used in this 05AB1E answer of mine, so there some example years are added to illustrate the steps.

6b) currentDate.month == 2 ? and 6c) 28 + isLeapYear are done like this:

D # Duplicate the month that is now the top of the stack
 < # Decrease it by 1
 i # And if this is now 1 (thus February):
 \ # Remove the duplicated month from the top of the stack
 28X+ # Add 28 and variable `X` (the isLeapYear) together

6d) : and 6e) 31 - (currentDate.month - 1) % 7 % 2; are done like this:

ë # Else:
 < # Month - 1
 7% # Modulo-7
 É # Is odd (shortcut for %2)
 31 # Push 31
 α # Absolute difference between both
} # Close the if-else

6f) If(currentDate.day < daysInCurrentMonth): is done like this:

‹ # Check if the day that is still on the stack is smaller than the value calculated
 i # And if it is:

6g) nextDate.day += 1; is done like this:

Y # Push variable `Y`
 ¬ # Push its head, the days (without popping the list `Y`)
 > # Day + 1
 0 # Push index 0
 # (This part is done after the if-else clauses to save bytes)
}} # Close the if-else clauses
 ǝ # Insert the day + 1 at index 0 in the list `Y`
 V # Pop and store the updated list in variable `Y` again

6h) Else: and 6i) nextDate.day = 1; are then done like this:

ë # Else:
 Y # Push variable `Y`
 1 # Push a 1
 3⁄4 # Push index 0
 ǝ # Insert 1 at index 0 (days part) in the list `Y`

6j) If(currentDate.month < 12)::

D # Duplicate the list `Y`
 Ås # Pop and push its middle (the month)
 D12‹ # Check if the month is below 12
 i # And if it is:

6k) nextDate.month += 1;:

> # Month + 1
 1 # Push index 1
 # (This part is done after the if-else clauses to save bytes)
}} # Close the if-else clauses
 ǝ # Insert the month + 1 at index 1 in the list `Y`
 V # Pop and store the updated list in variable `Y` again

6l) Else:, 6m) nextDate.month = 1; and 6n) nextDate.year += 1; are then done like this:

ë # Else:
 \ # Delete the top item on the stack (the duplicated month)
 1 # Push 1
 D # Push index 1 (with a Duplicate)
 ǝ # Insert 1 at index 1 (month part) in the list `Y`
 ¤ # Push its tail, the year (without popping the list `Y`)
 > # Year + 1
 2 # Index 2
 # (This part is done after the if-else clauses to save bytes)
}} # Close the if-else clauses
 ǝ # Insert the year + 1 at index 2 in the list `Y`
 V # Pop and store the updated list in variable `Y` again

And finally at 7) If(currentDate == parsed input-string): and 8) Stop the infinite loop, and output the counter:

Y # Push variable `Y`
 I # Push the input
 '.¡ '# Split it on dots
 Q # Check if the two lists are equal
 # # And if they are equal: stop the infinite loop
 # (And output the top of the stack (the counter) implicitly)
Kevin Cruijssen
  • 136.2k
  • 14
  • 154
  • 394

AltStyle によって変換されたページ (->オリジナル) /