Temukan hari Minggu terakhir di setiap bulan pada tahun tertentu


21

Solusi F # dikenal di dalam 140 karakter , dan ini adalah masalah Kode Rosetta .

Hasil yang diperlukan pada stdout atau dalam variabel string untuk tahun input 2014:

2014-01-26 2014-02-23 2014-03-30 2014-04-27 2014-05-25 2014-06-29 2014-07-27 2014-08-31 2014-09-28 2014-10-26 2014-11-30 2014-12-28

Seperti yang diminta, untuk tahun 1900:

1900-01-28 1900-02-25 1900-03-25 1900-04-29 1900-05-27 1900-06-24 1900-07-29 1900-08-26 1900-09-30 1900-10-28 1900-11-25 1900-12-30

Dan 2000:

2000-01-30 2000-02-27 2000-03-26 2000-04-30 2000-05-28 2000-06-25 2000-07-30 2000-08-27 2000-09-24 2000-10-29 2000-11-26 2000-12-31

Ditempatkan karena kurma tampaknya memunculkan kecanggungan di sebagian besar bahasa. Lebih dari mengizinkan perpustakaan tanggal, saya berharap untuk melihatnya! Tetapi jika di luar bahasa dasar, nyatakan dalam nama posting (misalnya C # + Jon Skeet's NodaTime).

Klarifikasi:

  • Rentang tahun 1900 hingga 3015
  • Kalender Gregorian
  • Jika tidak penting, apa pun yang konvensional untuk UK / London.
  • Sebuah program yang mengambil alih commandline atau stdin baik-baik saja, menghasilkan hasilnya menjadi stdout
  • Fungsi mengambil nilai untuk tahun itu dan mengembalikan string juga baik-baik saja.

Tidak ada celah standar . Menantikan solusi APL, J, K, dan melihat beberapa perpustakaan tanggal baru.


@ Sp3000 - 1752 bisa sangat canggung :-)
squeamish ossifrage

@ MartinBüttner: Harap gunakan perpustakaan tanggal, telah mengedit pertanyaan untuk meminta orang menyatakan yang mereka gunakan dengan bahasa.
Phil H

1
Anda harus menentukan rentang tahun yang merupakan input yang valid, dan pertimbangan tentang adopsi Gregorian. (Yaitu jika rentang tahun termasuk sebelum 1930 maka Anda harus menentukan bahwa kalender Gregorian harus digunakan untuk seluruh rentang, terlepas dari lokal; atau bahwa output dapat bervariasi berdasarkan lokal; atau Anda harus memberikan batas waktu sebelum mana kalender Julian harus digunakan dan menguji kasus selama tiga tahun sekitar pergantian tersebut).
Peter Taylor

1
@squeamishossifrage: Saya sudah membatasi untuk 1900 dan Gregorian, karena saya lebih suka menghindari proyek penelitian untuk menetapkan spesifikasi ...
Phil H

1
@ Adám: Maaf membuat Anda menunggu begitu lama untuk balasan :) Ya memang.
Phil H

Jawaban:


1

Dyalog APL dengan kal dari dfns , 19 byte

Lebih baik terlambat daripada tidak sama sekali!

Anjuran untuk tahun, mengembalikan daftar tanggal dalam format tttt tttt .

⎕{⍺⍵,2↑⊢⌿cal⍺⍵}¨⍳12

masukan numerik dan biarkan itu menjadi argumen kiri ke

{... fungsi anonim (ditemukan di bawah) diterapkan untuk masing-masing

⍳12 angka dari 1 hingga 12 (bulan-bulan)

Fungsi anonim di atas adalah sebagai berikut:

⍺⍵, tambahkan argumen kiri dan kanan (mis. tahun dan bulan) ke

2↑ dua karakter pertama

⊢⌿ baris paling bawah dari

cal kalender untuk

⍺⍵ argumen kiri dan argumen kanan (tahun dan bulan)

TryAPL online:

  1. Kembali ke halaman ini setelah mengklik di sini untuk mengimpor caldan dependensinya.

  2. Klik di sini untuk menjalankan test case.


Sangat bagus. Pernah berharap untuk perpustakaan APL yang mengerti apa artinya tanggal, tetapi kal masuk akal!
Phil H

@ Tanggal dan hari FILH ?
Adem

1
@ PhilHH Ada juga namespace Tanggal dari MiServer.
Adem

1
@PhilH Dan dyalic dyalic APL primitif + - < = dan bekerja dengan objek tanggal Net .
Adem

7

Ruby, 91 + 6 = 97

#!ruby -prdate
$_=(Date.new(y=$_.to_i)...Date.new(y+1)).select(&:sunday?).chunk(&:mon).map{|k,v|v[-1]}*' '

Berfungsi dengan cukup baik. select(&:sunday?)cukup, dan mengejutkan, *' 'apakah semua format dengan sendirinya.


Trik yang bagus! Anda dapat menyimpan tiga karakter lagi menggunakan chunkbukan group_by.
Cristian Lupascu

Jadi saya bisa, baik.
histokrat

6

Bash 4.x + ncal, 57

Jika pemisah baris baru OK, bukan spasi, maka kita dapat menghapus -nsakelar dan mengekor spasi dari echopernyataan. Dan saya kira itu akan tetap bekerja tanpa shebang, jadi saya menghapusnya juga:

for i in {01..12};{ echo "$1-$i-`ncal $i $1|tail -c-3`";}

Skrip asli (73 byte):

#!/bin/bash
for i in {01..12};{ echo -n "$1-$i-`ncal $i $1|tail -c-3` ";}

Pemakaian:

$ bash sundays.sh 2014
2014-01-26
2014-02-23
2014-03-30
2014-04-27
2014-05-25
2014-06-29
2014-07-27
2014-08-31
2014-09-28
2014-10-26
2014-11-30
2014-12-28
$

Catatan: Versi Bash sebelum 4.0 akan menghilangkan nol terkemuka dari bulan. Ini dapat diperbaiki dengan penambahan 5 karakter dengan mengubah {01..12}ke `seq -w 1 12)`. Juga, tail -c-3dapat menyebabkan masalah pada beberapa sistem di mana output ncalmenyertakan spasi tambahan, tapi saya tidak mengetahui ada yang melakukannya.


1
Apakah perbedaannya benar-benar terkait dengan Darwin, bukan hanya versi Bash? Telah ditambahkan di Bash 4.0 (meskipun ada beberapa bug di dalamnya nanti). Bagaimanapun, 1 karakter masih bisa dihindarkan dengan menggunakan `…`alih-alih kebiasaan yang baik $(…).
manatwork

Ah, bisa jadi. Darwin mengatakan menggunakan versi 3.2.53; Debian menggunakan 4.1.5.
squeamish ossifrage

@manatwork PS Hanya perhatikan komentar Anda tentang back-ticks. Tangkapan yang bagus, terima kasih!
ossifrage mual

Saya tidak berpikir Anda perlu menghitung #!/bin/bashuntuk tujuan bermain golf.
Trauma Digital

@ DigitalTrauma Itu bagus. Sepertinya saya bisa menggunakan jeda baris daripada spasi juga. Turun ke 57 byte sekarang :-)
squeamish ossifrage

6

IBM DFSORT, 11 3 baris dengan 71, 72 atau 80 karakter

 OPTION COPY 
 OUTFIL REPEAT=12,OVERLAY=(5:SEQNUM,2,ZD,5,2,1,8,Y4T,LASTDAYM,TOJUL=Y4T*
 ,9,7,Y4T,ADDDAYS,+1,TOJUL=Y4T,1:16,7,Y4T,PREVDSUN,TOGREG=Y4T(-),12X) 

Dua jawaban dengan format output berbentuk kolom telah teruji oleh waktu. Itu memberi saya "loop", semacam, di bahwa pada OUTFIL REPEAT = menyalin catatan saat ini yang berkali-kali.

Teknik yang berbeda untuk mendapatkan nilai, yang tampaknya lebih lama tetapi lebih pendek karena saya tidak dapat menemukan cara tanpa syarat untuk berurusan dengan catatan ke-12 berada di tahun berikutnya, dan menjadikannya syarat bersyarat termasuk IFTHEN=(WHEN=, dua kali, dan beberapa hal lainnya. Keuntungan pada ayunan (bulan pertama adalah cara paling sederhana untuk melakukannya) sangat kehilangan bundaran (persyaratan sintaksis tertentu).

Ini menggunakan fungsi inbuilt (semua fungsi dalam DFSORT adalah inbuilt) untuk menemukan hari terakhir bulan itu. Kemudian tambahkan satu hari (fungsi) untuk mendapatkan yang pertama dari bulan berikutnya dan menggunakan fungsi PREVDSUN untuk mendapatkan hari Minggu sebelumnya (yang akan selalu menjadi hari Minggu terakhir di bulan sebelumnya, seperti sebelumnya).

Ketika mengubah tahun (input) menjadi tanggal yang valid, nomor urut dua digit digunakan untuk bulan itu, dan nilai itu juga disalin untuk hari itu, karena titik awal tidak masalah selama valid, seperti kita setelah hari terakhir bulan pada awalnya: 5,2lebih pendek dari C'01'.

Inilah detailnya:

OPTION COPY - menyalin file input ke output

OUTFIL - untuk memungkinkan beberapa file output, dengan pemilihan dan pemformatan yang berbeda, menghasilkan laporan yang diformat. Digunakan dalam preferensi untuk yang lebih pendek INRECkarena penggunaan REPEAT=.

REPEAT = 12 - menghasilkan 12 salinan dari setiap catatan. Dalam contoh ini, hanya ada satu catatan input (tidak seperti versi sebelumnya) karena SEQNUM.

5: - mulai di kolom 5 pada catatan.

SEQNUM, 2, ZD - nomor urut, standar untuk mulai dari satu, dua digit, "desimal dikategorikan" (untuk unsigned, yang akan menjadi, sama dengan karakter).

1,8 - salin byte 1 untuk panjang 8 ke lokasi saat ini (9). Ini karena Y4T perlu melihat bahwa 8, jika tidak format tanggal yang berbeda akan digunakan.

Y4T - tanggal format ccyymmdd (karena 8 tepat di depannya).

LASTDAYM - Hari terakhir Bulan (juga dimungkinkan dari Minggu, Kwartal dan Tahun).

TOJUL = - konversi tanggal keluaran untuk fungsi tanggal (TOJUL adalah satu karakter kurang dari TOGREG)

9,7 - sekarang 7 lama, Y4T akan menjadi CCYYDDD.

ADDDAYS - menambahkan beberapa hari, menyesuaikan secara otomatis jika masuk ke bulan / tahun berikutnya (bisa juga ADDMONS dan ADDYEARS)

PREVDSUN - tanggal Julian datang, Minggu sebelumnya berlokasi, TOGREG untuk mendapatkan format keluaran yang benar, dengan pemisah "-" (bisa apa saja yang Anda suka sebagai pemisah)

12X - kosong untuk membersihkan kekacauan yang memungkinkan kami melakukannya dengan cara yang singkat

Output dari di atas, untuk 2014, adalah:

2014-01-26
2014-02-23
2014-03-30
2014-04-27
2014-05-25
2014-06-29
2014-07-27
2014-08-31
2014-09-28
2014-10-26
2014-11-23
2014-12-28

Diperlukan sesuatu untuk memberi tahu SORT apa yang harus dilakukan. Tidak ada standar. OPTION COPYadalah yang terpendek, SORT FIELDS=COPYsetara tetapi lebih lama.

Pekerjaan itu sendiri dilakukan kali ini di OUTFIL(untuk memungkinkan penggunaan REPEAT). Kode kerja bisa dibilang ada di antara 160 (2 * 80), 144 (2 * 72), 140 (72 + 69), atau 138 (70 + 68) (tidak termasuk blanko terkemuka, lanjutan paksa dan trailing blank).

Mengingat bahwa penerima harus tahu apa yang mereka lakukan, saya pikir saya dapat mengatakan bahwa kode DFSORT mencantumkan hari Minggu terakhir setiap bulan untuk setiap tahun mulai tahun 1900 (akan berjalan dari tahun 0001, tapi saya menghindari penelitian sebagai well) hingga 9999 (meskipun DFSORT mendukung tahun hingga 9999, solusi sebelumnya tidak akan berfungsi di tahun 9999 karena tanggal ke-12 masuk ke tahun berikutnya) dapat di-Tweet.

Mengapa kodenya begitu panjang, jika ada fungsi inbuilt yang tepat?

Definisi bidang adalah fana. Bidang hanya didefinisikan sebagai lokasi tertentu dalam data (yang merupakan catatan) untuk segera digunakan. Dengan kata lain, bidang tidak didefinisikan seperti itu, tetapi didefinisikan untuk setiap penggunaan dan hanya untuk digunakan. Fungsi tanggal perlu mengetahui format tanggal mana yang digunakan untuk sumber, dan output harus dalam format tanggal, sehingga harus ditentukan.

Sekarang kita punya kencan Julian .... TBC?


 OPTION COPY 
 INREC OVERLAY=(1,4,C'0201',1,8,1,8,1,8,1,8,1,8,1,8,1,8,1,8,1,8,1,8,1,8*
 ,94:C'1',89:1,4,ZD,ADD,+1,ZD,LENGTH=4,14:C'3',22:C'4',30:C'5',38:C'6',*
 46:C'7',54:C'8',62:C'9',69:C'10',77:C'11',85:C'12',127:X,89,8,Y4T,PREV*
 DSUN,TOGREG=Y4T(-),116:X,81,8,Y4T,PREVDSUN,TOGREG=Y4T(-),105:X,73,8,Y4*
 T,PREVDSUN,TOGREG=Y4T(-),94:X,65,8,Y4T,PREVDSUN,TOGREG=Y4T(-),83:X,57,*
 8,Y4T,PREVDSUN,TOGREG=Y4T(-),72:X,49,8,Y4T,PREVDSUN,TOGREG=Y4T(-),61:X*
 ,41,8,Y4T,PREVDSUN,TOGREG=Y4T(-),50:X,33,8,Y4T,PREVDSUN,TOGREG=Y4T(-),*
 39:X,25,8,Y4T,PREVDSUN,TOGREG=Y4T(-),28:X,17,8,Y4T,PREVDSUN,TOGREG=Y4T*
 (-),17:X,09,8,Y4T,PREVDSUN,TOGREG=Y4T(-),1:1,8,Y4T,PREVDSUN,TOGREG=Y4T*
 (-),11:X,18,120,6X) 

Membutuhkan beberapa JCL

//LASTSUNG EXEC PGM=SORT 
//SYSOUT   DD SYSOUT=* 
//SORTOUT  DD SYSOUT=* 
//SYSIN    DD * 

Dan file input (baris lain dari JCL dan tiga item instream data):

//SORTIN DD *
2014 
1900 
2000 

Menghasilkan:

2014-01-26 2014-02-23 2014-03-30 2014-04-27 2014-05-25 2014-06-29 2014-07-27 2014-08-31 2014-09-28 2014-10-26 2014-11-30 2014-12-28
1900-01-28 1900-02-25 1900-03-25 1900-04-29 1900-05-27 1900-06-24 1900-07-29 1900-08-26 1900-09-30 1900-10-28 1900-11-25 1900-12-30
2000-01-30 2000-02-27 2000-03-26 2000-04-30 2000-05-28 2000-06-25 2000-07-30 2000-08-27 2000-09-24 2000-10-29 2000-11-26 2000-12-31

Sebenarnya akan bekerja hingga tahun 9999.

DFSORT adalah produk penyortiran Mainframe IBM. Data dapat dimanipulasi, tetapi karena pengurutan adalah kunci dan pengurutan sering kali besar dan berjalan lama, kartu kontrol DFSORT tidak memiliki konstruksi pengulangan, jadi kami tidak dapat memasukkan SORT ke dalam satu lingkaran. Membuat hal-hal yang agak bertele-tele untuk tugas-tugas seperti Golf.

Mengapa memposting jawaban, adalah karena DFSORT memiliki PREVDdayfungsi. Jadi hari Minggu terakhir dalam sebulan itu mudah. Ini adalah hari Minggu sebelumnya (PREVDSUN) hingga hari pertama bulan berikutnya.

Itu juga menyenangkan untuk melakukannya dalam satu "operan" (OVERLAY), agak seperti melakukan semuanya di dalam sprintfatau serupa.

Ini dia ungolfed:

 OPTION COPY 

 INREC OVERLAY=(1,4,C'0201',1,8,1,8,1,8,1,8,1,8,1,8, 
         1,8,1,8,1,8,1,8, 
         1,8,94:C'1',89:1,4,ZD,ADD,+1,ZD,LENGTH=4, 
         14:C'3',22:C'4',30:C'5',38:C'6',46:C'7',54:C'8',
         62:C'9',69:C'10',77:C'11',85:C'12', 
        127:X,89,8,Y4T,PREVDSUN,TOGREG=Y4T(-), 
        116:X,81,8,Y4T,PREVDSUN,TOGREG=Y4T(-), 
        105:X,73,8,Y4T,PREVDSUN,TOGREG=Y4T(-), 
         94:X,65,8,Y4T,PREVDSUN,TOGREG=Y4T(-), 
         83:X,57,8,Y4T,PREVDSUN,TOGREG=Y4T(-), 
         72:X,49,8,Y4T,PREVDSUN,TOGREG=Y4T(-), 
         61:X,41,8,Y4T,PREVDSUN,TOGREG=Y4T(-), 
         50:X,33,8,Y4T,PREVDSUN,TOGREG=Y4T(-), 
         39:X,25,8,Y4T,PREVDSUN,TOGREG=Y4T(-), 
         28:X,17,8,Y4T,PREVDSUN,TOGREG=Y4T(-), 
         17:X,09,8,Y4T,PREVDSUN,TOGREG=Y4T(-), 
          1:1,8,Y4T,PREVDSUN,TOGREG=Y4T(-), 
         11:X,18,120,6X) 

Meskipun tidak cukup pelecehan, itu tidak biasa untuk mencoba menjejalkan semua ini menjadi satu OVERLAY, dan ada beberapa hal yang tampaknya tidak perlu yang diperlukan untuk memungkinkan semuanya masuk ke dalam satu OVERLAY. Ada beberapa ruang untuk bermain golf, tetapi karena itu hanya akan menghapus satu baris paling banyak, saya tidak tergoda.

INREC diproses untuk setiap catatan.

OVERLAY memungkinkan konten catatan yang ada diubah. Jika catatan diperpanjang melampaui panjangnya dalam proses, itu tidak masalah.

1,4 adalah tahun yang akan datang. Ini memiliki 0201 literal ditambahkan ke dalamnya, dan kemudian 1,8 berturut-turut mengulanginya 11 kali untuk memberikan satu chuck panjang 96 byte,

Tahun ke-12 pada catatan saat ini diperpanjang mendapat 1 ditambahkan ke dalamnya, dan bulannya dibuat menjadi 1 (Januari).

Sisa 10 bulan diubah menjadi 3 hingga 11.

Lalu ada 12, dalam urutan terbalik (karena OVERLAY) dari jenis hal ini:

127:X,89,8,Y4T,PREVDSUN,TOGREG=Y4T(-),

N: adalah nomor kolom pada catatan. X memasukkan kosong. 89,8 mengambil data dari kolom / panjang itu, Y4T memperlakukannya sebagai tanggal CCYYMMDD, PREVDSUM bekerja pada hari Minggu sebelumnya, TOGREG = Y4T (-) menampilkannya sebagai tanggal Gregorian CCYY-MM-DD.

Karena Anda mendapatkan sampah jika sumber dan target bagian tertentu dari OVERLAY tumpang tindih secara destruktif, final 11:X,18,120,6X)mengatur ulang dan menutupi sedikit kekacauan.

Manual dan makalah dapat ditemukan di: http://www-01.ibm.com/support/docview.wss?uid=isg3T7000080 , dan termasuk Panduan Pemrograman Aplikasi DFSORT 900+ halaman.

Seperti halnya semua produk IBM, semua manual tersedia gratis (kecuali sejumlah kecil yang sangat mahal yang hanya segelintir orang di dunia yang pura-pura mengerti).

Semua Kartu Kontrol DFSORT harus dimulai dengan yang kosong. Kolom 72 hanya digunakan untuk kelanjutan (tidak ada yang kosong akan dilakukan, tetapi * adalah konvensional). Kolom 72 diikuti oleh area nomor urut yang diabaikan, membuat setiap record 80 byte.

Beberapa solusi lain yang akan datang, mungkin.


5

Bash, 63 byte

for i in {01..12};{  date -v30d -v${i}m  -v2014y  -vsun +%Y-%m-%d;}

Keluaran:

2014-01-26
2014-02-23
2014-03-30
2014-04-27
2014-05-25
2014-06-29
2014-07-27
2014-08-24
2014-09-28
2014-10-26 
2014-11-30
2014-12-28

for i in {1..12};{ date -v30d -v${i}m -v$1y -v0w +%Y-%m-%d;}- 60 byte
Trauma Digital

-vparam to datekhusus untuk tanggal BSD. Jadi ini berfungsi pada OSX, tetapi tidak pada kebanyakan Linux - mungkin itu harus dinyatakan dalam jawabannya.
Trauma Digital

@DigitalTrauma, berfungsi di mac dan Linux saya.
michael501

4

Python 2 - 189 byte

y=input()
for m in range(12):
 d=[31-(1322>>m&1),28+(y%400<1or 1>y%4<y%100)][m==1];Y=y-(m<2);Z=Y%100;C=Y/100
 while(d+13*((m-2)%12+4)/5+Z+Z/4+C/4-2*C)%7-1:d-=1
 print"%d-%02d-%d"%(y,m+1,d),

Masukkan tanggal melalui STDIN.

Masih banyak lagi golf yang bisa dilakukan. Program sedikit berlebihan, hanya untuk bersenang-senang:

  • Tidak ada impor, khususnya yang tidak menggunakan fungsi tanggal bawaan
  • Gunakan kongruensi Zeller untuk menghitung hari dalam seminggu

Catatan

  • 1322 adalah tabel pencarian ajaib untuk menentukan apakah bulan non-Februari memiliki 30 atau 31 hari
  • Tidak zfilldiperlukan selama bertahun-tahun karena rentang input, atau hari karena mereka akan selalu lebih dari 20

Python 2 - 106 byte

Solusi tidak menyenangkan:

from calendar import*
y=input();m=1
while m<13:w,n=monthrange(y,m);print"%d-%02d-%d"%(y,m,n-(n+w)%7),;m+=1

calendar.monthrangemengembalikan dua angka: hari kerja bulan dimulai pada ( w) dan jumlah hari dalam bulan ( n). Solusinya sedikit berlawanan karena penangkapan - hari kerja kembali dimulai pada 0 untuk hari Senin , bukan hari Minggu! Namun, ini diimbangi oleh fakta yang nberbasis 1.


1
Jawaban Pyth yang sangat konyol:$from calendar import monthrange as gt$V12AGH>QhN%"%d-%02d-%d"(QhN-H%+GH7
FryAmTheEggman

3

JavaScript (ES6) 155 145

Edit masalah zona waktu yang diperbaiki Bisa lebih pendek jika dibuat rekursif. Mungkin.

F=y=>{
  for(n=i=o=[];!o[11];)
    d=new Date(Date.UTC(y,0,++i)),m=d.getMonth(),
    d.getDay()||(m!=n&&o.push(p.toISOString().slice(0,10)),p=d,n=m);
  return o.join(' ')
}

Anda bisa menggunakannya new Date(y,0,++i,9). Juga, ini gagal untuk tahun kabisat 2100 dan di atas karena JS tidak memiliki info tentang tahun kabisat dan dengan demikian, tidak memiliki Feb 29sama sekali di tahun kabisat untuk tahun 2100 dan di atas.
Pengoptimal

@Optimizer itu bukan JS: 2100,2200,2300 bukan tahun kabisat. 2014 adalah tahun kabisat dan JS tahu. Sedangkan untuk menggunakan jam 9, saya tidak dapat memverifikasi tapi saya pikir itu tidak berfungsi jika Anda misalnya di Melbourne ...
edc65

Ah .. Tidak pernah tahu kita turun 3 hari per 400 tahun. Tentang 9 - Saya mengubah zona saya dari -1000 (Hawaii) ke 1100 (Melbourne) dan new Date(2014,0,26,9)hari Minggu memberikan yang benar ISOtali serta getDay()sebagai 0.
Pengoptimal

3

JavaScript, ES6, 222 219 199 byte

Saya tidak melihat jawaban JavaScript di rosetta wiki.

Kita mulai:

S=Y=>{for(l=[],p=new Date(Y,i=0);i<365+!(Y%4);)if(!(d=new Date(Y,0,++i,9)).getDay()){p.getMonth()-d.getMonth()&&l.push(p);p=new Date(d)}return[...l,p].map(x=>x.toISOString().split("T")[0]).join(" ")}

Ini menciptakan fungsi Syang mengembalikan string dengan output yang diinginkan. fungsi ini juga menangani tahun kabisat.

Karena ES6, ini hanya berfungsi di Firefox terbaru.

Terima kasih kepada apsillers untuk tip yang mendapatkannya dikurangi menjadi 200 byte

Temukan versi yang tidak dikenali di bawah ini sebagai cuplikan tumpukan yang dapat Anda jalankan di sini sendiri:

S=Y=>{
  for(l=[],p=new Date(Y,i=0);i<365+!(Y%4);)
    if(!(d=new Date(Y,0,++i,9)).getDay()){
      p.getMonth()-d.getMonth()&&l.push(p);
      p=new Date(d)
    }
  return[...l,p].map(x=>x.toISOString().split("T")[0]).join(" ")
}

alert(S(parseInt(prompt())))


Anda dapat menggunakan + prompt () daripada parseInt dan mencukur beberapa byte
Jacob

@ Jacob Prompt itu tidak ditambahkan ke jumlah byte.
Pengoptimal

OKI. Seharusnya saya membaca pertanyaan ...
Yakub

@apsillers Terima kasih banyak! Memperbaiki masalah dan menguranginya banyak berdasarkan tip Anda.
Pengoptimal

2100Output input 2100-01-31 2100-02-28 2100-03-28 2100-04-25 2100-05-30 2100-06-27 2100-07-25 2100-08-29 2100-09-26 2100-10-31 2100-11-28 2100-12-26 2101-01-02salah.
Qwertiy

3

Rebol - 120 116 80 79 76

d: do join"1-1-"input print collect[for m 2 13 1[d/2: m keep d - d/weekday]]


Tidak dikumpulkan + beberapa anotasi:

d: do join "1-1-" input         ;; golfy way to create Rebol date! datatype 1-Jan-(year)

print collect [
    for m 2 13 1 [              ;; loop thru months 2 to 13!
        d/2: m                  ;; move to (1st of) next month
        keep d - d/weekday      ;; collect/keep last sunday of month
    ]
]

Contoh perhitungan minggu di konsol Rebol:

>> ; get last sunday of Jan 2014

>> d: 1-1-2014
== 1-Jan-2014

>> d/month: d/month + 1
== 2

>> d
== 1-Feb-2014

>> d/weekday
== 6

>> d - d/weekday
== 26-Jan-2014

>> ; above is last sunday of Jan 2014
>> ; and when pass end of year (ie. month 13!)

>> d/month: 13
== 13

>> d
== 1-Jan-2015

Potensi 87: d: 1-1-1 d / tahun: lakukan pengumpulan cetak input [ulangi m 12 [d / bulan: m + 1 simpan d - d / hari kerja]]
rgchris

@rgchris Terima kasih Chris. Mampu mencukur 7 karakter lain untuk.
draegtun

Bagus!! Ini buruk, tetapi tidak pernah benar-benar menganggap FOR sebagai jalan pintas.
rgchris

2

CJam, 122 102 byte

30li:X400%){[1387Yb30f+~28I!I4%!I100%e&|g+\]W%{\_2$>7*-\7%7\m1$+}/}fI;]12/W=12,{101+s1>}%]z{X+W%'-*S}/

Ini tidak menggunakan bentuk perpustakaan tanggal apa pun. Bisa juga masih banyak bermain golf, saya kira.

Uji di sini.


3
Saya sangat terpesona bahwa jawaban CJam bukan jawaban teratas dalam tantangan kode-golf untuk sekali. Saya bisa mati bahagia .. Hari ini adalah hari yang baik (sampai golf turun menjadi 6 byte, jelas)
Brandon

@Brandon: Itulah alasan saya pikir itu akan menarik. Sangat berharap untuk melihat perpustakaan yang menakjubkan yang membuat ini mudah, tetapi kecewa sejauh ini.
Phil H

1

R, 128 karakter

P=paste;f=format;a=strptime(P(1:366,scan()),"%j %Y");cat(sort(sapply(split(a,f(a,"%B")),function(x)P(tail(x[f(x,"%u")==7],1)))))

Dengan jeda baris:

P=paste
f=format
a=strptime(P(1:366,scan()),"%j %Y")
cat(sort(sapply(split(a,f(a,"%B")),function(x)P(tail(x[f(x,"%u")==7],1)))))

1

C # 255

Tidak disatukan

static void Main(string[] a)
    {
        int y = Int32.Parse(Console.ReadLine());
        DateTime d = new DateTime(y, 1, 1);
        while (d.Year == y)
        {
            if (d.DayOfWeek == DayOfWeek.Sunday && d.Day>(DateTime.DaysInMonth(y,d.Month)-7))
                Console.WriteLine(d.ToShortDateString());
            d = d.AddDays(1);
        }
        Console.ReadKey();
    }

Edit: dimodifikasi untuk mencetak hanya hari Minggu terakhir :)


Bukan format output yang dibutuhkan. + Ini adalah kode golf
edc65

1

q, 67

{({{1<>x mod 7}-[;1]/x}')14h$1_til[13]+13h$"D"$(($)x),".01.01"}

Apakah tidak ada perpustakaan tanggal yang dapat digunakan untuk ini di q?
Phil H

1

"Oh, tidak, dia lagi!"

Java - 259 246 byte

void g(int y){for(int i=;i<12;i++){GregorianCalendar c=new GregorianCalendar(y,i,0);c.set(c.DAY_OF_WEEK,c.SUNDAY);c.set(c.DAY_OF_WEEK_IN_MONTH,-1);System.out.print(y+"-"+String.format("%02d",(c.get(c.MONTH)+1))+"-"+(c.get(c.DAY_OF_MONTH))+" ");}}

Versi tidak disatukan:

void g(int y){
    for (int i = 0; i < 12;i++) {
        GregorianCalendar c = new GregorianCalendar(y, i, 0);
        c.set(c.DAY_OF_WEEK, c.SUNDAY);
        c.set(c.DAY_OF_WEEK_IN_MONTH, -1);
        System.out.print(y+"-"+String.format("%02d",(c.get(c.MONTH)+1))+"-"+(c.get(c.DAY_OF_MONTH))+" ");
    }
}

Pemakaian:

import java.util.GregorianCalendar;
import java.util.Scanner;

public class LastSundayInYear {

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.println("Year?");
        int year = scanner.nextInt();
        LastSundayInYear sunday = new LastSundayInYear();
        sunday.g(year); 
    }

    void g(int y){
        for (int i = -1; ++i < 12;) {
            GregorianCalendar c = new GregorianCalendar(y, i, 0);
            c.set(c.DAY_OF_WEEK, c.SUNDAY);
            c.set(c.DAY_OF_WEEK_IN_MONTH, -1);
            System.out.print(y+"-"+String.format("%02d",(c.get(c.MONTH)+1))+"-"+(c.get(c.DAY_OF_MONTH))+" ");
        }
    }
}

Keluaran:

2014-01-26 2014-02-23 2014-03-30 2014-04-27 2014-05-25 2014-06-29 2014-07-27 2014-08-31 2014-09-28 2014-10-26 2014-11-30 2014-12-28

Namun jawaban "mari kita beri balasan Java hanya untuk iseng" saja. Baiklah. Tetapi, paling tidak, karena Anda berusaha mencapai titik jawaban saya ini, saya akan mencoba membuat Anda bosan lagi dan menjelaskan alasan saya.

Metode gmenerima tahun yang diinginkan dan, untuk setiap bulan, menciptakan GregorianCalendarobjek (bulan beralih dari 0 hingga 11). Kemudian, yang pertama c.setmenetapkan hari dalam seminggu sebagai hari Minggu dan yang kedua menyatakan bahwa kita menginginkan minggu terakhir bulan itu - seperti yang terlihat pada dokumentasi resmi . The System.out.printlnprint tanggal hari Minggu (jika kita melakukan hak ini, tahun akan dicetak sebagai c.get(c.YEAR), tetapi menggunakan ylagi mencukur off 13 karakter), bulan harus diformat untuk menambahkan nol dari Januari sampai September (dan nilai bertambah karena, yah, bulan di sini diwakili 0-11) dan hari Minggu terakhir dicetak. Dan prosedur ini diulang selama sebelas bulan lainnya.


0

C #, 212 , 237

string x(int y){var s="";var t="";var d=new DateTime(y,1,1);for(;;){if(d.Year!=y){return s;}t=(d.DayOfWeek==DayOfWeek.Sunday)?t=string.Format("{0}-{1}-{2} ",d.Year,d.Month,d.Day):t;s=(d.AddDays(1).Month!=d.Month)?s+=t:s;d=d.AddDays(1);}}

Dengan jeda baris

string x(int y)
    {
        var s = "";
        var t = "";
        var d = new DateTime(y,1,1);
        for (;;)
        {
            if (d.Year != y) {
                return s;
            }
            t = (d.DayOfWeek == DayOfWeek.Sunday) ? t = string.Format("{0}-{1}-{2} ", d.Year, d.Month, d.Day) : t;
            s=(d.AddDays(1).Month!=d.Month)?s+=t:s;
            d=d.AddDays(1);
        }
    }

Output untuk 2014

"2015-1-25 2015-2-22 2015-3-29 2015-4-26 2015-5-31 2015-6-28 2015-7-26 2015-8-30 2015-9-27 2015-10-25 2015-11-29 2015-12-27"

Bukan format output yang diperlukan
edc65

Di sana, diperbaiki. Lebih baik?
Darren Breen

0

C # 171

Berfungsi mengembalikan string.

string S(int y){var r="";for(int m=1;m<13;++m){var d=new System.DateTime(y,1,1).AddMonths(m).AddDays(-1);r+=y+string.Format("-{0:00}-{1} ",m,d.Day-d.DayOfWeek);}return r;}

Tidak disatukan

string S(int y)
{
    var r="";
    for (int m=1;m<13;++m)
    {
        var d = new System.DateTime(y, 1, 1).AddMonths(m).AddDays(-1);
        r += y + string.Format("-{0:00}-{1} ", m, d.Day - d.DayOfWeek);
    }
    return r;
}

0

C # 194

menggunakan Linq:

string d(int y){return string.Join(" ",Enumerable.Range(1,12).Select(m=>new DateTime(y,m,DateTime.DaysInMonth(y,m))).Select(d=>d.AddDays(-(int)d.DayOfWeek)).Select(d=>d.ToString("yyy-MM-dd")));}

Tidak disatukan

string d(int y)
{
    return string.Join(" ",Enumerable.Range(1,12)
        .Select(m => new DateTime(y, m, DateTime.DaysInMonth(y, m)))
        .Select(d => d.AddDays(-(int)d.DayOfWeek))
        .Select(d => d.ToString("yyy-MM-dd")));
}

Keluaran

2013-01-27 2013-02-24 2013-03-31 2013-04-28 2013-05-26 2013-06-30 2013-07-28 2013-08-25 2013-09-29 2013-10-27 2013-11-24 2013-12-29

0

Mathematica - 171

Dibungkus dalam fungsi anonim, mengembalikan string

StringJoin[Last@#~DateString~{"Year","-","Month","-","Day"," "}&/@GatherBy[Select[DateRange[DateObject[{#}],DateObject[{#+1}]],DayName@#==Sunday&],DateValue[#,"Month"]&]]&

Golf matematika pertama. Saya merasa seperti itu dapat dikurangi secara substansial.


0

VB-192

Function z(y)
For i = 1 To 11
a = 0
s = IIf(i <> 11, DateSerial(y, i + 1, 1), DateSerial(y + 1, 1, 1))
While Weekday(s - a) <> 1
a = a + 1
Wend
r = r + Str(s - a) + " "
Next
z = r
End Function

Bisa lebih buruk ^^

Entri kedua dan terakhir saya (jangan berpikir saya bisa membuatnya lebih kecil)

142

Function z(y)
Dim m(12)
For i = 1 To 366
s = DateSerial(y, 1, 1) + i
If Weekday(s) = 1 Then m(Month(s)) = s
Next
z = Join(m, " ")
End Function

0

Ruby 76

Menggunakan parameter baris perintah ruby sundays.rb 1900. Menggunakan perpustakaan tanggal.

require'date';puts (1..12).map{|m|d=Date.new($*[0].to_i,m,-1);d-d.wday}*" "
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.