Quanti venerdì 13 in un anno?


28

La tua sfida è quella di scrivere un programma che, dato un anno, genera il numero di "Venerdì 13" in esso.

Regole e dettagli:

  • Puoi ricevere input tramite STDINo come argomento passato al tuo programma.
  • Dovresti fornire il risultato a STDOUT.
  • Si può presumere che l'input sarà un anno valido e non precede il calendario gregoriano (in questi casi è consentito un comportamento indefinito).
  • Sono consentite le librerie Calendario / Data.

Questo è un , quindi vince il codice più breve (in byte).

(Link sfida correlato)


7
Qual è l'intervallo richiesto di input? Se va molto prima del 1800, quali ipotesi dovrebbero essere fatte sul passaggio dal calendario giuliano a quello gregoriano?
Peter Taylor,

@PeterTaylor Non ci avevo pensato. Se una data precede gregorian, allora puoi avere un comportamento indefinito.
Cruncher,

1
I primi paesi ad adottare il calendario gregoriano lo fecero nell'ottobre del 1582, in seguito allo stesso toro di Gregorio. I paesi che adottarono il nuovo calendario in ritardo non cambiarono fino al 20 ° secolo, ad esempio la Grecia lo introdusse il 1 ° marzo 1923.
Jeppe Stig Nielsen,

@JeppeStigNielsen Non so molto sui calendari e così via. Che li abbiano adottati o meno non cambia le date di Gregorian. Le biblioteche dovrebbero essere in grado di calcolare le date da molto tempo fa presumo?
Cruncher,

3
Sono offtopico qui, immagino. Molte biblioteche scritte da programmatori anglo-americani usano settembre 1752 come il tempo "corretto" di cambio dei calendari. Questo è stato quando l'impero britannico è cambiato. Il nuovo calendario è stato mantenuto quando sono stati fondati gli Stati Uniti, ovviamente. (Per curiosità, alcuni software SQL hanno il 1753 come anno minimo poiché non vogliono affrontare il problema del settembre 1752). Tuttavia, l'uso del settembre 1752 è altamente anglocentrico. Hai ragione, le date gregoriane sono le stesse sia che siano state usate storicamente o meno. Questo è il cosiddetto calendario gregoriano prolettico .
Jeppe Stig Nielsen,

Risposte:


3

APL (Dyalog APL) con cal da dfns , 29 byte

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

Provalo online!

⍳ 12 gli interi da uno a dodici

⎕ ,¨ accetta input numerici e antepone a ciascuno dei dodici numeri

{...  su ciascuna delle coppie, applica la funzione ...

cal⍵ ottenere un calendario per quell'anno-mese

2 ↓ rilasciare due righe (didascalia e giorni)

 trasporre (in modo che possiamo indirizzare le colonne anziché le righe)

¯5 ↑ prendi le ultime cinque (due cifre per ciascuno di venerdì e sabato più uno spazio)

3 ↑ prendi le prime due (due cifre per venerdì più uno spazio)

 trasporre (quindi otteniamo l'ordine di lettura)

, sfilacciarsi

 eseguire come espressione APL (fornisce un elenco delle date del venerdì)

13 ∊ tredici è un membro di quella lista?

+/ sommare i 12 booleani


Usando l'algoritmo di @ Wrzlprmft , possiamo farlo senza librerie per 53 byte:

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

-∘0 1 sottrarre zero e uno

400 100 4 ∘.| tabella restante divisione per i due anni (attraverso) divisa per questi numeri (giù)

0 ≠.= "prodotto" interno con 0, ma usando ≠ e = invece di +. ×

⊢ , anteponi l'anno dell'argomento non modificato

2 3 ¯1 +.× prodotto interno con questi numeri

14 | resto della divisione quando diviso per quattordici

'21232211321211' ⌷⍨ indice in questa stringa


Ha 29 caratteri, ma questi sono più di 1 byte, giusto?
Cruncher

@ Cruncher Ho aggiunto un link esplicativo nell'intestazione. Se apri il link TIO, vedrai che dice "29 caratteri, 29 byte (SBCS)" sulla destra, ovvero Set di caratteri a byte singolo.
Adám,

Bene, suppongo che questo sia il nuovo vincitore allora, è prassi normale in questo SE cambiare la risposta accettata così a lungo dopo la domanda?
Cruncher

@Cruncher Sì. E ci sono anche badge da ottenere per essere accettati molto dopo l'OP.
Adám

12

Mathematica 49 46 45 44 42

Come pura funzione : 42 caratteri

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

Esempio

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

2


Come funzione denominata : 44 caratteri

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

Esempi

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

2
3
2
1


Un personaggio più corto:f=DayName@{#,m,6}~Table~{m,12}~Count~Friday&
Mr.Wizard l'

@ Mr.Wizard Sì. Mi sorprende che Mathematica possa analizzare i molteplici casi di notazione infografica.
DavidC,

David sorprende me che non avete visto la mia (più) l'uso di questa notazione congiunti. : ^) (Esempi: (1) , (2) )
Mr.Wizard l'

8

Ruby, 49 48 47 46

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

Modifica: rasati un personaggio tornando indietro di una settimana, grazie a Jan, e un altro passando da Time.new a Time.gm

Modifica: a spese di offuscarlo un po 'di più, posso arrivare a 46 con

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

5
risparmio di un carattere se si contano i numeri del venerdì 6
John Dvorak

2
@JanDvorak clever!
istocratico,

perché 6? Non l'ho capito.
NARKOZ,

3
Se il 6 è venerdì, anche il 13 è venerdì
TwiNight

Se l'ottava è una domenica, allora lo è anche la prima, e quindi puoi usarla Time.gm(m,i).wday<1. Inoltre, non so perché stai nominando la funzione.
Lee W,

8

Powershell, 68 63 58 52 50

Grazie Iszi per l'informazione.

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

Utilizzando il fatto che se il 1 ° giorno del mese è domenica, il 13 sarà venerdì.

Ho anche provato:

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

ma non è lo stesso $argsall'interno del blocco di script.


1
Mi piace l'idea di usare il primo giorno del mese.
Cruncher,

Bel trucco, lì. La @ non è necessaria, però.
Iszi,

Un'altra cosa, sebbene io sia colpevole della stessa cosa in molti dei miei script. La sfida specifica che l'input può provenire da un argomento. Sostituisci $ncon $argsnel ciclo e puoi farne a meno $n=read-host;. Salva 8. Rimuovi @, come menzionato sopra, e sei
arrivato

Correzione: scende a 52!
Iszi,

Sto cercando di capire perché la tua seconda sceneggiatura non funzionerà e sono in perdita. La cosa interessante è che posso cambiare fuori $argsper $input, alimentando così l'anno dalla tubazione, e lo script verrà eseguito ma emette sempre 3.
Iszi

5

R 76 72 57

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

Possono facilmente ottenere questo giù 4 sostituendo il tuo "%a %d")=="Fri 13"con "%w%d)=="513")utilizzando dow come un numero, e rimuovendo gli spazi.
Chmullig,

molto apprezzato!
flodel l'

+1 Anche se fare l' sequnico mese è in realtà più breve qui! sum(format(as.Date(paste(scan(),1:12,13,sep="-")),"%w%d")=="513")ha solo 65 caratteri!
plannapus,

wow non avrei indovinato che <avrebbe costretto un personaggio a un numero intero. Bel trucco!
plannapus,

@plannapus È piuttosto comune. Poiché i codici carattere sono tutti numeri. Anche java può confrontare int e char
Cruncher l'

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

Lunedì 9 potrebbe non avere lo stesso squillo ma funziona altrettanto bene.

Modifica: un anno e mezzo per notare che dateè più breve di datetime:)


Soluzione davvero bella!
leancz,

2
Puoi salvare un carattere facendofrom datetime import*
user80551

Bello! Ho finito con qualcosa di effettivamente identico, ma evitando exec: f=lambda y:sum([date(y,m,13).weekday()==4 for m in range(1,13)]).... Soluzione della stessa dimensione con l'importazione (86 byte), però.
Iwaseatenbyagrue,

5

Non utilizzare alcuna libreria o funzione di data integrata:

Golfscript - 51

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

' [3/=RI[)a%:*.' potrebbe anche essere 'feefefgeeffgfe'

Python - 82 79

Essenzialmente lo stesso algoritmo.

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

utilizzando questo trucco , questo può essere ulteriormente approfondito per:

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

Questo sfrutta il fatto che, per quanto riguarda il calendario, ci sono solo 14 anni diversi, che si distinguono per il loro ultimo giorno e se stanno saltando. lcalcola il numero di anni bisestili fino al suo argomento (se il calendario gregoriano si estendeva all'indietro fino all'anno 1). (2*i+3*l(i)-l(i-1))%14è l'abbreviazione di l(i)-l(i-1)+(i+l(i))%7*2, dove l(i)-l(i-1)ci dice se l'argomento è un anno bisestile ei+l(i) riassume i turni dell'ultimo giorno (uno in un anno normale, due in un anno bisestile).


Dal momento che questo è il mio primo golfscript golf, apprezzerei ogni suggerimento per continuare a giocare a golf.
Wrzlprmft,

Stavo pensando a una soluzione del genere utilizzando il fatto che in realtà ci sono solo 14 anni unici, ma non ero sicuro del miglior linguaggio per renderlo competitivo. Penso che questa sia la risposta più breve senza librerie. Se gli anni bisestili fossero uniformemente ogni 4 anni, potresti essere in grado di vincere con questo
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]-'`');}

Non è la risposta più breve, ma non utilizza librerie.


Ehi, saresti disposto a fornire una risposta senza risposta con una spiegazione? Sono interessato a quello che hai fatto esattamente
Cruncher l'

1
@Cruncher, è una tabella di ricerca sulla base del fatto che il calendario gregoriano segue un ciclo di 400 anni.
Peter Taylor,

1
Più esplicitamente (e più), C #: static char GetNumberOfFriday13s(int year) { const string perpetualCalendar = "1221212213113213122221122131122121221311321312222112213112212122131132131222211221311221212213113213112213113213122221122131122121221311321312222112213112212122131132131222211221311221212213113213122213113213122221122131122121221311321312222112213112212122131132131222211221311221212213113213122221122213122221122131122121221311321312222112213112212122131132131222211221311221212213113213122221122131"; return perpetualCalendar[year % 400];. Non funzionerà per anni negativi.
Jeppe Stig Nielsen,

Carino! Come un piccolo bug, v[0]dovrebbe essere v[1]. Puoi anche giocare a golf un po '; considerare l'utilizzo strcat, l'archiviazione di caratteri per la stampa diretta a[]e la sottrazione di costanti numeriche anziché costanti di caratteri. :)
user1354557 l'

1
Ho migliorato anche la compressione: 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 caratteri)
user1354557 l'

4

C ( 151 145 137 131 130 caratteri)

Sono sorpreso di vedere che esiste solo un'altra soluzione che non utilizza gli strumenti di calendario integrati. Ecco un approccio matematico (altamente offuscato), anche 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));}

(Quanto sopra viene compilato in GCC senza errori)

Soluzione alternativa: C (287-> 215 caratteri)

Mi è piaciuta molto la soluzione di Williham Totland e il suo uso della compressione. Ho corretto due piccoli bug e modificato il codice per accorciarne la lunghezza:

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

Grazie a @DigitalTrauma per aver salvato 10 caratteri utilizzando seqcon l'avvio predefinito 1.

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

(La versione precedente utilizzava echoun bug a causa della riga vuota quando <(echo $1-{1..12}-6$'\n'). Quindi questa funzione ha funzionato bene fino ad oggi è un venerdì.

Vediamo:

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

E 'è locale dipende, SI Se non fare il lavoro, potrebbe essere necessario

export LANG=C

o

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

In una funzione; +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

Da lì, se la mia funzione diventa:

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

o

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

Questo sembra essere dipendente dalla locale.
Peter Taylor,

Sì, si basa sul valore predefinito C. Ma c'è un bug ...
F. Hauri,

Salva un carattere annullando l'annullamento della stringa del formato di stampa e sfuggendo al \ invece:%s\\n
Digital Trauma

1
Oppure usa seqper eliminare 8 caratteri:date -f<(seq -f$1-%g-6 1 12)|grep -c ^F
Digital Trauma

1
In realtà, puoi radere altri 2 caratteri. Se si omette il numero di sequenza iniziale, seq inizierà automaticamente da 1, che è quello che si desidera:seq -f$1-%g-6 12|date -f-|grep -c ^F
Trauma digitale

4

JavaScript, 70

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

e perché è -1?
Lukasz "Severiaan" Grela,

1
Sembra buono! È possibile salvare un paio di byte, rimuovendo ,b,cdalla dichiarazione di funzione (! Va bene anche perdite vars per il golf), anche come bè lanciato come un Numberpossibile +=risultato di prova al posto del &&b++: b+=/^F/.test(new Date(a,c,6)). Tuttavia, puoi salvare un altro byte, usando !new Date(a,c,1).getDay()(questo funziona perché getDayrestituisce 0 per domenica, e se il 13 è un venerdì, il 1 sarà una domenica) invece del testquale nel complesso dovresti risparmiare 7 byte!
Dom Hastings,

@DomHastings: grazie per i tuoi consigli !!!
guy777,

3

K

64 caratteri

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

Legge da stdin


Ok, cosa sta succedendo qui? : P
Williham Totland,

Leggi nell'anno, costruisci l'elenco delle date del 13 ° giorno di ogni mese, prova il giorno della settimana = venerdì, somma risultante elenco di booleani
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))))))

Oddio, non ho mai saputo leggere 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);}

Grazie a Jeppe Stig Nielsen per Linq e suggerimento di controllare la domenica l'8.

Grazie a Danko Durbić per avermi suggerito >invece di ==.


Invece di c+=(int)new DateTime(y,i,13).DayOfWeek==5?1:0;, utilizzare l'equivalente c+=new DateTime(y,i,8).DayOfWeek==0?1:0;. Il trucco è sottrarre 5, perché in questo modo è possibile eliminare il cast inte anche il numero 8ha una cifra in meno rispetto al numero 13. Domenica l'ottava!
Jeppe Stig Nielsen,

Con Linq: int g(int y){return Enumerable.Range(1,12).Count(m=>new DateTime(y,m,8).DayOfWeek==0);}. Ovviamente come lambda questo è y=>Enumerable.Range(1,12).Count(m=>new DateTime(y,m,8).DayOfWeek==0).
Jeppe Stig Nielsen,

Puoi salvare un personaggio confrontandolo .DayOfWeek<1.
Danko Durbić,

@ DankoDurbić Questo può applicarsi alla c#risposta ma non è sicuro di come applicarla linq.
Kami,

Errore mio; apparentemente non puoi confrontare DayOfWeekcon nessun altro numero intero che 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;

Corri con echo <year> | php -nR '<code>'.

Fondamentalmente lo stesso che Oleg ha provato e Damir Kasipovic ha fatto, solo con un golf migliore:
ogni mese che inizia di domenica, ha un venerdì 13.
Quindi giro i mesi e conto i primi giorni di domenica.

abbattersi

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

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

Esempio di utilizzo nella console di Rebol:

>> y: 2012
== 2012

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

La soluzione alternativa che raccoglie tutto il venerdì 13 in un determinato anno è:

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

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

ncal stampa un calendario per l'anno dato con i giorni della settimana in basso a sinistra.

sedcon una /gbandiera si abbassa tutti i 13 con nuove righe

grep -c conta le righe che iniziano con "2" (20 segue sempre 13)

Grazie a @DigitalTrauma per aver trovato un bug nella mia vecchia versione e aver proposto una soluzione!


Non del tutto funzionato per me - le linee del venerdì vengono stampati solo una volta anche se contengono più di un 13.
Digital Trauma

1
Penso che il meglio che posso fare con qualcosa del genere sia 38:ncal $1|sed /F/s/13/\\n/g|grep -c ^\ 2
Digital Trauma

1
@DigitalTrauma Hai ragione. Ad un certo punto questa sceneggiatura funzionava. lasciami aggiustarlo.
Non che Charles

1
@DigitalTrauma sembra che funzionasse una versione molto più lunga. grazie per la correzione!
Non che Charles,

Interessante, l'espressione sed non quotata che ho proposto funziona con GNU sed (Linux) ma non con BSD sed (OSX). Suppongo che tu possa guadagnare 1 carattere a costo di portabilità se scegli la versione GNU.
Trauma digitale

1

Scala, 76 68 caratteri

In 78 caratteri:

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

Niente di straordinario, tranne per l'uso di numeri magici per DAY_OF_WEEK = 7e FRIDAY = 6.

Versione a 68 caratteri:

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

Sì, Java ha cambiato i valori delle costanti del giorno della settimana tra le API.


È un peccato new java.util.GregorianCalendarche sia così lungo :(
Cruncher

1

Python 195/204

Funziona solo per gli anni precedenti, perché monthdatescalendarrestituisce un calendario per l'anno dato fino ad ora . Penso che ci sia ancora molto potenziale di ottimizzazione :).

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)

Un'altra soluzione, funziona per ogni data ma non è più piccola:

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)

Nel tuo primo esempio l'intervallo dovrebbe essere (1,13) altrimenti ti mancherebbe venerdì 13 dicembre, come nel 2013.
leancz,

1
Non hai nemmeno disturbato il golf. Rimuovi alcuni di quegli spazi.
mbomb007,

1

Perl 6, 55 53

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

Vecchia risposta:

{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

Con l'idea di non cercare 13th, ma prima, e come sundayè 0questa Salviamo 3 caratteri! Grazie @ Iszi e Danko Durbić!

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

Potrebbe calcolare dal 2010 al 2017 (per esempio) in questo modo:

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

(Ok, non c'è newline , ma non è stato chiesto;)

Vecchio post: 63

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

In azione:

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

In Smalltalk (sapore Squeak / Pharo), implementa questo metodo in Integer ( 86 caratteri)

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

Quindi utilizzare in questo modo: 2014countFriday13.

Certo, potremmo usare un nome più breve, ma non sarebbe Smalltalk


0

C ++ - Troppi byte :(

Ho provato una soluzione che non utilizza librerie di date.

Ho trovato una soluzione piuttosto interessante (se così posso dire anche io). Sfortunatamente non posso essere più breve di questo, il che mi dà davvero fastidio perché sembra che ci dovrebbe essere un modo migliore.

La soluzione si basa su questo algoritmo che è di soli 44 byte in sé. Purtroppo ho bisogno di altri 100 byte per avvolgerlo bene ...

#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 attraverso il codice di ritorno (in C ++, utilizzando couto printfo qualcosa del genere ne richiede un altro#include , che farebbe esplodere la soluzione ancora di più).

Driver / programma di test:

# 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

Uscita del programma del driver:

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

Conto 88 per l'algoritmo, non 44. Cos'è l'algoritmo e qual è il warp? ($m<3?$y--:$y-2)+3anziché d=13,, d+=m<3?y--:y-2,ed+4 dovrebbe funzionare anche e risparmia molto. +5invece di +3e -5dovrebbe funzionare anche e salva 2 byte. for(m=0;++m<13;)salva un byte. Passare m=0alla testa della funzione salva un altro byte; e spostandosi ()%7||++fsulla testa del loop ne salva un altro. In calo da 149 a 136 byte.
Tito

0

Clojure, 207 187 byte

-20 byte eliminando il import, e alcuni spazi bianchi che ho perso.

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

A partire dal 1 ° gennaio di un determinato anno, circola ogni giorno. Se il giorno è venerdì 13, aumenta il conteggio. Continua a girare fino al prossimo anno.

(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, nessun builtin, 81 byte

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

Corri con echo <year> | php -nR '<code>'.

abbattersi

I giorni feriali si ripetono ogni 400 anni.
Nei risultati dal 1600 al 1999 (ad esempio), esiste un periodo di 28 lunghezze con solo tre lacune:

  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

Dopo aver corretto l'anno per queste lacune, possiamo ottenere il risultato con un semplice hash:

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

Non breve (95 byte) ma carino. E possiamo giocare a golf

  • 4 byte usando una catena ternaria per l'offset,
  • 8 byte convertendo la mappa hash da una stringa base4 in numero intero,
  • un altro usando la rappresentazione esadecimale,
  • e uno unendo le espressioni.

Un port della risposta C ++ di CompuChip può essere ridotto a 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

Provalo

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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.