Hari minggu 29 Februari berikutnya


14

Tulis fungsi yang mengambil tanggal dan mengembalikan hari minggu 29 Februari berikutnya setelah tanggal itu.

  • Input adalah string dalam format ISO Extended: YYYY-MM-DD (mis. 27 Mei 2010 akan menjadi "2010-05-27").

  • Outputnya adalah string yang merupakan nama hari dalam seminggu (mis. "Senin"). Kapitalisasi tidak masalah, tetapi berikan nama lengkap dalam bahasa Inggris.

  • Jika tanggal yang diberikan adalah 29 Februari, maka kembalilah hari minggu 29 Februari berikutnya .

  • Gunakan perhitungan untuk Kalender Gregorian Proleptik (jadi, ia menggunakan perhitungan tahun kabisat Gregorian untuk seluruh panjangnya). Jangan khawatir tentang Kalender Julian atau ketika peralihan dari Julian ke Gregorian terjadi. Anggap saja Gregorian untuk semuanya.

  • Fungsi harus bekerja setidaknya untuk kisaran "0001-01-01" - "2100-01-01".

  • Jangan ragu untuk menggunakan pustaka standar apa pun yang disediakan oleh bahasa pilihan Anda, tetapi jangan gunakan pustaka pihak ke-3 kecuali jika Anda ingin memasukkan kode itu sebagai bagian dari solusi Anda.

  • Kode terpendek (karakter paling sedikit) menang.

Contoh:

  • 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"

(dan tidak, Anda tidak perlu menyebutkan fungsinya func)

Petunjuk:

  • Ingatlah bahwa tahun yang berakhir pada 00 yang tidak dapat dibagi oleh 400 bukan tahun kabisat.
  • 1 Januari 0001 adalah hari Senin.

Jawaban:


7

Windows PowerShell, 65

Cukup mudah.

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

Seperti biasa, kita dapat mengurangi dua byte jika kita bersedia menunggu lama sampai selesai:

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

Uji:

> '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

Sejarah:

  • 2011-02-18 00:06 (65) Upaya pertama.

Jalan apa yang diperlukan agar ini bisa berfungsi? Saya memiliki tanggal GnuWin di jalan saya, yang melanggar itu.
Peter Taylor

@ Peter: Mungkin berbenturan dengan date. Hapus saja GNUWin32 dari PATH dan itu akan berfungsi. Atau ubah dateke Get-Date(perilaku fallback semacam itu hanya berfungsi ketika tidak ada perintah yang ditemukan - untuk memeriksa, cukup gunakan gcm date). Bagaimanapun, saya tidak menganggap bahwa masalah khusus dengan skrip ini sebagai GNUWin32 bukan bagian dari instalasi Windows standar.
Joey

Alasan saya bertanya adalah karena saya sudah mencoba menggunakan get-datedan mendapatkan pesan kesalahan. Method invocation failed because [System.Management.Automation.PSObject] doesn't contain a method named 'op_Addition'.Apakah perlu PS2 atau .Net 4 atau sesuatu?
Peter Taylor

@ Peter: Saya mencoba PowerShell v2. .NET 4 tidak berperan karena PowerShell ditautkan ke 2.0 runtime. Bagaimanapun, seharusnya tidak ada PSObject yang kembali dari Get-Datetetapi a System.DateTime.
Joey

Sangat aneh. $d=Get-Date "0400-01-01"; $d++memberikan pesan kesalahan tentang ++tidak didefinisikan pada DateTime. Yang sama mengganti ++dengan +=1atau +="1"atau +='1'memberikan pesan kesalahan tentang PSObject. Dan hanya +"1"berfungsi.
Peter Taylor

5

Ruby 1.9, 85 karakter

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

Solusi mudah. Panggil fungsi dengan f[args].

  • Sunting: (87 -> 97) Memperbaiki 0001-01-01testcase.
  • Sunting 2: (97 -> 91) Date.parse memungkinkan menentukan tanggal reformasi kalender juga.
  • Sunting 3: (91 -> 87) Gunakan lambda sebagai ganti fungsi. Terima kasih Dogbert !
  • Sunting 4: (87 -> 85) Hapus spasi yang tidak perlu. Sekali lagi terima kasih, Dogbert !

4
Gagal testcase untuk "0001-01-01". Tanggal Ruby terlalu kuat, butuh tanggal Julian untuk diperhitungkan.
steenslag

@Ventero Apa yang dilakukan def *? Belum pernah melihatnya sebelumnya.
steenslag

@steenslag: Terima kasih, perbaiki testcase itu. def*hanya mendefinisikan fungsi yang disebut *. Dengan begitu saya tidak perlu spasi di antara defdan nama fungsi.
Ventero

1
Tidak bisakah Anda mendefinisikan lambda saja? a = -> {...}
Dogbert

1
Juga, tidak perlu ruang apa pun setelah strftime.
Dogbert

3

T-SQL 166 185 Karakter

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')

Saya sudah mengacaukan fungsi tanggal T-SQL, jadi saya pikir mengapa tidak ...

Solusi asli salah ...

Inilah yang sebenarnya harus saya lakukan agar strategi itu berhasil:

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')

Mengingat bahwa saya membuat overflow mengurangi 2 bulan dari 0001-01-01 bahkan jika saya memang menggunakan tipe data yang benar saya menyerah membuat sesuatu yang pendek dan valid untuk pertanyaan ini. O_o. Trixsy mempertanyakan.
mootinator

Saya suka melihat solusi T-SQL ini. :)
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");};

Anda dapat menyimpan 8 byte dengan menggunakan definisi fungsi normal:string f(string d){...}
Joey

.ToString("dddd")mencetak tanggal di lokasi saat ini, tidak dalam bahasa Inggris.
Joey

165 karakter => string f (string d) {var n = DateTime.Parse (d) .AddDays (307); while (! (DateTime.IsLeapYear (n.Year))) n = n.AddYears (1); return (DateTime baru (n.Tahun, 2,29)). DayOfWeek.ToString ();}
Stephan Schinkel

Selanjutnya ditingkatkan menjadi 127 karakter: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

Terima kasih Peter ... Versi sangat golf, 96 byte:

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

Versi lama, 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

SAMPEL I / O

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

mungkin harus mengatur TZ jika tidak ada zona waktu default yang ditetapkan, saya belajar cyberciti.biz/faq/… saat melakukan ini pada beberapa IDE online
Aman ZeeK Verma

1
Apakah Anda akan bermain golf ini? ; p Anda dapat mengganti semuanya sebelum baris terakhir dengani=0;d=;until [ `date -d"$1 $i days" +%m-%d` = "02-29" ];do((i++));done
Peter Taylor

:-) seperti yang telah kita bahas tentang kekasaran saya atas bash! ... Untuk beberapa alasan, saya tidak banyak bermain-main dengan bash .. mereka sangat rawan kesalahan! .. Terima kasih atas saran Anda .. diperbarui!
Aman ZeeK Verma

1
Rawness with bash bukan alasan untuk menggunakan nama variabel empat huruf: P
Peter Taylor

ya pak, saya mengerti maksud Anda.
Aman ZeeK Verma

2

Perl, tidak ada perpustakaan tanggal: 160 159 155

sub f {($ y, $ m) = split / - /, @ _ ​​[0], 2; $ y ++ if ($ m> '02 -28 '); $ y = ($ y + 3)% 400 >> 2; $ y + = $ y &&! ($ Y% 25); @ r = (Selasa, Rabu, Kamis, Jumat, Sabtu, Minggu, Minggu); @ r [(5 * $ y - ($ y / 25 & 3))% 7]. "Hari";}

Manfaat sebenarnya dari pustaka tanggal ini adalah mendorong panjangnya nama-nama hari itu kepada orang lain.

Di sisi lain, saya pikir ini adalah satu-satunya solusi sejauh ini yang berfungsi terlepas dari lokal.


2

DATE dan beberapa lem BASHy (90)

Fungsi:

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

Pengujian:

$ 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 Karakter

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";}

Lebih Jelas:

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";
}

Menulis di D sangat mudah, tetapi pasti tidak akan memenangkan kontes kode golf. Namun, di luar kode golf, saya lebih suka membuatnya mudah untuk menulis dan memahami tetapi lama daripada harus singkat tetapi sulit untuk menulis dan mengerti.


1

Java 8 - 252 karakter

Golf:

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());}}

Tidak Disatukan:

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());
    }
}

Saya menerima downvotes tetapi bisakah Anda menjelaskan "necro itu nyata" dan menautkan ke FAQ yang menjelaskan maksud Anda? Saya tidak berpikir saya akan menang tetapi saya pikir itu akan menarik untuk melihat bagaimana Java bisa melakukannya, esp. diberikan Java 8. Saya melihat golf kode memiliki "kelas berat" versus kompetisi langsung. Java jarang mengalahkan Ruby atau Python.
Michael Easter

OP melarang perpustakaan pihak ke-3, jadi pada tahun 2011, solusi Java akan menjadi tidak menyenangkan, karena orang tidak dapat menggunakan perpustakaan Joda Time yang populer. Namun, Java 8 (dirilis pada Maret 2014) berisi perpustakaan DateTime JSR-310 - en.wikipedia.org/wiki/… . Alasan saya adalah saya pikir Java 8 akan menyenangkan, dan berpotensi menarik bagi beberapa pembaca. (Jika Anda bukan salah satu dari mereka, oke: masih ada alasan untuk jabatan itu.)
Michael Easter

1

Rebol - 78

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

Tidak Disatukan:

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

Contoh penggunaan (dalam konsol 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);}

kerusakan

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): 1untuk tahun kabisat, yang 0lain
date(l): representasi teks lengkap dari hari dalam seminggu


0

GNU coreutils, 71 byte

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

Pencarian linear 8 tahun ke depan (kasus terburuk, diberikan 2096-02-29). Sed menemukan dan menampilkan garis pertama yang cocok dengan 29 Februari.

Saya terkejut menemukan bahwa t;d;:;qitu lebih pendek daripada pengujian untuk melihat apakah digit tetap (/[01]/d;q ), meskipun perintah dua kali lebih banyak.

Tes

Saya menambahkan tes tambahan untuk kasus sudut yang sulit:

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
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.