Berapa hari Jumat tanggal 13 dalam setahun?


28

Tantangan Anda adalah menulis sebuah program yang, setelah satu tahun, menampilkan jumlah "Friday 13ths" di dalamnya.

Aturan & Detail:

  • Anda dapat mengambil input melalui STDIN, atau sebagai argumen yang diteruskan ke program Anda.
  • Anda harus menampilkan hasilnya STDOUT.
  • Anda dapat berasumsi bahwa input akan menjadi tahun yang valid, dan tidak memberi tanggal lebih awal pada kalender Gregorian (perilaku tidak terdefinisi diizinkan dalam kasus-kasus ini).
  • Kalender / Pustaka Tanggal diizinkan.

Ini adalah , jadi kode terpendek (dalam byte) menang.

(Tautan tantangan terkait)


7
Berapa kisaran input yang diperlukan? Jika berjalan jauh sebelum 1800, asumsi apa yang harus dibuat tentang peralihan dari Julian ke kalender Gregorian?
Peter Taylor

@ PeterTaylor saya belum memikirkannya. Jika suatu tanggal pre-date gregorian maka Anda dapat memiliki perilaku tidak terdefinisi.
Cruncher

1
Negara-negara pertama yang mengadopsi kalender Gregorian melakukannya pada Oktober 1582, mengikuti banteng Gregory sendiri. Negara-negara untuk mengadopsi kalender baru terlambat tidak berubah sampai abad ke-20, misalnya Yunani memperkenalkannya pada 1 Maret 1923.
Jeppe Stig Nielsen

@JeppeStigNielsen Saya tidak tahu banyak tentang kalender dan semacamnya. Apakah mereka mengadopsinya atau tidak, tidak mengubah tanggalnya. Perpustakaan harus dapat menghitung tanggal dari cara saya kira?
Cruncher

3
Saya sedang offtopic di sini, saya kira. Banyak perpustakaan yang ditulis oleh pemrogram Anglo-Amerika menggunakan September 1752 sebagai waktu perubahan kalender yang "benar". Saat itulah Kerajaan Inggris berubah. Kalender baru disimpan ketika AS didirikan, tentu saja. (Sebagai rasa ingin tahu, beberapa perangkat lunak SQL memiliki 1753 sebagai tahun minimal karena mereka tidak ingin mengatasi masalah September 1752.) Namun, menggunakan September 1752 sangat anglosentris. Anda benar, tanggal Gregorian sama apakah mereka digunakan secara historis atau tidak. Itulah yang disebut kalender Gregorian proleptik .
Jeppe Stig Nielsen

Jawaban:


3

APL (Dyalog APL) dengan kal dari dfns , 29 byte

+/{13∊⍎,⍉3↑¯5↑⍉2cal⍵}¨⎕,¨⍳12

Cobalah online!

⍳ 12 bilangan bulat satu sampai dua belas

⎕ ,¨ mengambil input numerik dan menambahkan masing-masing dari dua belas angka

{...  pada masing-masing pasangan, terapkan fungsinya ...

cal⍵ dapatkan kalender untuk tahun-bulan itu

2 ↓ turunkan dua baris (keterangan dan hari)

 transpos (jadi kita bisa membahas kolom alih-alih baris)

¯5 ↑ ambil lima terakhir (dua digit untuk masing-masing hari Jumat dan Sabtu ditambah satu spasi)

3 ↑ ambil dua yang pertama (dua digit untuk Jumat ditambah spasi)

 transpos (jadi kami mendapat pesanan membaca)

, berlepasan

 dieksekusi sebagai ekspresi APL (memberikan daftar tanggal Jumat)

13 ∊ Apakah tiga belas anggota dari daftar itu?

+/ jumlah 12 Boolean


Dengan menggunakan algoritma @ Wrzlprmft , kita dapat melakukannya tanpa pustaka untuk 53 byte:

'21232211321211'⊃⍨14|2 3 ¯1+.×⊢,0≠.=400 100 4∘.|-∘0 1

-∘0 1 kurangi nol dan satu

400 100 4 ∘.| tabel sisa pembagian selama dua tahun (lintas) dibagi dengan angka-angka ini (turun)

0 ≠.= "produk" dalam dengan 0, tetapi menggunakan ≠ dan = bukannya +. ×

⊢ , pertahankan tahun argumen yang tidak dimodifikasi

2 3 ¯1 +.× produk dalam dengan angka-angka ini

14 | pembagian divisi ketika dibagi empat belas

'21232211321211' ⌷⍨ indeks ke dalam string ini


Ini 29 karakter, tetapi ini lebih dari 1 byte karakter, kan?
Cruncher

@Cruncher Saya telah menambahkan tautan penjelas dalam tajuk. Jika Anda membuka tautan TIO, Anda akan melihat tulisan "29 chars, 29 bytes (SBCS)" di sebelah kanan, yaitu Single Byte Character Set.
Adám

Nah, saya kira ini adalah pemenang baru, apakah praktik standar dalam SE ini untuk mengubah jawaban yang diterima selama ini setelah pertanyaan?
Cruncher

@Cuncher Ya. Dan bahkan ada lencana yang bisa didapat untuk diterima lama setelah OP.
Adám

12

Mathematica 49 46 45 44 42

Sebagai fungsi murni : 42 karakter

DayName@{#,m,6}~Table~{m,12}~Count~Friday&

Contoh

DayName@{#,m,6}~Table~{m,12}~Count~Friday&[2013]

2


Sebagai fungsi bernama : 44 karakter

f=DayName@{#,m,6}~Table~{m,12}~Count~Friday&

Contohnya

f[1776]
f[2012]
f[2013]
f[2014]

2
3
2
1


Satu karakter lebih pendek:f=DayName@{#,m,6}~Table~{m,12}~Count~Friday&
Mr.Wizard

@ Mr.Wizard Ya. Ini mengejutkan saya bahwa Mathematica dapat mengurai banyak kasus notasi infiks.
DavidC

David itu mengejutkan saya bahwa Anda belum melihat penggunaan saya atas notasi siam ini. : ^) (Contoh: (1) , (2) )
Mr.Wizard

8

Ruby, 49 48 47 46

f=->m{(1..12).count{|i|Time.gm(m,i,6).friday?}}

Sunting: Mencukur karakter dengan kembali seminggu, terima kasih kepada Jan, dan lainnya dengan beralih dari Time.new ke Time.gm

Sunting: Dengan mengorbankan sedikit lebih banyak, saya bisa mendapatkan 46 dengan

f=->m{(1..12).count{|i|Time.gm(m,i,8).wday<1}}

5
one-char saving jika Anda menghitung jumlah hari Jumat tanggal 6
John Dvorak

2
@JanDvorak pintar!
histokrat

mengapa 6? Saya tidak mengerti.
NARKOZ

3
Jika tanggal 6 adalah hari Jumat, maka tanggal 13 juga merupakan hari Jumat
TwiNight

Jika tanggal 8 adalah hari Minggu, maka tanggal 1 juga, dan Anda dapat menggunakannya Time.gm(m,i).wday<1. Juga, saya tidak tahu mengapa Anda memberi nama fungsinya.
Lee W

8

Powershell, 68 63 58 52 50

Terima kasih Iszi atas tipnya.

$n=$args;(1..12|?{!+(date $n-$_).DayOfWeek}).Count

Menggunakan fakta bahwa jika hari pertama di bulan itu adalah hari Minggu, tanggal 13 akan menjadi hari Jumat.

Saya juga sudah mencoba:

(1..12|?{!+(date $args-$_).DayOfWeek}).Count

tapi itu tidak sama $argsdi dalam blok skrip.


1
Saya suka ide menggunakan hari pertama bulan itu.
Cruncher

Trik yang bagus, di sana. Namun, @ tidak perlu.
Iszi

Hal lain, meskipun saya bersalah atas hal yang sama dalam banyak skrip saya. Tantangannya memang menentukan bahwa input dapat berasal dari argumen. Ganti $ndengan $argsdalam loop, dan Anda dapat melakukannya tanpa $n=read-host;sepenuhnya. Menghemat 8. Hapus @, seperti yang disebutkan di atas, dan Anda turun ke 54.
Iszi

Koreksi: Turun ke 52!
Iszi

Mencoba mencari tahu mengapa skrip kedua Anda tidak berfungsi dan saya bingung. Yang menarik adalah bahwa saya bisa mengganti $argsuntuk $input, sehingga makan tahun di dari pipa, dan script akan berjalan tapi selalu output 3.
Iszi

5

R 76 72 57

sum(format(as.Date(paste(scan(),1:12,1,sep="-")),"%w")<1)

Dapat dengan mudah menurunkan ini 4 dengan mengganti "%a %d")=="Fri 13"dengan "%w%d)=="513")menggunakan dow sebagai angka, dan menghilangkan spasi.
chmullig

sangat dihargai!
flodel

+1 Meskipun melakukan seqsatu - satunya pada bulan ini sebenarnya lebih pendek di sini! sum(format(as.Date(paste(scan(),1:12,13,sep="-")),"%w%d")=="513")hanya 65 karakter!
plannapus

wow saya tidak akan menduga bahwa <akan memaksa karakter ke integer. Trik yang bagus!
plannapus

@plannapus Ini agak umum. Karena kode karakter adalah semua angka. Bahkan java dapat membandingkan int dan char
Cruncher

5

Python2.7 90 86

from datetime import*
s=c=0
exec's+=1;c+=date(%d,s,9).weekday()<1;'%input()*12
print c

Senin tanggal 9 mungkin tidak memiliki cincin yang sama tetapi berfungsi dengan baik.

Sunting: Satu setengah tahun untuk melihat yang datelebih pendek dari datetime:)


Solusi yang sangat bagus!
leancz

2
Anda dapat menyimpan char dengan melakukanfrom datetime import*
user80551

Bagus! Saya akhirnya dengan sesuatu yang secara efektif identik, tetapi menghindari exec: f=lambda y:sum([date(y,m,13).weekday()==4 for m in range(1,13)]).... Solusi ukuran yang sama dengan impor (86 byte), meskipun.
iwaseatenbyagrue

5

Tidak menggunakan perpustakaan atau fungsi tanggal bawaan:

Golfscript - 51

~..({4/.25/.4/--@}2*2*\3*+-
14%' [3/=RI[)a%:*.'\=5%

' [3/=RI[)a%:*.' bisa juga 'feefefgeeffgfe'

Python - 82 79

Intinya algoritma yang sama.

l=lambda y:y/4-y/100+y/400
i=input()
print"21232211321211"[(2*i+3*l(i)-l(i-1))%14]

Dengan menggunakan trik ini , ini dapat diturunkan lebih lanjut ke:

l=lambda y:y/4-y/100+y/400
i=input()
print 94067430>>(4*i+6*l(i)-2*l(i-1))%28&3

Ini mengeksploitasi fakta bahwa, berdasarkan kalender, hanya ada 14 tahun yang berbeda, yang dapat dibedakan berdasarkan hari terakhir mereka dan apakah mereka melompat. lmenghitung jumlah tahun kabisat hingga argumennya (jika kalender Gregorian diperpanjang mundur ke tahun 1). (2*i+3*l(i)-l(i-1))%14adalah kependekan dari l(i)-l(i-1)+(i+l(i))%7*2, di mana l(i)-l(i-1)memberitahu kita apakah argumennya adalah tahun kabisat dan i+l(i)meringkas pergeseran dari hari terakhir (satu dalam tahun normal, dua dalam tahun kabisat).


Karena ini adalah golfscript golf pertama saya, saya akan menghargai setiap petunjuk tentang golf lebih lanjut ke bawah.
Wrzlprmft

Saya sedang memikirkan solusi yang memanfaatkan fakta bahwa hanya ada 14 tahun yang unik sebenarnya, tetapi tidak yakin bahasa terbaik untuk membuatnya kompetitif. Saya pikir ini adalah jawaban terpendek tanpa perpustakaan. Jika tahun kabisat seragam setiap 4 tahun, Anda mungkin bisa menang dengan ini
Cruncher

4

C 301+ 287

main(int x,char**v){char p[400],*a[]={"abbababbacaacbac","bacabbb","baabbaca","abbb","aabbacaac","abbbbcaac","abbbbaabb"},*b="adcadcadcaebcadcadcafbcadcadcagbcadcadcadc";int c=0,i,y=atoi(v[0]);for(i=0;i<42;i++)strcpy(&p[c],a[b[i]-'a']),c+=strlen(a[b[i]-'a']);printf("%d",p[y%400]-'`');}

Bukan jawaban terpendek, tetapi tidak menggunakan perpustakaan.


Hei, apakah Anda bersedia memberikan jawaban yang tidak diserang dengan penjelasan? Saya tertarik dengan apa yang Anda lakukan
Cruncher

1
@Cruncher, ini adalah tabel pencarian berdasarkan kalender Gregorian yang mengikuti siklus 400 tahun.
Peter Taylor

1
Lebih eksplisit (dan lagi), C #: static char GetNumberOfFriday13s(int year) { const string perpetualCalendar = "1221212213113213122221122131122121221311321312222112213112212122131132131222211221311221212213113213112213113213122221122131122121221311321312222112213112212122131132131222211221311221212213113213122213113213122221122131122121221311321312222112213112212122131132131222211221311221212213113213122221122213122221122131122121221311321312222112213112212122131132131222211221311221212213113213122221122131"; return perpetualCalendar[year % 400];. Tidak akan bekerja selama bertahun-tahun negatif.
Jeppe Stig Nielsen

Imut! Sebagai bug kecil, v[0]seharusnya v[1]. Anda juga bisa bermain golf ini sedikit; pertimbangkan untuk menggunakan strcat, menyimpan karakter untuk langsung dicetak a[], dan kurangi konstanta numerik alih-alih konstanta karakter. :)
user1354557

1
Saya meningkatkan kompresi juga: main(int x,char**v){char p[400],*a[]={"1221212213113213","2131222","21122131","1222","112213113","122223113","122221122"},*b="adcadcadcaebcadcadcafbcadcadcagbcadcadcadc";*p=0;for(;*b;b++)strcat(p,a[*b-97]);putchar(p[atoi(v[1])%400]);}(215 karakter)
user1354557

4

C ( 151 145 137 131 130 karakter)

Saya terkejut melihat bahwa hanya ada satu solusi lain yang tidak menggunakan alat kalender bawaan. Berikut ini adalah pendekatan matematika (sangat dikaburkan), juga dalam C:

f(x){return(x+(x+3)/4-(x+99)/100+!!x)%7;}main(int x,char**v){int y=atoi(v[1])%400,a=f(y+1);putchar('1'+((f(y)&3)==1)+(a>2&&a-5));}

(Kompilasi di atas di GCC tanpa kesalahan)

Solusi alternatif: C (287-> 215 karakter)

Saya agak menikmati solusi Williham Totland dan penggunaan kompresi. Saya memperbaiki dua bug kecil dan mengubah kode untuk mempersingkat panjangnya:

main(int x,char**v){char p[400],*a[]={"1221212213113","213122221122131","12213113","22213113","22221122","2131"},*b="abababafcbababafdbababafebababab";*p=0;for(;*b;b++)strcat(p,a[*b-97]);putchar(p[atoi(v[1])%400]);}


4

bash 47 36

seq -f$1-%g-6 12|date -f-|grep -c ^F

Terima kasih @DigitalTrauma karena telah menyimpan 10 karakter dengan menggunakan seqmulai dari awal 1.

date -f<(printf "%s\n" $1-{1..12}-6)|grep -c ^F

(Versi sebelumnya menggunakan echobug saat ini karena baris kosong ketika <(echo $1-{1..12}-6$'\n'). Jadi fungsi ini berfungsi dengan baik sampai hari ini adalah hari Jumat.

Ayo lihat:

set -- 2013
seq -f$1-%g-6 1 12|date -f-|grep -c ^F
2

date -f<(printf "%s\n" $1-{1..12}-13)|grep -c ^F
2

Apakah tergantung pada lokal , jika tidak berfungsi, Anda mungkin harus

export LANG=C

atau

LANG=C date -f<(printf "%s\n" $1-{1..12}-13)|grep -c ^F

Menjadi suatu fungsi; +7 -> 43

f(){ seq -f$1-%g-6 12|date -f-|grep -c ^F;}

f 2013
2

for i in {2010..2017};do echo $i $(f $i) ;done
2010 1
2011 1
2012 3
2013 2
2014 1
2015 3
2016 1
2017 2

Bonus: +78 -> 121

Dari sana, jika fungsi saya menjadi:

f(){ o=();for t in $(seq -f$1-%g-6 12|date -f- +%a,%b);do [ "${t:0:1}" = "F" ]&&o+=(${t#*,});done;echo ${#o[@]} ${o[@]};}

atau

f(){ o=();
     for t in $(seq -f$1-%g-6 1 12|date -f- +%a,%b);do
         [ "${t:0:1}" = "F" ]&&o+=(${t#*,})
       done
     echo ${#o[@]} ${o[@]}
}

for i in {2010..2017};do echo $i $(f $i) ;done
2010 1 Aug
2011 1 May
2012 3 Jan Apr Jul
2013 2 Sep Dec
2014 1 Jun
2015 3 Feb Mar Nov
2016 1 May
2017 2 Jan Oct

Ini tampaknya tergantung pada lokal.
Peter Taylor

Ya, ini didasarkan pada default C. Tapi ada bug ...
F. Hauri

Simpan char dengan menghapus tanda kutip format printf Anda dan keluar dari \ sebaliknya:%s\\n
Digital Trauma

1
Atau gunakan sequntuk menjatuhkan 8 karakter:date -f<(seq -f$1-%g-6 1 12)|grep -c ^F
Digital Trauma

1
Sebenarnya, Anda dapat mencukur 2 karakter lagi. Jika Anda menghilangkan nomor urut mulai, seq akan mulai pada 1 secara default, yang mana itu yang Anda inginkan:seq -f$1-%g-6 12|date -f-|grep -c ^F
Digital Trauma

4

JavaScript, 70

f=function(a){b=0;for(c=12;c--;)b+=!new Date(a,c,1).getDay();return b}

dan mengapa -1?
Lukasz 'Severiaan' Grela

1
Kelihatan bagus! Anda dapat menyimpan beberapa byte, dengan menghapus ,b,cdari deklarasi fungsi (! Ok itu untuk kebocoran vars untuk golf), juga sebagai bdilemparkan sebagai NumberAnda bisa +=hasil tes bukan &&b++: b+=/^F/.test(new Date(a,c,6)). Namun, Anda dapat menyimpan byte lain, menggunakan !new Date(a,c,1).getDay()(ini berfungsi karena getDaymengembalikan 0 untuk hari Minggu, dan jika tanggal 13 adalah hari Jumat, tanggal 1 akan menjadi hari Minggu) alih-alih testyang semuanya akan menghemat 7 byte!
Dom Hastings

@HomHastings: thx untuk tips Anda !!!
guy777

3

k

64 karakter

{+/6={x-7*x div 7}(.:')x,/:(".",'"0"^-2$'$:1+!:12),\:".13"}[0:0]

Baca dari stdin


Ok, apa yang sedang terjadi di sini? : P
Williham Totland

Baca tahun ini, buat daftar tanggal 13 hari setiap bulan, hari tes minggu = Jumat, jumlah hasil daftar boolean
skeevey

3

Gangguan Umum (CLISP), 149

(print 
    (loop for i from 1 to 12 count 
        (= 4 (nth-value 6 
            (decode-universal-time
                (encode-universal-time 0 0 0 13 i
                    (parse-integer (car *args*)) 0))))))

Ya Tuhan, aku tidak pernah bisa membaca lisp ..
Cruncher

2

C # 110 101 93 92

int f(int y){int c=0;for(int i=1;i<13;i++)c+=new DateTime(y,i,8).DayOfWeek>0?0:1;return c;}

C # Linq 88

int g(int y){return Enumerable.Range(1,12).Count(m=>new DateTime(y,m,8).DayOfWeek==0);}

Terima kasih kepada Jeppe Stig Nielsen untuk linq dan saran untuk memeriksa minggu pada tanggal 8.

Terima kasih kepada Danko Durbić karena menyarankan >alih-alih ==.


Alih-alih c+=(int)new DateTime(y,i,13).DayOfWeek==5?1:0;, gunakan yang setara c+=new DateTime(y,i,8).DayOfWeek==0?1:0;. Caranya adalah dengan mengurangi 5, karena dengan begitu Anda dapat menyingkirkan para pemain int, dan juga jumlahnya 8memiliki satu digit lebih sedikit dari angka tersebut 13. Sunday the Eighth!
Jeppe Stig Nielsen

Dengan Linq: int g(int y){return Enumerable.Range(1,12).Count(m=>new DateTime(y,m,8).DayOfWeek==0);}. Tentu saja seperti lambda ini y=>Enumerable.Range(1,12).Count(m=>new DateTime(y,m,8).DayOfWeek==0).
Jeppe Stig Nielsen

Anda dapat menyimpan satu karakter dengan membandingkan .DayOfWeek<1.
Danko Durbić

@ DankoDurbić Ini dapat diterapkan pada c#jawaban tetapi tidak yakin bagaimana menerapkannya linq.
Kami

Kesalahanku; tampaknya Anda tidak dapat membandingkan DayOfWeekdengan bilangan bulat lain selain 0- error CS0019: Operator '<' cannot be applied to operands of type 'System.DayOfWeek' and 'int'.
Danko Durbić

2

PHP, 55 byte

for(;++$i<13;)$c+=!date(w,strtotime($argn.-$i));echo$c;

Jalankan dengan echo <year> | php -nR '<code>'.

Pada dasarnya sama dengan yang dicoba Oleg dan Damir Kasipovic , hanya dengan bermain golf yang lebih baik:
Setiap bulan yang dimulai dengan minggu, memiliki hari Jumat tanggal 13.
Jadi saya mengulangi bulan dan menghitung hari-hari pertama minggu.

kerusakan

for(;++$i<13;)          // loop $i from 1 to 12
    $c+=!                   // 4. if result is not truthy (weekday==0), increment $c
        date(w,             // 3. get weekday (0 stands for Sunday)
            strtotime(      // 2. convert to timestamp (midnight 1st day of the month)
                $argn.-$i   // 1. concatenate year, "-" and month
            )
        )
    ;
echo$c;                 // output

1

K, 42

{+/1={x-7*x div 7}"D"$"."/:'$+(x;1+!12;1)}

.

k){+/1={x-7*x div 7}"D"$"."/:'$+(x;1+!12;1)}'1776 2012 2013 2014
2 3 2 1

1

Bash ( 52 47 karakter)

for m in {1..12};do cal $m $Y;done|grep -c ^15

1

Rebol, 63

f: 0 repeat m 12[d: do ajoin["6-"m"-"y]if d/weekday = 5[++ f]]f

Contoh penggunaan di konsol Rebol:

>> y: 2012
== 2012

>> f: 0 repeat m 12[d: do ajoin["6-"m"-"y]if d/weekday = 5[++ f]]f
== 3

Solusi alternatif yang mengumpulkan semua hari Jumat tanggal 13 tahun tertentu adalah:

>> collect[repeat m 12[d: do ajoin["13-"m"-"y]if d/weekday = 5[keep d]]]
== [13-Jan-2012 13-Apr-2012 13-Jul-2012]

1

Bash and Sed, 39

ncal $1|sed '/F/s/13/\
/g'|grep -c ^\ 2

ncal mencetak kalender untuk tahun tertentu dengan hari dalam seminggu di sebelah kiri.

seddengan /gflag subs semua 13 dengan newlines

grep -c menghitung garis yang dimulai dengan "2" (20 selalu mengikuti 13)

Terima kasih kepada @DigitalTrauma untuk menemukan bug di versi lama saya dan mengusulkan solusi!


Tidak cukup untuk saya - garis Jumat hanya dicetak sekali walaupun mengandung lebih dari satu 13.
Digital Trauma

1
Saya pikir yang terbaik yang bisa saya lakukan dengan sesuatu seperti ini adalah 38:ncal $1|sed /F/s/13/\\n/g|grep -c ^\ 2
Digital Trauma

1
@DigitalTrauma Anda benar. Pada titik tertentu skrip ini berfungsi. biarkan saya memperbaikinya.
Bukan karena Charles

1
@DigitalTrauma sepertinya beberapa versi yang lebih lama berfungsi. terima kasih untuk perbaikannya!
Bukan karena Charles

Menarik, ekspresi sed yang tidak dikutip yang saya ajukan bekerja dengan GNU sed (Linux) tetapi tidak dengan BSD sed (OSX). Saya kira Anda bisa mendapatkan 1 char dengan biaya portabilitas jika Anda memilih versi GNU.
Digital Trauma

1

Scala, 76 68 karakter

Dalam 78 karakter:

def f(y:Int)=0 to 11 count(new java.util.GregorianCalendar(y,_,6).get(7)==6)

Tidak ada yang luar biasa, kecuali untuk menggunakan angka ajaib untuk DAY_OF_WEEK = 7dan FRIDAY = 6.

Versi 68 karakter:

def f(y:Int)=0 to 11 count(new java.util.Date(y-1900,_,6).getDay==5)

Ya, Java mengubah nilai konstanta hari dalam seminggu antara API.


Sayang sekali new java.util.GregorianCalendarharus begitu lama :(
Cruncher

1

Python 195/204

Hanya berfungsi untuk tahun-tahun sebelumnya, karena monthdatescalendarmengembalikan kalender untuk tahun yang diberikan hingga sekarang . Saya pikir ada banyak potensi optimal yang tersisa :).

import calendar, sys
c=calendar.Calendar()
f=0
for m in range(1,12):
 for w in c.monthdatescalendar(int(sys.argv[1]),m):
  for d in w:
   if d.weekday() == 4 and d.day == 13:
    f=f+1
print(f)

Solusi lain, berfungsi untuk setiap tanggal tetapi tidak lebih kecil:

import datetime,sys
y=int(sys.argv[1])
n=datetime.date
f=n(y,1,1)
l=n(y,12,31)
i=0
for o in range(f.toordinal(), l.toordinal()):
 d=f.fromordinal(o)
 if d.day == 13 and d.weekday() == 4:
  i=i+1
print(i)

Dalam contoh pertama Anda, kisarannya adalah (1,13) jika tidak Anda akan melewatkan Jumat 13 Desember, seperti pada 2013.
leancz

1
Anda bahkan tidak repot-repot bermain golf. Hapus beberapa ruang itu.
mbomb007

1

Perl 6, 55 53

{sum (1..12).map: {Date.new($_,$^a,1).day-of-week>6}}

Jawaban lama:

{sum (1..12).map: {Date.new($_,$^a,13).day-of-week==5}}


0

Python (v2) 120

import datetime as d,sys
s=0
for m in range(1, 13):
    if d.datetime(int(sys.argv[1]),m,6).weekday()==4: s=s+1
print s

0

Perl + lib POSIX 55

Dengan ide tidak mencari 13thtapi pertama, dan sebagai sundayadalah 0membiarkan ini Hemat 3 karakter! Terima kasih @ Iszi dan Danko Durbić!

$==$_;$_=grep{!strftime"%w",0,0,0,1,$_,$=-1900}(0..11)

Dapat menghitung 2010 hingga 2017 (untuk sampel) dengan cara ini:

perl -MPOSIX -pE '$==$_;$_=grep{!strftime"%w",0,0,0,1,$_,$=-1900}(0..11)' <(
    printf "%s\n" {2010..2017})
11321312

(Ok, tidak ada baris baru , tapi itu tidak ditanyakan;)

Posting lama: 63

$==grep{5==strftime"%w",0,0,0,13,$_,$ARGV[0]-1900}(0..11);say$=

Beraksi:

for i in {2010..2017};do
    echo $i $(
        perl -MPOSIX -E '
            $==grep{5==strftime"%w",0,0,0,13,$_,$ARGV[0]-1900}(0..11);say$=
            ' $i );
  done
2010 1
2011 1
2012 3
2013 2
2014 1
2015 3
2016 1
2017 2

0

Dalam Smalltalk (Squeak / Pharo flavour), implementasikan metode ini dalam Integer ( 86 karakter)

countFriday13^(1to:12)count:[:m|(Date year:self month:m day:13)dayOfWeekName='Friday']

Kemudian gunakan seperti ini: 2014countFriday13.

Tentu saja, kita bisa menggunakan nama yang lebih pendek, tetapi itu bukan Smalltalk


0

C ++ - Terlalu banyak byte :(

Saya mencoba solusi yang tidak menggunakan perpustakaan tanggal apa pun.

Saya menemukan solusi yang cukup keren (jika saya bisa mengatakannya sendiri). Sayangnya saya tidak bisa mendapatkannya lebih pendek dari ini, yang benar-benar mengganggu saya karena rasanya harus ada cara yang lebih baik.

Solusinya bergantung pada algoritma ini yang hanya 44 byte dalam dirinya sendiri. Sayangnya saya perlu 100 byte untuk membungkusnya dengan baik ...

#include<stdlib.h>
main(int,char**v){int f=0,d,m,y;for(m=1;m<13;++m)d=13,y=atoi(v[1]),(d+=m<3?y--:y-2,23*m/9+d+4+y/4-y/100+y/400)%7-5||++f;return f;}

Output melalui kode kembali (dalam C ++, menggunakan coutatau printfatau sesuatu seperti itu membutuhkan lain #include, yang akan meledakkan solusi bahkan lebih).

Driver / program pengujian:

# Make sure we're not running an old version
rm doomsday.exe

gcc doomsday.cpp -o doomsday.exe

./doomsday.exe 1776
echo 1766: $?

./doomsday.exe 2012
echo 2013: $?

./doomsday.exe 2013
echo 2013: $?

./doomsday.exe 2014
echo 2014: $?

echo `wc doomsday.cpp -c` characters

Output dari program driver:

$ ./test_doomsday 
1766: 2
2013: 3
2013: 2
2014: 1
150 doomsday.cpp characters

Saya menghitung 88 untuk algoritme, bukan 44. Apakah algoritme itu dan apa warppingnya? ($m<3?$y--:$y-2)+3alih-alih d=13,, d+=m<3?y--:y-2,dan d+4harus bekerja juga dan menghemat banyak. +5bukannya +3dan -5harus bekerja juga dan menyimpan 2 byte. for(m=0;++m<13;)menghemat satu byte. Pindah m=0ke kepala fungsi menyimpan byte lain; dan pindah ()%7||++fke kepala loop menyimpan yang lain. Turun dari 149 ke 136 byte.
Titus

0

Clojure, 207 187 bytes

-20 byte dengan menyingkirkan import, dan beberapa spasi putih saya lewatkan.

(import '[java.time LocalDate DayOfWeek])#(loop[d(LocalDate/parse(str %"-01-01"))c 0](if(=(.getYear d)%)(recur(.plusDays d 1)(if(and(=(.getDayOfMonth d)13)(= (.getDayOfWeek d) DayOfWeek/FRIDAY))(inc c)c))c))

Mulai tanggal 1 Janauari pada tahun tertentu, ia berulang setiap hari. Jika hari itu adalah hari Jumat tanggal 13, itu menambah hitungan. Itu terus berulang sampai mencapai tahun berikutnya.

(import '[java.time LocalDate DayOfWeek])

(defn count-friday-13ths [year]
  (loop [d (LocalDate/parse (str year "-01-01")) ; Starting date
         c 0] ; The count
    (if (= (.getYear d) year) ; If we haven't moved onto the next year...
      (recur (.plusDays d 1) ; Add a day...
             (if (and (= (.getDayOfMonth d) 13) ; And increment the count if it's Friday the 13th
                      (= (.getDayOfWeek d) DayOfWeek/FRIDAY))
               (inc c) c))
      c))) ; Return the count once we've started the next year.

0

PHP, tanpa builtin, 81 byte

echo 0x5da5aa76d7699a>>(($y=$argn%400)+($y>102?$y>198?$y>299?48:32:16:0))%28*2&3;

Jalankan dengan echo <year> | php -nR '<code>'.

kerusakan

Hari kerja ulangi setiap 400 tahun.
Dalam hasil untuk 1600 hingga 1999 (misalnya), ada periode 28-panjang dengan hanya tiga celah:

  0:2212122131132131222211221311
 28:2212122131132131222211221311
 56:2212122131132131222211221311
 84:2212122131132131122
103:       131132131222211221311
124:2212122131132131222211221311
152:2212122131132131222211221311
180:2212122131132131222
199:       131132131222211221311
220:2212122131132131222211221311
248:2212122131132131222211221311
276:221212213113213122221122
300:            2131222211221311
316:2212122131132131222211221311
344:2212122131132131222211221311
372:2212122131132131222211221311

Setelah menyesuaikan tahun untuk celah ini, kita bisa mendapatkan hasilnya dengan hash sederhana:

$y=$argn%400;foreach([300,199,103]as$k)$y<$k?:$y+=16;
echo"2212122131132131222211221311"[$y%28];

Tidak pendek (95 byte) tetapi cantik. Dan kita bisa bermain golf

  • 4 byte dengan menggunakan rantai terner untuk offset,
  • 8 byte dengan mengkonversi peta hash dari string base4 ke integer,
  • satu lagi dengan menggunakan representasi hex,
  • dan satu dengan menggabungkan ekspresi.

Port jawaban CompuChip C ++ dapat diturunkan hingga 84 byte:for(;++$m<13;23*$m/9+($m<3?$y--:$y-2)+5+$y/4-$y/100+$y/400)%7?:$f++)$y=$argn;echo$f;
Titus

0

Japt -x , 10 byte

CÆ5¥ÐUXD e

Cobalah

CÆ5¥ÐUXD e     :Implicit input of integer U
C              :12
 Æ             :  Map each X in the range [0,C) (months are 0-indexed in JavaScript)
  5¥           :  Check if 5 is equal to
    ÐUXD       :  new Date(U,X,13)
         e     :  0-based index of day of the week
               :Implicitly reduce by addition and output
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.