05AB1E , 130 128 133 131 124 123 byte
ž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#
Tôi không nghĩ đến điều đó..
Đối với ngôn ngữ chơi gôn 05AB1E hoàn toàn không thành vấn đề cho dù đầu vào là .
hay -
. Tuy nhiên, 05AB1E không có bất kỳ nội dung nào cho các đối tượng hoặc tính toán Ngày. Nội dung duy nhất liên quan đến ngày mà nó có là năm / tháng / ngày / giờ / phút / giây / giây / giây.
Vì vậy, gần như tất cả các mã bạn thấy là các tính toán thủ công để chuyển sang ngày hôm sau và tính ngày trong tuần.
+5 byte do một phần tôi đã quên trong công thức của Zeller (năm 1 cho các tháng 1 và tháng 2) ..
Dùng thử trực tuyến hoặc Dùng thử trực tuyến với ngày tự xác định là 'hôm nay' .
Giải trình:
Bức tường văn bản đến.
Nói chung, mã theo mã giả sau:
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;
là một phần của chương trình 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;
và 3) Start an infinite loop:
là hướng thẳng trong chương trình 05AB1E:
0 # Push 0 to the stack
[ # Start an infinite loop
4) If(currentDate is NOT a Saturday and currentDate is NOT a Sunday):
là phần khó đầu tiên với tính toán thủ công. Vì 05AB1E không có nội dung ngày, nên chúng tôi sẽ phải tính toán Ngày trong tuần theo cách thủ công.
Công thức chung để làm điều này là:
h=(q+⌊13(m+1)5⌋+K+⌊K4⌋+⌊J4⌋−2J)mod7,
Trường hợp từ tháng 3 đến tháng 12:
- q làday của tháng (
[1, 31]
)
- m là 1-indexedmonth (
[3, 12]
)
- K là năm của thế kỷ (yearmod100 )
- J là thế kỷ 0 được lập chỉ mục (⌊year100⌋)
Và trong các tháng 1 và 2:
- q làday của tháng (
[1, 31]
)
- m là 1-indexedmonth+12 (
[13, 14]
)
- K là năm của thế kỷ cho năm trước ((year−1)mod100 )
- J là thế kỷ 0 được lập chỉ mục cho năm trước (⌊year−1100⌋)
Kết quả là vào ngày trong tuần h , trong đó 0 = Thứ Bảy, 1 = Chủ Nhật, ..., 6 = Thứ Sáu.
Nguồn: sự phù hợp của Zeller
Chúng ta có thể thấy điều này trong phần này của chương trình 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;
là thẳng về phía trước một lần nữa:
# 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
lại phức tạp hơn, vì chúng ta phải thực hiện thủ công. Vì vậy, điều này sẽ được mở rộng thành mã giả sau đây:
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;
Nguồn:
Thuật toán để xác định xem một năm có phải là năm nhuận hay không. (EDIT: Không còn phù hợp nữa, vì tôi sử dụng một phương pháp thay thế để kiểm tra năm nhuận đã lưu 7 byte.)
Thuật toán xác định số ngày trong một tháng.
6a) Integer isLeapYear = ...;
được thực hiện như thế này trong chương trình 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`
Cũng được sử dụng trong câu trả lời 05AB1E này của tôi , vì vậy có một số năm ví dụ được thêm vào để minh họa các bước.
6b) currentDate.month == 2 ?
và 6c) 28 + isLeapYear
được thực hiện như thế này:
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) :
và 6e) 31 - (currentDate.month - 1) % 7 % 2;
được thực hiện như thế này:
ë # 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):
được thực hiện như thế này:
‹ # 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;
được thực hiện như thế này:
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:
và 6i) nextDate.day = 1;
sau đó được thực hiện như thế này:
ë # 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;
và 6n) nextDate.year += 1;
sau đó được thực hiện như thế này:
ë # 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
Và cuối cùng ở 8) If(currentDate == parsed input-string):
và 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)