Wie viele freitags den 13. in einem Jahr?

28

Ihre Herausforderung besteht darin, ein Programm zu schreiben, das in einem Jahr die Anzahl der "Freitag-13-ten" ausgibt.

Regeln & Details:

  • Sie können Eingaben über STDINoder als Argument an Ihr Programm übergeben.
  • Sie sollten das Ergebnis an ausgeben STDOUT.
  • Sie können davon ausgehen, dass die Eingabe ein gültiges Jahr ist und den gregorianischen Kalender nicht vorbelegt (undefiniertes Verhalten ist in diesen Fällen zulässig).
  • Kalender- / Datumsbibliotheken sind zulässig.

Dies ist ein , also gewinnt der kürzeste Code (in Bytes).

(Link zur zugehörigen Herausforderung)

Cruncher
quelle
7
Was ist der erforderliche Eingabebereich? Wenn es viel vor 1800 geht, welche Annahmen sollten über die Umstellung vom Julianischen auf den Gregorianischen Kalender gemacht werden?
Peter Taylor
@PeterTaylor Ich hatte nicht darüber nachgedacht. Wenn ein Datum vor dem gregorianischen Datum liegt, kann das Verhalten undefiniert sein.
Cruncher
1
Die ersten Länder, die den Gregorianischen Kalender einführten, taten dies im Oktober 1582 nach dem Stier Gregors. Die Länder, die den neuen Kalender spät übernahmen, änderten sich erst im 20. Jahrhundert, zum Beispiel führte Griechenland ihn am 1. März 1923 ein.
Jeppe Stig Nielsen
@JeppeStigNielsen Ich weiß nicht viel über Kalender und so. Ob sie sie adoptierten oder nicht, ändert nichts an den gregorianischen Daten. Bibliotheken sollten in der Lage sein, Daten auf ganz andere Weise zu berechnen, als ich annehme?
Cruncher
3
Ich bin hier wohl offtopisch. Viele Bibliotheken, die von angloamerikanischen Programmierern geschrieben wurden, verwenden den September 1752 als "richtigen" Zeitpunkt für die Änderung von Kalendern. Zu diesem Zeitpunkt änderte sich das britische Empire. Der neue Kalender wurde natürlich bei der Gründung der USA beibehalten. (Aus Neugier hat einige SQL-Software das Jahr 1753 als Mindestjahr, da sie die Ausgabe vom September 1752 nicht bewältigen möchten.) Die Verwendung von September 1752 ist jedoch sehr anglozentrisch. Sie haben recht Gregorianische Daten sind die gleichen, ob sie historisch verwendet wurden oder nicht. Das ist der sogenannte proleptische Gregorianische Kalender.
Jeppe Stig Nielsen

Antworten:

3

APL (Dyalog APL) mit cal von dfns , 29 Bytes

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

Probieren Sie es online!

⍳ 12 die ganzen Zahlen eins bis zwölf

⎕ ,¨ Nehmen Sie die numerische Eingabe und stellen Sie jede der zwölf Zahlen voran

{… Wende  auf jedes der Paare die Funktion an…

cal⍵ Holen Sie sich einen Kalender für das Jahr-Monat

2 ↓ Füge zwei Zeilen ein (Beschriftung und Tage)

 transponieren (damit wir Spalten statt Zeilen ansprechen können)

¯5 ↑ nimm die letzten fünf (jeweils zwei Ziffern für Freitag und Samstag plus ein Leerzeichen)

3 ↑ nimm die ersten zwei (zwei Ziffern für Freitag plus ein Leerzeichen)

 transponieren (so bekommen wir Lesereihenfolge)

, ravel

 Als APL-Ausdruck ausführen (Liste der Freitagsdaten)

13 ∊ Ist 13 ein Mitglied dieser Liste?

+/ summiere die 12 Booleschen


Mit dem @ Wrzlprmft-Algorithmus können wir 53 Bytes lang ohne Bibliotheken arbeiten:

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

-∘0 1 subtrahieren Sie null und eins

400 100 4 ∘.| Divisionsresttabelle für die zwei Jahre (quer) geteilt durch diese Zahlen (runter)

0 ≠.= inneres "Produkt" mit 0, aber mit ≠ und = anstelle von +. ×

⊢ , stellen Sie das nicht geänderte Argument Jahr voran

2 3 ¯1 +.× inneres Produkt mit diesen Zahlen

14 | Division Rest, wenn durch vierzehn geteilt

'21232211321211' ⌷⍨ Index in diese Zeichenfolge

Adam
quelle
Es sind 29 Zeichen, aber das sind mehr als 1 Byte Zeichen, oder?
Cruncher
@Cruncher Ich habe einen erklärenden Link in der Überschrift hinzugefügt. Wenn Sie den TIO-Link öffnen, sehen Sie rechts "29 Zeichen, 29 Byte (SBCS)", dh Single Byte Character Set.
Adám
Nun, ich denke, dies ist der neue Gewinner. Ist es in dieser SE üblich, die akzeptierte Antwort so lange nach der Frage zu ändern?
Cruncher
@Cruncher Ja. Und es gibt sogar Abzeichen, um lange nach dem OP akzeptiert zu werden.
Adám
12

Mathematica 49 46 45 44 42

Als reine Funktion : 42 Zeichen

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

Beispiel

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

2


Als benannte Funktion : 44 Zeichen

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

Beispiele

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

2
3
2
1

DavidC
quelle
Ein Zeichen kürzer:f=DayName@{#,m,6}~Table~{m,12}~Count~Friday&
Mr.Wizard
@ Mr.Wizard Ja. Es überrascht mich, dass Mathematica die vielen Fälle der Infixnotation analysieren kann.
DavidC
David, es überrascht mich, dass du nicht gesehen hast, wie ich diese verbundene Notation (über) gebraucht habe. : ^) (Beispiele: (1) , (2) )
Mr.Wizard
8

Ruby, 49 48 47 46

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

Bearbeiten: Rasierte einen Charakter, indem er dank Jan eine Woche zurückging, und einen anderen, indem er von Time.new zu Time.gm wechselte

Edit: Auf Kosten der Verschleierung ein bisschen mehr, kann ich mit bis 46 bekommen

f=->m{(1..12).count{|i|Time.gm(m,i,8).wday<1}}
Histokrat
quelle
5
Ein-Zeichen-Ersparnis, wenn Sie die Anzahl der Freitag, den 6.
John Dvorak
2
@ JanDvorak klug!
Histokrat
warum 6? Ich habe es nicht verstanden.
NARKOZ
3
Wenn der 6. ein Freitag ist, dann ist der 13. auch ein Freitag
TwiNight
Wenn der 8. ein Sonntag ist, dann ist auch der 1., und so können Sie verwenden Time.gm(m,i).wday<1. Außerdem weiß ich nicht, warum Sie die Funktion benennen.
Lee W
8

Powershell, 68 63 58 52 50

Danke Iszi für den Tipp.

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

Wenn der erste Tag im Monat der Sonntag ist, ist der 13. der Freitag.

Ich habe auch versucht:

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

Aber es ist nicht dasselbe $argsinnerhalb des Skriptblocks.

Danko Durbić
quelle
1
Mir gefällt die Idee, den ersten Tag des Monats zu nutzen.
Cruncher
Netter Trick, da. Das @ ist jedoch nicht erforderlich.
Iszi
Eine andere Sache, obwohl ich mich in vielen meiner Skripte derselben schuldig gemacht habe. Die Abfrage gibt an, dass die Eingabe von einem Argument stammen kann. Ersetzen Sie $nmit $argsin der Schleife, und Sie können $n=read-host;ganz darauf verzichten. Speichert 8. Entfernen Sie @, wie oben erwähnt, und Sie sind auf 54.
Iszi
Korrektur: Kommt auf 52!
Iszi
Ich versuche herauszufinden, warum Ihr zweites Skript nicht funktioniert und ich bin ratlos. Was interessant ist, ist, dass ich wechseln kann, $argsum $inputdas Jahr aus der Pipeline
einzugeben
5

R 76 72 57

sum(format(as.Date(paste(scan(),1:12,1,sep="-")),"%w")<1)
Flodel
quelle
Kann leicht , indem du deinen Ersatz nach unten 4 erhalten "%a %d")=="Fri 13"mit "%w%d)=="513")von dow als Zahl verwendet wird , und die Räume zu entfernen.
chmullig
sehr geschätzt!
Flodel
+1 Obwohl es seqhier eigentlich kürzer ist , das Einzige im Monat zu tun ! sum(format(as.Date(paste(scan(),1:12,13,sep="-")),"%w%d")=="513")ist nur 65 Zeichen!
Plannapus
Wow, ich hätte nicht gedacht, dass <das ein Zeichen zu einer ganzen Zahl machen würde. Guter Trick!
Plannapus
@plannapus Es ist eher üblich. Da Zeichencodes alle Zahlen sind. Sogar Java kann int und char vergleichen
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

Montag, der 9., hat vielleicht nicht ganz den gleichen Klang, funktioniert aber genauso gut.

Edit: Anderthalb Jahre zu bemerken, dass dateist kürzer als datetime:)

ejrb
quelle
Wirklich schöne Lösung!
Leancz
2
Sie können ein from datetime import*
Zeichen
Nett! Ich endete mit etwas effektiv identisch, aber Vermeidung von exec: f=lambda y:sum([date(y,m,13).weekday()==4 for m in range(1,13)]).... Die gleiche Größe Lösung mit dem Import (86 Bytes), obwohl.
iwaseatenbyagrue
5

Keine Bibliotheken oder integrierten Datumsfunktionen verwenden:

Golfscript - 51

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

' [3/=RI[)a%:*.' könnte genauso gut sein 'feefefgeeffgfe'

Python - 82 79

Im Wesentlichen derselbe Algorithmus.

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

Mit diesem Trick können Sie weiter spielen, um:

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

Dies nutzt die Tatsache aus, dass es kalenderweise nur 14 verschiedene Jahre gibt, die an ihrem letzten Tag erkennbar sind und ob sie springen. lberechnet die Anzahl der Schaltjahre bis zu seinem Argument (wenn der Gregorianische Kalender rückwärts auf das Jahr 1 ausgedehnt wurde). (2*i+3*l(i)-l(i-1))%14steht für l(i)-l(i-1)+(i+l(i))%7*2, wo steht l(i)-l(i-1), ob das Argument ein Schaltjahr ist und i+l(i)fasst die Schichten des letzten Tages zusammen (eine in einem normalen Jahr, zwei in einem Schaltjahr).

Wrzlprmft
quelle
Da dies mein erstes Golfscript-Golf ist, würde ich mich über Hinweise zum weiteren Golfspielen freuen.
Wrzlprmft
Ich habe über eine solche Lösung nachgedacht, indem ich die Tatsache ausgenutzt habe, dass es tatsächlich nur 14 einzigartige Jahre gibt, aber ich war mir nicht sicher, welche Sprache am besten geeignet ist, um wettbewerbsfähig zu sein. Ich denke, dies ist die kürzeste Antwort ohne Bibliotheken. Wenn die Schaltjahre alle 4 Jahre einheitlich wären, könnten Sie möglicherweise damit gewinnen
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]-'`');}

Nicht die kürzeste Antwort, verwendet aber keine Bibliotheken.

Williham Totland
quelle
Hey, wären Sie bereit, die ungelöste Antwort mit einer Erklärung zu versehen? Ich bin daran interessiert, was genau du getan hast
Cruncher
1
@Cruncher, es ist eine Nachschlagetabelle auf der Grundlage, dass der Gregorianische Kalender einem 400-Jahres-Zyklus folgt.
Peter Taylor
1
Deutlicher ausgedrückt (und länger), C #: static char GetNumberOfFriday13s(int year) { const string perpetualCalendar = "1221212213113213122221122131122121221311321312222112213112212122131132131222211221311221212213113213112213113213122221122131122121221311321312222112213112212122131132131222211221311221212213113213122213113213122221122131122121221311321312222112213112212122131132131222211221311221212213113213122221122213122221122131122121221311321312222112213112212122131132131222211221311221212213113213122221122131"; return perpetualCalendar[year % 400];. Wird nicht für negative Jahre arbeiten.
Jeppe Stig Nielsen
Süß! Da sollte ein kleiner Bug dabei v[0]sein v[1]. Sie können auch ein bisschen Golf spielen; strcatZiehen Sie in Betracht , Zeichen zum direkten Drucken zu verwenden , zu speichern a[]und statt Zeichenkonstanten numerische Konstanten zu subtrahieren. :)
user1354557
1
Ich habe auch die Komprimierung verbessert: 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 Zeichen)
user1354557
4

C ( 151 145 137 131 130 Zeichen)

Ich bin überrascht zu sehen, dass es nur eine andere Lösung gibt, die keine integrierten Kalender-Tools verwendet. Hier ist ein (stark verschleierter) mathematischer Ansatz, auch in 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));}

(Die oben genannten kompiliert in GCC ohne Fehler)

Alternative Lösung: C (287-> 215 Zeichen)

Mir hat die Lösung von Williham Totland und die Komprimierung sehr gut gefallen . Ich habe zwei kleine Fehler behoben und den Code angepasst, um seine Länge zu verkürzen:

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]);}
user1354557
quelle
4

PHP, 82

<?for($i=1,$c=0;$i<13;$i++)$c+=(date("N",mktime(0,0,0,$i,1,$argv[1]))==7);echo $c;

Beyogen auf

"Jeder Monat, der an einem Sonntag beginnt, enthält einen Freitag, den 13., und es gibt mindestens einen Freitag, den 13., in jedem Kalenderjahr."

Aus http://en.wikipedia.org/wiki/Friday_the_13th

Damir Kasipovic
quelle
4

Bash 47 36

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

Vielen Dank an @DigitalTrauma für das Speichern von 10 Zeichen seqmit der Standardeinstellung start to 1.

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

(Vorherige Version mit echogegenwärtig einen Fehler wegen der leeren Zeile , wenn <(echo $1-{1..12}-6$'\n'). Also diese Funktion funktionierte gut , bis heute ist ein Freitag.

Wir werden sehen:

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

Ist abhängig vom Gebietsschema , und wenn es nicht funktioniert, müssen Sie es möglicherweise tun

export LANG=C

oder

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

In eine Funktion; +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

Von dort, wenn meine Funktion wird:

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

oder

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
F. Hauri
quelle
Dies scheint vom Gebietsschema abhängig zu sein.
Peter Taylor
Ja, dies basiert auf der Standardeinstellung C. Aber es gibt einen Fehler ...
F. Hauri
Speichern Sie ein Zeichen, indem Sie Ihre printf-Format-Zeichenfolge in Anführungszeichen setzen und stattdessen das Zeichen \ maskieren:%s\\n
Digitales Trauma,
1
Oder verwenden Sie seq, um 8 Zeichen fallen zu lassen:date -f<(seq -f$1-%g-6 1 12)|grep -c ^F
Digital Trauma
1
Tatsächlich können Sie 2 weitere Zeichen abschneiden. Wenn Sie die Startsequenznummer weglassen, beginnt die Sequenz standardmäßig bei 1, was Sie möchten:seq -f$1-%g-6 12|date -f-|grep -c ^F
Digitales Trauma,
4

JavaScript, 70

f=function(a){b=0;for(c=12;c--;)b+=!new Date(a,c,1).getDay();return b}
guy777
quelle
und warum ist es -1?
Lukasz 'Severiaan' Grela
1
Sieht gut aus! Sie können noch ein paar Bytes speichern, indem ,b,caus der Funktionsdeklaration (! Es ist in Ordnung zu Leck Vars für Golf), auch bgegossen als NumberSie können +=das Ergebnis des Tests statt der &&b++: b+=/^F/.test(new Date(a,c,6)). Sie können jedoch ein anderes Byte speichern, indem Sie !new Date(a,c,1).getDay()(dies funktioniert, weil getDayfür Sonntag 0 zurückgegeben wird und wenn der 13. ein Freitag ist, ist der 1. ein Sonntag) anstelle dessen, testwas Sie insgesamt 7 Bytes sparen sollten!
Dom Hastings
@DomHastings: danke für eure tipps !!!
guy777
3

k

64 Zeichen

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

Liest von stdin

Skeevey
quelle
Ok, nur was ist hier los? : P
Williham Totland
Lesen Sie im Jahr, erstellen Sie eine Liste der Daten des 13. Tages eines jeden Monats, testen Sie den Wochentag = Freitag, summieren Sie die resultierende Liste der Booleschen
skeevey
3

Common 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))))))
Pål GD
quelle
Oh Gott, ich konnte nie lispeln lesen.
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);}

Vielen Dank an Jeppe Stig Nielsen für den Link und den Vorschlag, sich am 8. für den Sonntag zu melden.

Vielen Dank an Danko Durbić für den Vorschlag >statt ==.

Kami
quelle
c+=(int)new DateTime(y,i,13).DayOfWeek==5?1:0;Verwenden Sie stattdessen das Äquivalent c+=new DateTime(y,i,8).DayOfWeek==0?1:0;. Der Trick ist, zu subtrahieren 5, denn dann können Sie den Wurf auf loswerden int, und auch die Zahl 8hat eine Ziffer weniger als die Zahl 13. Sonntag der Achte!
Jeppe Stig Nielsen
Mit Linq: int g(int y){return Enumerable.Range(1,12).Count(m=>new DateTime(y,m,8).DayOfWeek==0);}. Natürlich als Lambda y=>Enumerable.Range(1,12).Count(m=>new DateTime(y,m,8).DayOfWeek==0).
Jeppe Stig Nielsen
Sie können ein Zeichen durch Vergleichen speichern .DayOfWeek<1.
Danko Durbić
@ DankoDurbić Das kann auf die c#Antwort zutreffen, ist sich aber nicht sicher, wie man es anwenden soll linq.
Kami
Mein Fehler; anscheinend kann man es nicht DayOfWeekmit einer anderen ganzen Zahl als 0- vergleichen error CS0019: Operator '<' cannot be applied to operands of type 'System.DayOfWeek' and 'int'.
Danko Durbić
2

PHP, 55 Bytes

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

Laufen Sie mit echo <year> | php -nR '<code>'.

Im Grunde dasselbe wie Oleg und Damir Kasipovic , nur mit besserem Golfspiel:
Jeder Monat, der mit einem Sonntag beginnt, hat einen Freitag, den 13 ..
Also durchlaufe ich die Monate und zähle die ersten Tage, die Sonntage sind.

Nervenzusammenbruch

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
Titus
quelle
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
tmartin
quelle
1

Bash ( 52 47 Zeichen)

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

Rebol, 63

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

Anwendungsbeispiel in der Rebol-Konsole:

>> y: 2012
== 2012

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

Alternative Lösung, die den ganzen Freitag, den 13. im gegebenen Jahr sammelt, ist:

>> 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]
draegtun
quelle
1

Bash und Sed, 39

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

ncal druckt einen Kalender für das angegebene Jahr mit Wochentagen links unten.

sedmit einer /gFlagge werden alle 13er mit Zeilenumbrüchen unterlegt

grep -c zählt die Zeilen, die mit "2" beginnen (20 folgt immer 13)

Vielen Dank an @DigitalTrauma, dass Sie einen Fehler in meiner alten Version gefunden und eine Lösung vorgeschlagen haben!

Nicht dieser Charles
quelle
Funktioniert bei mir nicht ganz - Freitag-Zeilen werden nur einmal gedruckt, auch wenn sie mehr als eine 13 enthalten.
Digitales Trauma
1
Ich denke, das Beste, was ich mit so etwas anfangen kann, ist 38:ncal $1|sed /F/s/13/\\n/g|grep -c ^\ 2
Digitales Trauma
1
@DigitalTrauma Du hast recht. Irgendwann funktionierte dieses Skript. Lass es mich reparieren.
Nicht dass Charles
1
@DigitalTrauma scheint eine viel längere Version zu haben. danke für die verlegenheit!
Nicht dass Charles
Interessanterweise funktioniert der nicht zitierte Ausdruck sed, den ich vorgeschlagen habe, mit GNU sed (Linux), aber nicht mit BSD sed (OSX). Ich denke, Sie können 1 Zeichen auf Kosten der Portabilität gewinnen, wenn Sie die GNU-Version wählen.
Digital Trauma
1

Scala, 76 68 Zeichen

In 78 Zeichen:

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

Nichts Außergewöhnliches, außer magische Zahlen für DAY_OF_WEEK = 7und zu verwenden FRIDAY = 6.

Version mit 68 Zeichen:

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

Ja, Java hat die Werte der Wochentagskonstanten zwischen den APIs geändert.

Karol S
quelle
Es ist eine Schande new java.util.GregorianCalendar, muss so lange dauern :(
Cruncher
1

Python 195/204

Funktioniert nur für frühere Jahre, da monthdatescalendarbis jetzt ein Kalender für das angegebene Jahr zurückgegeben wird . Ich denke, es gibt noch viel Optimierungspotential :).

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)

Eine andere Lösung, die für jedes Datum geeignet ist, aber nicht kleiner ist:

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)
klingt.net
quelle
In Ihrem ersten Beispiel sollte der Bereich (1,13) sein, sonst würden Sie den 13. Dezember verpassen, wie im Jahr 2013.
leancz
1
Sie haben sich nicht einmal die Mühe gemacht, Golf zu spielen. Entfernen Sie einige dieser Leerzeichen.
mbomb007
1

Perl 6, 55 53

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

Alte Antwort:

{sum (1..12).map: {Date.new($_,$^a,13).day-of-week==5}}
bb94
quelle
48 Bytes
Jo King
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
leancz
quelle
0

Perl + lib POSIX 55

Mit dem Gedanken, nicht erst zu suchen 13th, und wie es sundayist, 0lassen Sie 3 Zeichen sparen! Danke @ Iszi und Danko Durbić!

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

Könnte 2010 bis 2017 (als Beispiel) folgendermaßen berechnen:

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

(Ok, es gibt kein Newline , aber das wurde nicht gefragt;)

Alter Beitrag: 63

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

In Aktion:

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
F. Hauri
quelle
0

In Smalltalk (Squeak / Pharo Aroma), implementieren diese Methode in Integer ( 86 Zeichen)

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

Dann verwenden Sie es wie folgt aus : 2014countFriday13.

Natürlich könnten wir einen kürzeren Namen verwenden, aber dann wäre es nicht Smalltalk

aka.nice
quelle
0

C ++ - Zu viele Bytes :(

Ich habe eine Lösung ausprobiert, die keine Datumsbibliotheken verwendet.

Ich fand eine ziemlich coole (wenn ich so sagen darf) Lösung. Leider kann ich es nicht kürzer machen, was mich wirklich nervt, weil ich das Gefühl habe, dass es einen besseren Weg geben sollte.

Die Lösung hängt von diesem Algorithmus ab, der nur 44 Byte umfasst. Leider brauche ich noch 100 Bytes, um es schön zu verpacken ...

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

Ausgabe über den Rückkehrcode (in C ++ erfordert die Verwendung von coutoder printfetwas Ähnliches ein anderes #include, was die Lösung noch mehr in die Luft jagen würde).

Treiber / Testprogramm:

# 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

Ausgabe des Treiberprogramms:

$ ./test_doomsday 
1766: 2
2013: 3
2013: 2
2014: 1
150 doomsday.cpp characters
CompuChip
quelle
Ich zähle 88 für den Algorithmus, nicht 44. Was ist der Algorithmus und was ist der Warpping? ($m<3?$y--:$y-2)+3statt d=13,, d+=m<3?y--:y-2,und d+4sollte auch funktionieren und viel sparen. +5statt +3und -5sollte auch funktionieren und spart 2 bytes. for(m=0;++m<13;)spart ein Byte. Wenn Sie m=0zum Funktionskopf wechseln, wird ein weiteres Byte gespeichert. Wenn Sie sich ()%7||++fzum Schleifenkopf bewegen , wird ein anderer gespeichert. Nach unten von 149 auf 136 Bytes.
Titus
0

Clojure, 207 187 Bytes

-20 Bytes durch das Loswerden der importund einige Leerzeichen, die ich verpasst habe.

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

Ab dem 1. Januar des jeweiligen Jahres durchläuft es jeden Tag eine Schleife. Wenn der Tag Freitag der 13. ist, wird die Anzahl erhöht. Die Schleife wird fortgesetzt, bis sie das nächste Jahr erreicht.

(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.
Karzigenat
quelle
0

PHP, keine eingebauten, 81 Bytes

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

Laufen Sie mit echo <year> | php -nR '<code>'.

Nervenzusammenbruch

Die Wochentage wiederholen sich alle 400 Jahre.
In den Ergebnissen für 1600 bis 1999 (zum Beispiel) gibt es einen Zeitraum von 28 Jahren mit nur drei Lücken:

  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

Nachdem wir das Jahr für diese Lücken angepasst haben, können wir das Ergebnis mit einem einfachen Hash erhalten:

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

Nicht kurz (95 Bytes), aber hübsch. Und wir können Golf spielen

  • 4 Bytes unter Verwendung einer ternären Kette für den Offset,
  • 8 Bytes durch Konvertieren der Hash-Map von einer Base4-Zeichenfolge in eine Ganzzahl,
  • eine weitere unter Verwendung der Hex-Darstellung,
  • und eine durch Zusammenführen der Ausdrücke.
Titus
quelle
Ein Port der C ++ - Antwort von CompuChip kann auf 84 Bytes reduziert werden: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 Bytes

CÆ5¥ÐUXD e

Versuch es

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
Zottelig
quelle