Ngày trong tuần của ngày 29 tháng 2 sắp tới


14

Viết một hàm mất một ngày và trả về ngày trong tuần của ngày 29 tháng 2 sau ngày đó.

  • Đầu vào là một chuỗi ở định dạng mở rộng ISO: YYYY-MM-DD (ví dụ: ngày 27 tháng 5 năm 2010 sẽ là "2010-05-27").

  • Đầu ra là một chuỗi là tên của ngày trong tuần (ví dụ: "Thứ hai"). Viết hoa không thành vấn đề, nhưng hãy đặt tên đầy đủ bằng tiếng Anh.

  • Nếu ngày đã cho là ngày 29 tháng 2, thì hãy trả lại ngày trong tuần của ngày 29 tháng 2 tiếp theo .

  • Sử dụng các tính toán cho Lịch Gregorian Proleptic (vì vậy, nó sử dụng các tính toán năm nhuận của Gregorian cho toàn bộ chiều dài của nó). Đừng lo lắng về Lịch Julian hoặc khi việc chuyển đổi từ Julian sang Gregorian xảy ra. Chỉ cần giả định Gregorian cho tất cả mọi thứ.

  • Chức năng phải hoạt động ít nhất trong phạm vi "0001-01-01" - "2100-01-01".

  • Vui lòng sử dụng bất kỳ thư viện tiêu chuẩn nào mà ngôn ngữ bạn chọn cung cấp, nhưng không sử dụng thư viện của bên thứ 3 trừ khi bạn muốn đưa mã đó vào như một phần của giải pháp.

  • Mã ngắn nhất (ít ký tự nhất) thắng.

Ví dụ:

  • func("0001-01-01") -> "Sunday"
  • func("1899-12-03") -> "Monday"
  • func("1970-01-01") -> "Tuesday"
  • func("1999-07-06") -> "Tuesday"
  • func("2003-05-22") -> "Sunday"
  • func("2011-02-17") -> "Wednesday"
  • func("2100-01-01") -> "Friday"

(và không, bạn không phải đặt tên hàm func)

Gợi ý:

  • Hãy nhớ rằng những năm kết thúc bằng 00 mà không thể chia hết cho 400 năm không phải là năm nhuận.
  • Ngày 1 tháng 1, 0001 là thứ Hai.

Câu trả lời:


7

Windows PowerShell, 65

Khá đơn giản.

filter f{for($d=date $_;($d+='1').day*$d.month-58){}$d.dayofweek}

Như thường lệ, chúng ta có thể tắt hai byte nếu chúng ta sẵn sàng chờ đợi một thời gian dài cho đến khi hoàn thành:

filter f{for($d=date $_;($d+=9).day*$d.month-58){}$d.dayofweek}

Kiểm tra:

> '0001-01-01','1899-12-03','1970-01-01','1999-07-06','2003-05-22','2011-02-17','2100-01-01'|f
Sunday
Monday
Tuesday
Tuesday
Sunday
Wednesday
Friday

Lịch sử:

  • 2011/02/18 00:06 (65) Nỗ lực đầu tiên.

Con đường nào là cần thiết để làm việc này? Tôi có ngày GnuWin trên con đường của mình, nó đang phá vỡ nó.
Peter Taylor

@Peter: Nó có thể đụng độ với date. Chỉ cần loại bỏ GNUWin32 khỏi PATH và nó sẽ hoạt động. Hoặc thay đổi datethành Get-Date(loại hành vi dự phòng đó chỉ hoạt động khi không tìm thấy lệnh nào - để kiểm tra, chỉ cần sử dụng gcm date). Dù sao, tôi không xem xét rằng một vấn đề cụ thể với tập lệnh này vì GNUWin32 không phải là một phần của bất kỳ cài đặt Windows tiêu chuẩn nào.
Joey

Lý do tôi hỏi là vì tôi đã thử sử dụng get-datevà nhận được thông báo lỗi Method invocation failed because [System.Management.Automation.PSObject] doesn't contain a method named 'op_Addition'.Nó có cần PS2 hoặc .Net 4 hay không?
Peter Taylor

@Peter: Tôi đã dùng thử PowerShell v2. .NET 4 không phát vào được vì PowerShell được liên kết với thời gian chạy 2.0. Trong mọi trường hợp, không nên có PSObject quay lại từ Get-Datea System.DateTime.
Joey

Nó rất kỳ lạ. $d=Get-Date "0400-01-01"; $d++đưa ra một thông báo lỗi về việc ++không được xác định trên DateTime. Điều này cũng thay thế ++bằng +=1hoặc +="1"hoặc +='1'cung cấp cho các thông báo lỗi về PSObject. Và chỉ +"1"hoạt động.
Peter Taylor

5

Ruby 1.9, 85 ký tự

f=->a{require"date";d=Date.parse(a,0,0)+1;d+=1until d.day*d.month==58;d.strftime"%A"}

Giải pháp đơn giản. Gọi hàm với f[args].

  • Chỉnh sửa: (87 -> 97) Đã sửa lỗi 0001-01-01testcase.
  • Chỉnh sửa 2: (97 -> 91) Date.parse cho phép chỉ định ngày cải cách lịch là tốt.
  • Chỉnh sửa 3: (91 -> 87) Sử dụng lambda thay vì chức năng. Cảm ơn Dogbert !
  • Chỉnh sửa 4: (87 -> 85) Xóa các khoảng trống không cần thiết. Cảm ơn một lần nữa, Dogbert !

4
Thất bại trong testcase cho "0001-01-01". Ngày của Ruby quá mạnh mẽ, phải tính đến ngày Julian.
steenslag

@Ventero Def * làm gì? Chưa bao giờ nhìn thấy nó trước đây.
steenslag

@steenslag: Cảm ơn, đã sửa cái testcase đó. def*chỉ định nghĩa một hàm gọi là *. Theo cách đó, tôi không cần khoảng trắng giữa defvà tên hàm.
Ventero

1
Bạn không thể chỉ định nghĩa một lambda thay thế? a = -> {...}
Dogbert

1
Ngoài ra, không cần bất kỳ không gian nào sau khi rời khỏi.
Dogbert

3

T-SQL 166 185 Ký tự

CREATE PROCEDURE f29 (@d DATETIME) AS
DECLARE @i int
SET @i=YEAR(DATEADD(M,-2,@d)+3)
SET @i=@i+(4-@i%4)
IF @i%100=0 AND @i%400<>0 SET @i=@i+4
SELECT DATENAME(W,CAST(@i AS CHAR)+'-2-29')

Tôi đã bị rối với các hàm ngày T-SQL, vì vậy tôi đã hiểu tại sao không ...

Giải pháp ban đầu không chính xác ...

Đây là những gì tôi thực sự phải làm để làm cho chiến lược đó hoạt động:

CREATE PROCEDURE f29 (@d DATE) AS
DECLARE @i int
SET @i = YEAR(@d)
BEGIN TRY 
SET @i=YEAR(DATEADD(D, 3, DATEADD(M,-2,@d)))
END TRY
BEGIN CATCH
END CATCH
SET @i=@i+(4-@i%4)
IF @i%100=0 AND @i%400<>0 SET @i=@i+4
SELECT DATENAME(W,CAST(@i AS CHAR)+'-2-29')

Cho rằng tôi tạo ra một phép trừ 2 tháng kể từ 0001-01-01 ngay cả khi tôi sử dụng đúng kiểu dữ liệu, tôi từ bỏ việc tạo ra một cái gì đó ngắn hợp lệ cho câu hỏi này. Ôi. Trixsy đặt câu hỏi.
mootinator

Tôi thích nhìn thấy các giải pháp T-SQL này. :)
Steve

3

C #, 176

Func<String,String>f=(d)=>{DateTime n;for(n=DateTime.Parse(d).AddDays(307);!(DateTime.IsLeapYear(n.Year));n=n.AddYears(1)){}return new DateTime(n.Year,2,29).ToString("dddd");};

Bạn có thể lưu 8 byte bằng cách sử dụng định nghĩa hàm thông thường:string f(string d){...}
Joey

.ToString("dddd")Tuy nhiên, in ngày ở miền địa phương hiện tại, không phải bằng tiếng Anh.
Joey

165 ký tự => chuỗi f (chuỗi d) {var n = DateTime.Pude (d) .AddDays (307); while (! (DateTime.IsLeapYear (n.Year))) n = n.AddYears (1); return (DateTime mới (n.Year, 2,29)). DayOfWeek.ToString ();}
Stephan Schinkel

Cải thiện hơn nữa thành 127 ký tự:string f(string d){var n=DateTime.Parse(d).AddDays(1);return DateTime.IsLeapYear(n.Year)&&n.DayOfYear==60?n.DayOfWeek+"":f(n+"");}
Patrik Westerlund

3

Bash, 96 byte

Cảm ơn Peter ... Phiên bản được đánh gôn cao, 96 byte:

i=1;until [ `date -d"$1 $i days" +%m-%d` = "02-29" ];do((i++));done
date -d "${1} ${i} days" +%A

Phiên bản cũ, 229 byte

#!/bin/bash
from=$1
i=1
while [ "$isFeb" = "" ] || [ "$is29" = "" ]
do
isFeb=`date -d "${from} ${i} days" | grep Feb`
is29=`date -d "${from} ${i} days" +%Y-%m-%d | grep "\-29"`
((i++))
done
((i--))
date -d "${from} ${i} days" +%A

MẪU I / O

:~/aman>./29Feb.sh 0001-01-01
Sunday
:~/aman>./29Feb.sh 1899-12-03
Monday
:~/aman>./29Feb.sh 1970-01-01
Tuesday

có thể phải đặt TZ nếu không có múi giờ mặc định được đặt, tôi đã học được cyberciti.biz/faq/NH khi thực hiện điều này trên một số IDE trực tuyến
Aman ZeeK Verma

1
Bạn đang đi chơi golf này? ; p Bạn có thể thay thế mọi thứ trước dòng cuối cùng bằngi=0;d=;until [ `date -d"$1 $i days" +%m-%d` = "02-29" ];do((i++));done
Peter Taylor

:-) như chúng ta đã thảo luận về sự thô sơ của tôi đối với bash! ... Vì một số lý do, tôi không quan tâm nhiều đến bash .. chúng rất dễ bị lỗi! .. Cảm ơn bạn đã đề xuất .. đã cập nhật!
Verman Aman ZeeK

1
Sự thô sơ với bash không phải là lý do để sử dụng tên biến gồm bốn chữ cái: P
Peter Taylor

vâng thưa ngài, tôi đã nhận được quan điểm của bạn
Aman ZeeK Verma

2

Perl, không có thư viện ngày: 160 159 155

phụ f {($ y, $ m) = split / - /, @ _ ​​[0], 2; $ y ++ if ($ m> '02 -28 '); $ y = ($ y + 3)% 400 >> 2; $ y + = $ y &&! ($ Y% 25); @ r = (Thứ Ba, Thứ Tư, Thứ Năm, Thứ Sáu, Thứ Bảy, Chủ Nhật, Thứ Hai); @ r [(5 * $ y - ($ y / 25 & 3))% 7]. "Ngày";}

Lợi ích thực sự của các thư viện ngày này là đẩy lùi độ dài tên của ngày cho người khác.

Mặt khác, tôi nghĩ rằng đây là giải pháp duy nhất cho đến nay hoạt động bất kể địa phương.


2

NGÀY và một số keo BASHy (90)

Chức năng:

f(){ while :;do $(date -d$1+1day +'set - %F %A 1%m%d');(($3==10229))&&break;done;echo $2;}

Kiểm tra:

$ for x in 0001-01-01 1899-12-03 1970-01-01 1999-07-06 2003-05-22 2011-02-17 2100-01-01 ; do f $x ; done
Sunday
Monday
Tuesday
Tuesday
Sunday
Wednesday
Friday

1

D: 175 ký tự

S f(S)(S s){auto d=Date.fromISOExtString(s)+days(1);while(d.month!=Month.feb||d.day!=29)d+=days(1);return["Sun","Mon","Tues","Wednes","Thurs","Fri","Sat"][d.dayOfWeek]~"day";}

Dễ đọc hơn:

S f(S)(S s)
{
    auto d = Date.fromISOExtString(s) + days(1);

    while(d.month != Month.feb || d.day != 29)
        d += days(1);

    return ["Sun", "Mon", "Tues", "Wednes", "Thurs", "Fri", "Sat"][d.dayOfWeek] ~ "day";
}

Rất dễ dàng để viết bằng D, nhưng chắc chắn sẽ không giành chiến thắng trong bất kỳ cuộc thi đánh gôn nào. Tuy nhiên, bên ngoài môn đánh gôn, tôi muốn viết và hiểu nó dễ hơn nhưng lâu hơn là viết ngắn gọn nhưng khó viết và khó hiểu.


1

Java 8 - 252 ký tự

Chơi gôn

import java.time.*;
import java.time.format.*;
public class S{public static void main(String[] a){LocalDate d=LocalDate.parse(a[0]).plusDays(1);while(d.getMonthValue()!=2||d.getDayOfMonth()!=29){d=d.plusDays(1);}System.out.println(d.getDayOfWeek());}}

Ung dung:

import java.time.*;
import java.time.format.*;
public class S {
    public static void main(String[] a) {
        LocalDate d = LocalDate.parse(a[0]).plusDays(1);

        while(d.getMonthValue()!=2 || d.getDayOfMonth()!=29) {
            d = d.plusDays(1);
        }
        System.out.println(d.getDayOfWeek());
    }
}

Tôi chấp nhận downvote nhưng bạn có thể vui lòng giải thích "necro là có thật" và liên kết đến Câu hỏi thường gặp giải thích quan điểm của bạn không? Tôi không nghĩ mình sẽ thắng nhưng nghĩ sẽ rất thú vị khi xem Java có thể làm như thế nào, đặc biệt. đưa ra Java 8. Tôi xem golf mã là có "hạng cân" so với một cuộc thi hoàn toàn. Java sẽ hiếm khi đánh bại Ruby hoặc Python hoàn toàn.
Michael Phục sinh

OP cấm các thư viện bên thứ 3, vì vậy vào năm 2011, một giải pháp Java sẽ rất khó chịu, vì người ta không thể sử dụng thư viện Joda Time nổi tiếng. Tuy nhiên, Java 8 (được phát hành vào tháng 3 năm 2014) chứa thư viện DateTime của JSR-310 - en.wikipedia.org/wiki/ . Lý do của tôi là tôi nghĩ Java 8 sẽ thú vị và có khả năng thú vị với một số độc giả. (Nếu bạn không phải là một trong số đó, tốt thôi: vẫn còn một lý do cho bài đăng.)
Michael Easter

1

Nổi loạn - 78

f: func[d][system/locale/days/(until[d: d + 1 d/day * d/month = 58]d/weekday)]

Ung dung:

f: func [d] [
    system/locale/days/(
        until [
            d: d + 1
            d/day * d/month = 58
        ]
        d/weekday
    )
]

Ví dụ sử dụng (trong bảng điều khiển Rebol):

>> f 0001-01-01
== "Sunday"

>> f 2100-01-01
== "Friday"

1

PHP, 104 byte

function f($s){for($y=$s-(substr($s,5)<"02-29");!date(L,$t=strtotime(++$y."-2-1")););return date(l,$t);}

phá vỡ

for($y=$s-;                 // "-" casts the string to int; decrement year if ...
    (substr($s,5)<"02-29")  // ... date is before feb 29
    !date(L,                        // loop while incremented $y is no leap year
        $t=strtotime(++$y."-2-1")   // $t=feb 01 in that year (same weekday, but shorter)
    );
);
return date(l,$t);          // return weekday name of that timestamp

date(L): 1cho năm nhuận, 0khác
date(l): đại diện toàn văn bản của ngày trong tuần


0

GNU coreutils, 71 byte

f(){
seq -f "$1 %gday" 2921|date -f- +'%m%d%A'|sed 's/0229//;t;d;:;q'
}

Tìm kiếm tuyến tính trong 8 năm tiếp theo (trường hợp xấu nhất, được đưa ra 2096-02-29). Sed tìm và xuất ra dòng đầu tiên phù hợp với ngày 29 tháng 2.

Tôi đã ngạc nhiên khi thấy rằng nó t;d;:;qngắn hơn so với thử nghiệm để xem liệu các chữ số có còn ( /[01]/d;q) hay không, mặc dù có nhiều gấp đôi số lệnh.

Xét nghiệm

Tôi đã thêm một dòng thử nghiệm cho các trường hợp góc khó:

for i in 0001-01-01.Sunday 1899-12-03.Monday \
    1970-01-01.Tuesday     1999-07-06.Tuesday \
    2003-05-22.Sunday      2011-02-17.Wednesday 2100-01-01.Friday \
    2000-02-28.Tuesday     2000-02-29.Sunday    2000-03-01.Sunday   2096-02-29.Friday
do
    printf "%s => %s (expected %s)\n" ${i%.*} $(f ${i%.*}) ${i#*.}
done
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.