Bir yıl içinde 13. olan kaç cuma?


28

Buradaki zorluk, bir yıl verilen “13'üncü Cuma” sayısını veren bir program yazmaktır.

Kurallar ve Detaylar:

  • Giriş STDINyaparak veya programınıza iletilen bir argüman olarak giriş yapabilirsiniz .
  • Sonucu çıktılamalısın STDOUT.
  • Girdinin geçerli bir yıl olacağını ve Gregoryen takvimini önceden tarihlemediğini varsayabilirsiniz (bu durumlarda tanımsız davranışa izin verilir).
  • Takvim / Tarih kütüphanelerine izin verilir.

Bu bir , yani en kısa kod (bayt cinsinden) kazanır.

(İlgili meydan okuma bağlantısı)


7
Gerekli girdi aralığı nedir? 1800'den önce çok geçerse, Julian'dan Gregoryan takvimine geçiş konusunda ne gibi varsayımlar yapılmalıdır?
Peter Taylor

@PeterTaylor Bunun hakkında hiç düşünmemiştim. Bir tarih gregorian öncesi tarihler ise tanımsız davranış olabilir.
Cruncher

1
Gregoryen takvimini ilk kabul eden ülkeler, Gregory'nin boğazı sonrasında 1582 Ekim'inde bunu yaptı. Yeni takvimi geç kabul edecek olan ülkeler 20. yüzyıla kadar değişmedi, örneğin Yunanistan 1 Mart 1923'te tanıttı.
Jeppe Stig Nielsen

@JeppeStigNielsen Takvimler ve bunun hakkında pek bir şey bilmiyorum. Onları evlat edinip etmemek, Yunan tarihlerinin ne olduğunu değiştirmez. Kütüphaneler, tahmin ettiğim yöntemlerle tarihleri ​​hesaplayabilmeli mi?
Cruncher

3
Sanırım burada offtopic oluyorum. Anglo-Amerikan programcıları tarafından yazılan birçok kütüphane, Eylül 1752'yi takvimlerin değişiminin "doğru" zamanı olarak kullanmaktadır. Bu, İngiliz İmparatorluğu'nun değiştiği zamandı. Tabii ki, yeni takvim ABD kurulduğunda yapıldı. (Merak olarak, bazı SQL yazılımları Eylül 1752 sorunuyla baş etmek istemediklerinden, asgari yıl olarak 1753'e sahiptir.) Ancak, Eylül 1752'yi kullanmak oldukça anglo-merkezlidir. Haklısınız Gregorian tarihleri, tarihsel olarak kullanılmış olsun olmasın aynıdır. Bu sözde proleptik Gregoryen takvimi.
Jeppe Stig Nielsen

Yanıtlar:


3

APL (Dyalog APL) ile cal gelen dfns , 29 bayt

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

Çevrimiçi deneyin!

⍳ 12 tam sayılar bir ile on iki arasında

⎕ ,¨ sayısal girdi almak ve on iki sayının her birine hazırlanmak

{ Çiftlerin her birine, işlevi uygulayın…

cal⍵ o yıl için bir takvim al

2 ↓ iki satır bırak (başlık ve günler)

 transpose (satırlar yerine sütunlara hitap edebiliyoruz)

¯5 ↑ son beşi alın (cuma ve cumartesi her biri için iki rakam ve bir boşluk)

3 ↑ ilk ikisini al (cuma için iki hane artı bir boşluk)

 devrik (böylece okuma sırası alıyoruz)

, sökülmek

 APL ifadesi olarak çalıştır (cuma günlerinin listesini verir)

13 ∊ on üç bu listenin bir üyesi mi?

+/ 12 Boole'yu topla


@ Wrzlprmft algoritmasını kullanarak , 53 baytlık kütüphaneler olmadan yapabiliriz:

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

-∘0 1 sıfır ve bir çıkarma

400 100 4 ∘.| iki yıl boyunca bölme kalan tablosu (bu yana) bu sayılara bölünerek (aşağı)

0 ≠.= iç "ürün" 0 ile, ancak + yerine ≠ ve = kullanılarak

⊢ , değiştirilmemiş tartışma yılını hazırlamak

2 3 ¯1 +.× bu sayılarla iç ürün

14 | kalan bölüm on dörte bölündüğünde

'21232211321211' ⌷⍨ bu dizine dizine ekle


29 karakter, ancak bunlar 1 byte karakterden daha fazla değil mi?
Cruncher

@Cruncher Başlığa açıklayıcı bir bağlantı ekledim. TIO bağlantısını açarsanız, sağda "29 karakter, 29 bayt (SBCS)" yazdığını görürsünüz, yani Tek Bayt Karakter Kümesi.
Adám

Öyleyse, sanırım bu yeni kazanan, soruyu bu kadar uzun zaman sonra kabul edilen cevabı değiştirmek için bu SE'de standart uygulama mı?
Cruncher

@Cruncher Evet. OP'den uzun süre sonra kabul edilmek için sahip olunabilecek rozetler bile var.
17'de

12

Mathematica 49 46 45 44 42

Bir şekilde , saf fonksiyonu : 42 karakter

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

Örnek

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

2


Bir As adlı fonksiyonu : 44 chars

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

Örnekler

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

2
3
2
1


Bir karakter daha kısa:f=DayName@{#,m,6}~Table~{m,12}~Count~Friday&
Mr.Wizard

@ Mr.Wizard Evet. Mathematica'nın birçok ek gösterimi vakasını ayrıştırabilmesi beni şaşırtıyor.
DavidC

David o şaşırtan beni bu yapışık gösterimin benim (aşırı) kullanımını görmedim. : ^) (Örnekler: (1) , (2) )
Mr.Wizard

8

Ruby, 49 48 47 46

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

Düzenleme: Bir karakter, Jan sayesinde bir hafta geriye, bir diğeri Time.new'den Time.gm'ye geçerek tekrar düzenlendi

Düzenleme: biraz daha fazla şaşırtmak pahasına, 46 ile alabilirim

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

5
6ncı cuma sayısını sayarsanız tek char tasarruf
John Dvorak

2
@JanDvorak akıllı!
Histocrat

neden 6 Anlamadım.
NARKOZ

3
6. cuma ise, o zaman 13. cuma da cuma
TwiNight

Sekizinci bir pazar ise, ilk olan da aynı şekilde kullanabilirsiniz Time.gm(m,i).wday<1. Ayrıca, işlevi neden adlandırdığınızı da bilmiyorum.
Lee W,

8

Powershell, 68 63 58 52 50

Bahşiş için teşekkürler Iszi.

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

Ayın ilk günü Pazar ise, 13'ünün Cuma olacağı gerçeğini kullanarak.

Ben de denedim:

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

fakat $argssenaryo bloğunun içinde aynı değil .


1
Ayın ilk gününü kullanma fikrini seviyorum.
Cruncher,

Güzel numara, orada. @ Gerekli değildir.
Iszi

Diğer bir şey, senaryolarımın çoğunda aynı suçlu olduğum halde. Zorluk, girdinin bir argümandan gelebileceğini belirtir. Döngü içinde $nile değiştirin $argsve $n=read-host;tamamen yapmadan yapabilirsiniz . Tasarruf 8. Yukarıda bahsedildiği gibi, @ öğesini kaldırın, 54'e
düştünüz.

Düzeltme: 52 ye kadar geliyor!
Iszi

İkinci senaryonun neden işe yaramadığını anlamaya çalışıyorum ve ben kaybettim. İlginç olan ben dışarı değiştirebilir olmasıdır $argsiçin $inputböylece boru hattından yıla bakış besleyen, ve komut dosyası çalışacağını ama hep 3. verir
Iszi

5

R 76 72 57

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

Kolayca değiştirerek 4'e aşağı bu olsun Can "%a %d")=="Fri 13"ile "%w%d)=="513")bir sayı olarak dow kullanarak ve boşluk kaldırarak.
chmullig

çok takdir!
flodel

+1 seqSadece ayda yapıyor olsam gerçekte burada daha kısa! sum(format(as.Date(paste(scan(),1:12,13,sep="-")),"%w%d")=="513")sadece 65 karakter!
plannapus

vay, <bunun bir karakteri bir tamsayıya zorlayacağını tahmin edemezdim. İyi numara!
Plannapus

@plannapus Oldukça yaygın. Çünkü karakter kodları tüm sayılardır. Java bile int ve char karşılaştırabilir
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

Pazartesi 9, aynı yüzüğü aynı olmayabilir ama aynı şekilde çalışır.

Düzenleme: Bir yıl bir buçuk yıldan datedaha kısa olduğunu fark etmek datetime:)


Gerçekten güzel bir çözüm!
leancz

2
Yaparak bir char kaydedebilirsinizfrom datetime import*
user80551

Güzel! Etkili derecede özdeş bir şeyle sonuçlandım ama exec kaçınıyorum: f=lambda y:sum([date(y,m,13).weekday()==4 for m in range(1,13)]).... Yine de ithalatla aynı büyüklükteki çözüm (86 byte).
iwaseatenbyagrue

5

Herhangi bir kitaplık veya yerleşik tarih işlevi kullanmamak:

Golf Betiği - 51

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

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

Python - 82 79

Temelde aynı algoritma.

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

Bu numarayı kullanarak , bu daha fazla golf oynayabilir:

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

Bu durum, takvim bakımından, son günleriyle ve sıçrayanlar tarafından ayırt edilebilecek yalnızca 14 farklı yılın olduğu gerçeğini kullanıyor. lArgüman yıllarına kadar olan atılım yıllarının sayısını hesaplar (Gregoryen takvimi 1 yılına geriye doğru uzanırsa). (2*i+3*l(i)-l(i-1))%14kısacası l(i)-l(i-1)+(i+l(i))%7*2, burada l(i)-l(i-1)argümanın artık bir yıl olup olmadığını ve i+l(i)son günün değişimlerini özetlediğini söyler (normal bir yılda bir, artık yılda iki).


Bu benim ilk golfscript golfüm olduğu için, daha aşağı golf oynamak için herhangi bir ipucunu takdir ediyorum.
Wrzlprmft

Aslında sadece 14 eşsiz yıl olduğu gerçeğini kullanarak böyle bir çözümü düşünüyordum, ancak bunu rekabetçi hale getirmek için en iyi dilin olduğundan emin değildim. Bence bu kütüphanesiz en kısa cevap. Eğer artık yıllar her 4 yılda bir aynı ise, bununla kazanabilirsiniz
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]-'`');}

En kısa cevap değil, kütüphane kullanmıyor.


Hey, ungolfed cevabını bir açıklama ile anlatmaya hazır mısın? Tam olarak ne yaptığınızla ilgileniyorum
Cruncher

1
@Cruncher, Gregoryen takviminin 400 yıllık bir dönemi takip etmesi temelinde bir arama tablosu.
Peter Taylor

1
Daha açık bir şekilde (ve daha uzun), C #: static char GetNumberOfFriday13s(int year) { const string perpetualCalendar = "1221212213113213122221122131122121221311321312222112213112212122131132131222211221311221212213113213112213113213122221122131122121221311321312222112213112212122131132131222211221311221212213113213122213113213122221122131122121221311321312222112213112212122131132131222211221311221212213113213122221122213122221122131122121221311321312222112213112212122131132131222211221311221212213113213122221122131"; return perpetualCalendar[year % 400];. Negatif yıllar boyunca işe yaramayacak.
Jeppe Stig Nielsen,

Sevimli! Küçük bir böcek gibi v[0]olmalı v[1]. Bunu biraz da golf oynayabilirsiniz; kullanmayı strcat, karakterleri doğrudan yazdırmak için saklamayı ve karakter a[]sabitleri yerine sayısal sabitleri çıkarmayı düşünün . :)
user1354557 11:13

1
Ben de sıkıştırmayı geliştirdim: 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 11:13

4

C ( 151 145 137 131 130 karakter)

Yerleşik takvim araçlarını kullanmayan tek bir çözüm olduğunu görmek beni şaşırttı. İşte C de (oldukça karışık) bir matematiksel yaklaşım:

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

(Yukarıdaki GCC’de hatasız derleme)

Alternatif çözüm: C (287-> 215 karakter)

Williham Totland’ın çözümünden ve sıkıştırma kullanımı hoşuma gitti . İki küçük hatayı düzelttim ve uzunluğunu kısaltmak için kodu değiştirdim:

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

seqVarsayılan başlatma ile 10 karakter kaydettiğiniz için teşekkürler @DigitalTrauma 1.

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

(Kullanarak Önceki sürüm echonedeniyle boş hattının mevcut bir hatayı zaman <(echo $1-{1..12}-6$'\n')bugün kadar bu fonksiyon cezası çalıştı Yani. Olan bir Cuma.

Bakalım:

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

Mi yerel o işi yoksa bağımlı, si, sen gerekebilir

export LANG=C

veya

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

Bir işleve; +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

Oradan, eğer fonksiyonum:

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[@]};}

veya

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

Bu yerel bağımlı gibi görünüyor.
Peter Taylor

Evet, bu varsayılan dayanmaktadır C. Ama bir hata var ...
F. Hauri

Printf formatı dizginizden çıkartarak ve bunun yerine \ 'karakterinden kaçarak bir karakter kazanın:%s\\n
Digital Trauma,

1
Ya da seq8 karakter atmak için kullanın :date -f<(seq -f$1-%g-6 1 12)|grep -c ^F
Dijital Travma,

1
Aslında, 2 karakter daha tıraş edebilirsin. Başlangıç ​​sıra numarasını atlarsanız, sıralama varsayılan olarak 1'den başlayacaktır, istediğinizi seçin: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}


1
İyi görünüyor! Sen kaldırarak, daha birkaç byte kaydedebilirsiniz ,b,cişlev bildiriminde dan (! Kaçağı için 's ok golf için vars) olarak da bdökme gibi bir Numberyapabilirsiniz +=testin sonucu yerine &&b++: b+=/^F/.test(new Date(a,c,6)). Ancak, başka bir baytı kurtarabilirsiniz !new Date(a,c,1).getDay()(bu işe getDayyarar çünkü Pazar için 0 döndürür ve 13. gün Cuma ise, 1. Pazar olur) bunun yerine testtamamen 7 bayt kurtarması gerekir!
Dom Hastings

@DomHastings: ipuçları için thx !!!
guy777

3

k

64 karakter

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

Stdin'den okur


Tamam, burada neler oluyor? : P
Williham Totland,

Yılda okuyun, her ayın 13. günü, haftanın sınama günü = cuma günü, toplam
booleanların

3

Ortak Lisp (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))))))

Oh tanrım, asla lisp okuyamazdım ..
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);}

Linq ve 8th Pazar günü kontrol öneri için Jeppe Stig Nielsen için teşekkürler.

>Bunun yerine önerdiğiniz için Danko Durbić'e teşekkür ederiz ==.


Bunun yerine c+=(int)new DateTime(y,i,13).DayOfWeek==5?1:0;, eşdeğerini kullanın c+=new DateTime(y,i,8).DayOfWeek==0?1:0;. İşin püf noktası çıkarmaktır 5, çünkü o zaman oyuncu kadrosundan kurtulabilirsiniz intve sayının 8sayıdan küçük bir hanesi vardır 13. Sekizinci Pazar!
Jeppe Stig Nielsen

Linq ile: int g(int y){return Enumerable.Range(1,12).Count(m=>new DateTime(y,m,8).DayOfWeek==0);}. Tabii bir lambda olarak bu y=>Enumerable.Range(1,12).Count(m=>new DateTime(y,m,8).DayOfWeek==0).
Jeppe Stig Nielsen

Karşılaştırarak bir karakter kaydedebilirsiniz .DayOfWeek<1.
Danko Durbić

@ DankoDurbić Bu, c#cevaba başvurabilir, ancak nasıl uygulanacağından emin değil linq.
Kami

Benim hatam; görünüşe DayOfWeekgöre 0- ' den başka bir tamsayı ile kıyaslayamazsın error CS0019: Operator '<' cannot be applied to operands of type 'System.DayOfWeek' and 'int'.
Danko Durbić

2

PHP, 55 bayt

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

İle koş echo <year> | php -nR '<code>'.

Temel olarak Oleg'in denediği ve Damir Kasipoviç'in yaptığı gibi, daha iyi bir golf oynayarak:
Pazar ile başlayan her ayın 13'ünde bir Cuma var.
Böylece aylar arasında dolaşıyorum ve pazar günleri olan ilk günleri sayıyorum.

Yıkmak

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

Rebol konsolunda kullanım örneği:

>> y: 2012
== 2012

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

13. Cuma günü belirtilen yılda toplanan alternatif çözüm:

>> 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 ve Sed, 39

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

ncal Haftanın günleri soldan aşağıya gelecek şekilde verilen yıl için bir takvim yazdırır.

sedBir ile /gsatırsonu ile tüm 13s dışarı bayrak denizaltılar

grep -c "2" ile başlayan satırları sayar (20, her zaman 13'ü takip eder)

Eski sürümümde bir hata bulduğu ve bir çözüm önerdiği için @DigitalTrauma'ya teşekkürler!


İlgi alanım Çalışmaz - Cuma hatları sadece içerdikleri kez bile basılır birden fazla 13.
Dijital Travma

1
Sanırım böyle bir şeyle yapabileceğimin en iyisi 38:ncal $1|sed /F/s/13/\\n/g|grep -c ^\ 2
Digital Trauma

1
@DigitalTrauma Haklısın. Bir noktada bu senaryo çalışıyordu. düzeltmeme izin ver.
Charles,

1
@DigitalTrauma biraz daha uzun bir sürüm çalışıyor gibi görünüyor. düzeltme için teşekkürler!
Charles,

İlginçtir, önerdiğim alıntı olmayan sed ifadesi GNU sed (Linux) ile çalışır, ancak BSD sed (OSX) ile çalışmaz. GNU versiyonunu seçtiyseniz, taşınabilirlik maliyetinde 1 karakter kazanabilirsiniz.
Dijital Travma

1

Scala, 76 68 karakter

78 karakterde:

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

Hiçbir şey sıradan için büyülü numaralarını kullanmak hariç DAY_OF_WEEK = 7ve FRIDAY = 6.

68 karakter versiyonu:

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

Evet, Java, API'ler arasında haftanın günü sabitlerini değiştirdi.


Çok yazık new java.util.GregorianCalendarolmalı :(
Cruncher

1

Python 195/204

Sadece önceki yıllarda çalışır, çünkü şimdiyemonthdatescalendar kadar verilen yıl için bir takvim döndürür . Bence çok fazla optimizasyon potansiyeli kaldı :).

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)

Başka bir çözüm, her tarih için işe yarar, ancak daha küçük değildir:

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)

İlk örneğinizde, aralık (1,13) olmalıdır, aksi takdirde, 2013'te olduğu gibi 13 Aralık Cuma’nı kaçırırsınız.
leancz

1
Golf oynamaktan bile hoşlanmadın. Bu boşluklardan bazılarını kaldırın.
mbomb007

1

Perl 6, 55 53

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

Eski cevap:

{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

Aramama fikriyle 13thama önce, ve bu olduğu gibi sunday, 03 karakter kazanın! Iszi ve Danko Durbić @ teşekkürler!

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

2010'dan 2017'ye (örnek için) şu şekilde hesaplanabilir:

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

(Tamam, yeni satır yok , ancak istenmedi;)

Eski yazı: 63

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

Eylemde:

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

Gelen Smaltalk (ciyaklamak / Pharo lezzet), Integer, bu yöntemi uygulamak ( 86 karakter)

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

Sonra bu gibi kullanmak: 2014countFriday13.

Elbette, daha kısa bir isim kullanabiliriz, ancak daha sonra Smalltalk olmazdı.


0

C ++ - Çok fazla bayt :(

Herhangi bir tarih kütüphanesinden faydalanmayan bir çözüm denedim.

Oldukça havalı bir çözüm buldum (eğer söyleyebilirimse). Maalesef bundan daha kısa süremiyorum, bu beni gerçekten rahatsız ediyor çünkü daha iyi bir yol olması gerektiğini düşünüyor.

Çözüm , kendi içinde yalnızca 44 bayt olan bu algoritmaya dayanıyor. Ne yazık ki güzel bir şekilde sarmak için 100 bayta daha ihtiyacım var ...

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

Dönüş kodunu kullanarak çıktı (C ++ 'da, veya başka bir şey gerektiren bir şey kullanarak coutveya çözümü daha da uçuracak).printf#include

Sürücü / test programı:

# 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

Sürücü programının çıktısı:

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

Algoritma için 88 sayıyorum, 44 değil. Algoritma nedir ve çözgü nedir? ($m<3?$y--:$y-2)+3yerine d=13,, d+=m<3?y--:y-2,ve d+4aynı zamanda çalışmak ve çok kaydeder olmalıdır. +5yerine +3ve -5çalışması gerekir ve 2 bayt kaydeder. for(m=0;++m<13;)bir bayt kaydeder. m=0İşlev kafasına hareket etmek başka bir bayt kazandırır; ve ()%7||++fdöngü kafasına hareket etmek, bir başkasını kurtarır. 149'dan 136 bayta kadar.
Titus

0

Clojure, 207 187 bayt

-20 bayttan kurtuldum importve bir boşluk bıraktım.

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

Verilen yılın 1 Ocak'ından başlayarak, her gün tekrar eder. Günün 13’ü Cuma ise, sayısı artırır. Gelecek yıla kadar döngü devam ediyor.

(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, yerleşik değil, 81 bayt

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

İle koş echo <year> | php -nR '<code>'.

Yıkmak

Hafta içi her 400 yılda bir tekrarlayın.
1600-1999 (örneğin) sonuçlarında, sadece üç boşluklu 28 uzunlukta bir süre vardır:

  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

Bu boşluklar için yılı ayarladıktan sonra, sonucu basit bir karma ile alabiliriz:

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

Kısa değil (95 bayt) ama güzel. Ve golf oynayabiliriz

  • Ofset için bir üçlü zincir kullanarak 4 bayt,
  • Karma haritasını bir base4 dizgisinden tam sayıya dönüştürerek 8 bayt,
  • hex gösterimini kullanarak bir tane daha,
  • ve biri ifadeleri birleştirerek.

Bir CompuChip C ++ cevabının limanı 84 byte'a kadar indirilebilir: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 bayt

CÆ5¥ÐUXD e

Dene

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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.