05AB1E , 130 128 133 131 124 124 123 octets
žežfžg)V0[Y`UÐ3‹12*+>13*5÷s3‹Xα©т%D4÷®т÷©4÷®·()ćsO7%2@+Y`т‰0Kθ4ÖUD2Qi\28X+ë<7%É31α}‹iY¬>0ëY1¾ǝDÅsD12‹i>1ë\1Dǝ¤>2}}ǝVYI'.¡Q#
Je suis hors de mon esprit..
Pour la langue de golf 05AB1E, peu importe que l'entrée soit avec .
ou-
. Cependant, 05AB1E n'a pas de commandes intégrées pour les objets Date ou les calculs. Le seul élément intégré concernant les dates dont il dispose est l'année / mois / jour / heures / minutes / secondes / microsecondes d'aujourd'hui.
Donc à cause de cela, la quasi-totalité du code que vous voyez sont des calculs manuels pour aller au lendemain et calculer le jour de la semaine.
+5 octets en raison d'une partie que j'ai oubliée dans la formule de Zeller (année 1 pour les mois de janvier et février) ..
Essayez-le en ligne ou essayez-le en ligne avec une date émulée auto-spécifiée de «aujourd'hui» .
Explication:
Mur de texte entrant.
En général, le code suit le pseudo-code suivant:
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;
fait partie du programme 05AB1E:
ž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;
et 3) Start an infinite loop:
sont simples dans le programme 05AB1E:
0 # Push 0 to the stack
[ # Start an infinite loop
4) If(currentDate is NOT a Saturday and currentDate is NOT a Sunday):
est la première partie difficile avec des calculs manuels. Comme 05AB1E n'a pas de date intégrée, nous devrons calculer le jour de la semaine manuellement.
La formule générale pour ce faire est:
h=(q+⌊13(m+1)5⌋+K+⌊K4⌋+⌊J4⌋−2J)mod7,
Où pour les mois de mars à décembre:
- q est leday du mois (
[1, 31]
)
- m est le 1-indexé month (
[3, 12]
)
- K est l'année du siècle ( yearmod100 )
- J est le siècle indexé sur 0 ( ⌊year100⌋)
Et pour les mois janvier et février:
- q est leday du mois (
[1, 31]
)
- m est le m indexémonth+12 (
[13, 14]
)
- K est l'année du siècle pour l'année précédente ((year−1)mod100 )
- J est le siècle indexé sur 0 pour l'année précédente (⌊year−1100⌋)
Il en résulte le jour de la semaine h , où 0 = samedi, 1 = dimanche, ..., 6 = vendredi.
Source: congruence de Zeller
Nous pouvons le voir dans cette partie du programme 05AB1E:
Y # Push variable `Y`
` # Push the day, month, and year to the stack
U # Pop and save the year in variable `X`
Ð # Triplicate the month
3‹ # Check if the month is below 3 (Jan. / Feb.),
# resulting in 1 or 0 for truthy/falsey respectively
12* # Multiply this 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
13* # Multiplied by 13
5÷ # Integer-divided by 5
s3‹ # Check if the month is below 3 again (resulting in 1 / 0)
Xα # Take the absolute difference with the year
© # Store this potentially modified year in the register
т% # 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;
est à nouveau simple:
# 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
est encore plus complexe, car nous devons le faire manuellement. Donc, cela sera étendu au pseudo-code suivant:
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:
algorithme pour déterminer si une année est une année bissextile. (EDIT: n'est plus pertinent, car j'utilise une méthode alternative pour vérifier les années bissextiles qui ont économisé 7 octets.)
Algorithme pour déterminer le nombre de jours dans un mois.
6a) Integer isLeapYear = ...;
se fait comme ceci dans le programme 05AB1E:
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`
Également utilisé dans ma réponse 05AB1E , il y a donc quelques années d'exemple qui sont ajoutées pour illustrer les étapes.
6b) currentDate.month == 2 ?
et 6c) 28 + isLeapYear
se font comme ceci:
D # Duplicate the month that is now the top of the stack
2Q # Check if it's equal to 2
i # And if it is:
\ # Remove the duplicated month from the top of the stack
28X+ # Add 28 and variable `X` (the isLeapYear) together
6d) :
et 6e) 31 - (currentDate.month - 1) % 7 % 2;
se font comme ceci:
ë # 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):
se fait comme ceci:
‹ # 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;
se fait comme ceci:
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:
et 6i) se nextDate.day = 1;
font alors comme ceci:
ë # Else:
Y # Push variable `Y`
1 # Push a 1
¾ # 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;
et 6n) se nextDate.year += 1;
font alors comme ceci:
ë # 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
Et enfin à 8) If(currentDate == parsed input-string):
et 9) 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)