Quantas sexta-feira 13 em um ano?

28

Seu desafio é escrever um programa que, dado um ano, produz o número de "sexta-feira 13" nele.

Regras e detalhes:

  • Você pode receber informações via STDINou como um argumento passado para o seu programa.
  • Você deve enviar o resultado para STDOUT.
  • Você pode assumir que a entrada será um ano válido e não antecede o calendário gregoriano (comportamento indefinido é permitido nesses casos).
  • Bibliotecas de calendário / data são permitidas.

Este é um , portanto o código mais curto (em bytes) vence.

(Link do desafio relacionado)

Triturador
fonte
7
Qual é o intervalo de entrada necessário? Se for muito antes de 1800, que suposições devem ser feitas sobre a transição do calendário juliano para o gregoriano?
Peter Taylor
@ PeterTaylor eu não tinha pensado nisso. Se uma data for anterior a gregoriano, você poderá ter um comportamento indefinido.
Cruncher
1
Os primeiros países a adotar o calendário gregoriano o fizeram em outubro de 1582, seguindo a bula do próprio Gregório. Os países que adotaram o novo calendário tardiamente não mudaram até o século XX, por exemplo, a Grécia o introduziu em 1 de março de 1923.
Jeppe Stig Nielsen
@JeppeStigNielsen Não sei muito sobre calendários e coisas do tipo. Se eles os adotaram ou não, não muda quais são as datas gregorianas. As bibliotecas devem ser capazes de calcular datas de várias maneiras que eu presumo?
Cruncher
3
Eu estou sendo offtopic aqui, eu acho. Muitas bibliotecas escritas por programadores anglo-americanos usam setembro de 1752 como o tempo "correto" de mudança de calendários. Foi quando o Império Britânico mudou. O novo calendário foi mantido quando os EUA foram fundados, é claro. (Por curiosidade, alguns softwares SQL têm 1753 como o ano mínimo, pois não querem lidar com a questão de setembro de 1752.) No entanto, o uso de setembro de 1752 é altamente anglocêntrico. Você está certo As datas gregorianas são as mesmas, independentemente de terem sido usadas historicamente ou não. Esse é o chamado calendário gregoriano pró - séptico .
Jeppe Stig Nielsen

Respostas:

3

APL (Dyalog APL) com cal de dfns , 29 bytes

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

Experimente online!

⍳ 12 os inteiros de um a doze

⎕ ,¨ pegue a entrada numérica e preceda cada um dos doze números

{ Em cada um dos pares, aplique a função…

cal⍵ obter um calendário para esse ano-mês

2 ↓ soltar duas linhas (legenda e dias)

 transpor (para que possamos endereçar colunas em vez de linhas)

¯5 ↑ pegue os cinco últimos (dois dígitos para cada sexta-feira e sábado, mais um espaço)

3 ↑ pegue os dois primeiros (dois dígitos para sexta-feira mais um espaço)

 transpor (para obtermos a ordem de leitura)

, andar

 executar como expressão APL (fornece uma lista das datas das sextas-feiras)

13 ∊ treze é um membro dessa lista?

+/ somar os 12 booleanos


Usando o algoritmo do @ Wrzlprmft , podemos fazê-lo sem bibliotecas de 53 bytes:

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

-∘0 1 subtrair zero e um

400 100 4 ∘.| tabela restante de divisão para os dois anos (transversalmente) dividida por esses números (abaixo)

0 ≠.= "produto" interno com 0, mas usando ≠ e = em vez de +. ×

⊢ , preceder o ano do argumento não modificado

2 3 ¯1 +.× produto interno com esses números

14 | divisão restante quando dividido por catorze

'21232211321211' ⌷⍨ indexar nessa cadeia

Adão
fonte
São 29 caracteres, mas esses são mais de 1 byte, certo?
Cruncher
@Cruncher Adicionei um link explicativo no cabeçalho. Se você abrir o link TIO, verá que ele diz "29 caracteres, 29 bytes (SBCS)" à direita, ou seja, Conjunto de caracteres de byte único.
Adám 01/03/19
Bem, acho que esse é o novo vencedor, então, é prática comum neste SE alterar a resposta aceita muito tempo depois da pergunta?
Cruncher
@Cruncher Sim. E ainda existem emblemas para serem aceitos muito depois da OP.
Adám 01/03/19
12

Mathematica 49 46 45 44 42

Como uma função pura : 42 caracteres

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

Exemplo

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

2


Como uma função nomeada : 44 caracteres

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

Exemplos

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

2
3
2
1

DavidC
fonte
Um caractere mais curto:f=DayName@{#,m,6}~Table~{m,12}~Count~Friday&
Mr.Wizard
@ Mr.Wizard Sim. Surpreende-me que o Mathematica possa analisar os vários casos de notação infix.
DavidC
David, me surpreende que você não tenha visto meu uso (excessivo) dessa notação conjunta. : ^) (Exemplos: (1) , (2) )
Mr.Wizard
8

Ruby, 49 48 47 46

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

Edit: Raspou um personagem voltando uma semana, graças a Jan, e outro mudando de Time.new para Time.gm

Edit: À custa de ofuscá-lo um pouco mais, posso chegar a 46 com

f=->m{(1..12).count{|i|Time.gm(m,i,8).wday<1}}
histocrata
fonte
5
economizando se você contar o número de sextas-feiras a 6ª um-char
John Dvorak
2
@JanDvorak clever!
histocrat
por que 6? Eu não entendi.
NARKOZ
3
Se a 6ª é uma sexta-feira, então o 13º é também uma sexta-feira
TwiNight
Se o dia 8 for domingo, o dia 1 também será, e você poderá usá-lo Time.gm(m,i).wday<1. Além disso, não sei por que você está nomeando a função.
Lee W
8

Powershell, 68 63 58 52 50

Obrigado Iszi pela dica.

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

Usando o fato de que se o primeiro dia do mês for domingo, o dia 13 será sexta-feira.

Eu também tentei:

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

mas não é o mesmo $argsdentro do bloco de scripts.

Danko Durbić
fonte
1
Gosto da ideia de usar o primeiro dia do mês.
quer
Bom truque, aí. O @ é desnecessário, no entanto.
Iszi
Outra coisa, embora eu seja culpado do mesmo em muitos dos meus roteiros. O desafio especifica que a entrada pode vir de um argumento. Substitua $npor $argsno loop e você pode prescindir $n=read-host;totalmente. Salva 8. Remova @, como mencionado acima, e você
alcançou
Correção: chega a 52!
Iszi 11/12
Tentando descobrir por que seu segundo script não funcionará e eu estou perdida. O que é interessante é que eu posso mudar para fora $argspara $input, alimentando assim o ano a partir do gasoduto, e o script será executado, mas ele sempre envia 3.
Iszi
5

R 76 72 57

sum(format(as.Date(paste(scan(),1:12,1,sep="-")),"%w")<1)
modelo
fonte
Pode facilmente obter essa redução de 4 por substituir o seu "%a %d")=="Fri 13"com "%w%d)=="513")usando dow como um número, e remover os espaços.
chmullig
muito apreciado!
flodel
+1 Embora fazer o seqúnico no mês seja realmente mais curto aqui! sum(format(as.Date(paste(scan(),1:12,13,sep="-")),"%w%d")=="513")tem apenas 65 caracteres!
plannapus
uau, eu não imaginaria que <coagiria um caractere a um número inteiro. Bom truque!
plannapus
@ plannapus É bastante comum. Como os códigos de caracteres são todos os números. Até o java pode comparar int e 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

Segunda-feira, dia 9, pode não ter o mesmo toque, mas funciona tão bem quanto.

Edit: Um ano e meio para perceber que dateé menor que datetime:)

ejrb
fonte
Solução muito boa!
leancz
2
Você pode salvar um char fazendofrom datetime import*
user80551
Agradável! Acabei com algo efetivamente idêntico, mas evitando exec: f=lambda y:sum([date(y,m,13).weekday()==4 for m in range(1,13)]).... Mesmo tamanho de solução com a importação (86 bytes).
precisa saber é o seguinte
5

Não usando nenhuma biblioteca ou função de data interna:

Golfscript - 51

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

' [3/=RI[)a%:*.' poderia muito bem ser 'feefefgeeffgfe'

Python - 82 79

Essencialmente o mesmo algoritmo.

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

Usando esse truque , você pode jogar ainda mais:

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

Isso explora o fato de que, em termos de calendário, existem apenas 14 anos diferentes, que são distinguíveis no último dia e se eles estão saltando. lcalcula o número de anos bissextos até seu argumento (se o calendário gregoriano se estender para trás até o ano 1). (2*i+3*l(i)-l(i-1))%14é abreviação de l(i)-l(i-1)+(i+l(i))%7*2, onde l(i)-l(i-1)nos diz se o argumento é um ano bissexto e i+l(i)resume os turnos do último dia (um em um ano normal, dois em um ano bissexto).

Wrzlprmft
fonte
Uma vez que este é o meu primeiro golfscript golf, eu gostaria de receber alguma dica sobre como jogar mais.
precisa saber é o seguinte
Eu estava pensando em uma solução desse tipo, utilizando apenas 14 anos, mas não tinha certeza da melhor linguagem para torná-la competitiva. Eu acho que esta é a resposta mais curta, sem bibliotecas. Se os anos bissextos foram uniformemente a cada 4 anos, você pode ser capaz de ganhar com este
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]-'`');}

Não é a resposta mais curta, mas não usa bibliotecas.

Williham Totland
fonte
Ei, você estaria disposto a fornecer uma resposta não-gasta com uma explicação? Estou interessado no que exatamente você fez.
Cruncher
1
@Cruncher, é uma tabela de pesquisa com base no calendário gregoriano que segue um ciclo de 400 anos.
Peter Taylor
1
Mais explicitamente (e mais), C #: static char GetNumberOfFriday13s(int year) { const string perpetualCalendar = "1221212213113213122221122131122121221311321312222112213112212122131132131222211221311221212213113213112213113213122221122131122121221311321312222112213112212122131132131222211221311221212213113213122213113213122221122131122121221311321312222112213112212122131132131222211221311221212213113213122221122213122221122131122121221311321312222112213112212122131132131222211221311221212213113213122221122131"; return perpetualCalendar[year % 400];. Não vai funcionar por anos negativos.
Jeppe Stig Nielsen
Fofa! Como um pequeno bug, v[0]deveria ser v[1]. Você também pode jogar golfe um pouco; considere usar strcat, armazenar caracteres para imprimir diretamente a[]e subtrair constantes numéricas em vez de constantes de caracteres. :)
user1354557
1
Também melhorei a compactação: 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 caracteres)
user1354557
4

C ( 151 145 137 131 130 caracteres)

Estou surpreso ao ver que há apenas uma outra solução que não usa ferramentas de calendário internas. Aqui está uma abordagem matemática (altamente ofuscada), também em 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));}

(O acima é compilado no GCC sem erros)

Solução alternativa: C (287-> 215 caracteres)

Gostei bastante da solução de Williham Totland e de seu uso de compressão. Corrigi dois pequenos bugs e alterei o código para diminuir seu comprimento:

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
fonte
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;

Baseado em

"Qualquer mês que começa no domingo contém uma sexta-feira 13 e há pelo menos uma sexta-feira 13 em cada ano civil".

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

Damir Kasipovic
fonte
4

festança 47 36

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

Obrigado @DigitalTrauma por salvar 10 caracteres usando seqo início padrão para 1.

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

(Versão anterior usando echoapresentar um bug por causa da linha vazia quando <(echo $1-{1..12}-6$'\n'). Portanto, esta função funcionou bem até hoje é uma sexta-feira.

Vamos ver:

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

Is é dependente da localidade ; se, se não funcionar, pode ser necessário

export LANG=C

ou

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

Em uma função; +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

Bônus: +78 -> 121

A partir daí, se minha função se tornar:

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

ou

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
fonte
Isso parece depender da localidade.
Peter Taylor
Sim, isso é baseado no padrão C. Mas há um erro ...
F. Hauri
Salve um caractere entre aspas sua string de formato printf e escape do \ em vez disso:%s\\n
Digital Trauma
1
Ou use seqpara soltar 8 caracteres:date -f<(seq -f$1-%g-6 1 12)|grep -c ^F
Digital Trauma
1
Na verdade, você pode cortar mais 2 caracteres. Se você omitir o número de sequência inicial, o seq começará em 1 por padrão, e é o que você deseja: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}
guy777
fonte
e por que é -1?
Lukasz 'Severiaan' Grela
1
Parece bom! Você pode economizar mais alguns bytes, através da remoção ,b,cda declaração da função (! Que é OK para vazamento de vars para o golfe), também como bé moldado como um Numberpossível +=resultado de teste em vez do &&b++: b+=/^F/.test(new Date(a,c,6)). No entanto, você pode salvar outro byte usando !new Date(a,c,1).getDay()(isso funciona porque getDayretorna 0 para domingo e, se o dia 13 for sexta-feira, o primeiro dia será domingo) em vez do testque, em conjunto, você deverá economizar 7 bytes!
Dom Hastings
@DomHastings: thx por suas dicas !!!
precisa
3

k

64 caracteres

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

Lê a partir de stdin

skeevey
fonte
Ok, o que está acontecendo aqui? : P
Williham Totland
Leia no ano, lista de construção das datas de 13 dias de cada mês, dia do teste da semana = sexta-feira, lista resultante soma de booleans
skeevey
3

Lisp comum (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
fonte
Oh deus, eu nunca poderia ler 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);}

Agradeço a Jeppe Stig Nielsen pelo linq e pela sugestão de verificar o domingo no dia 8.

Obrigado a Danko Durbić por sugerir em >vez de ==.

Kami
fonte
Em vez de c+=(int)new DateTime(y,i,13).DayOfWeek==5?1:0;, use o equivalente c+=new DateTime(y,i,8).DayOfWeek==0?1:0;. O truque é subtrair 5, porque então você pode se livrar do elenco inte também o número 8tem um dígito a menos que o número 13. Domingo o oitavo!
Jeppe Stig Nielsen
Com Linq: int g(int y){return Enumerable.Range(1,12).Count(m=>new DateTime(y,m,8).DayOfWeek==0);}. Claro que como lambda é isso y=>Enumerable.Range(1,12).Count(m=>new DateTime(y,m,8).DayOfWeek==0).
Jeppe Stig Nielsen
Você pode salvar um caractere comparando .DayOfWeek<1.
Danko Durbić 11/12/13
@ DankoDurbić Isso pode ser aplicado à c#resposta, mas não sei ao certo como aplicá-la linq.
Kami
Meu erro; aparentemente você não pode comparar DayOfWeekcom nenhum outro número inteiro que não 0- 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;

Corra com echo <year> | php -nR '<code>'.

Basicamente, o mesmo que Oleg tentou e Damir Kasipovic , apenas com um golfe melhor:
todo mês que começa com um domingo, tem uma sexta-feira 13.
Então, percorro os meses e conto os primeiros dias que são domingos.

demolir

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
fonte
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
fonte
1

Bash ( 52 47 caracteres)

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

Rebol, 63

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

Exemplo de uso no console Rebol:

>> y: 2012
== 2012

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

A solução alternativa que coleta toda a sexta-feira 13 em determinado ano é:

>> 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
fonte
1

Bash e Sed, 39

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

ncal imprime um calendário para o ano especificado com os dias da semana à esquerda.

sedcom uma /gbandeira apaga todos os 13s com novas linhas

grep -c conta as linhas que começam com "2" (20 sempre segue 13)

Obrigado a @DigitalTrauma por encontrar um bug na minha versão antiga e propor uma solução!

Não que Charles
fonte
Não funciona muito bem para mim - linhas de sexta-feira são impressos apenas uma vez, mesmo se contiverem mais de um 13.
Trauma Digital
1
Eu acho que o melhor que posso fazer com algo assim é 38:ncal $1|sed /F/s/13/\\n/g|grep -c ^\ 2
Digital Trauma
1
@DigitalTrauma Você está certo. Em algum momento esse script estava funcionando. deixe-me consertar.
Não que Charles,
1
@DigitalTrauma parece que alguma versão muito mais longa estava funcionando. obrigado pela correção!
Não que Charles,
Interessante, a expressão sed não citada que propus funciona com GNU sed (Linux), mas não com BSD sed (OSX). Eu acho que você pode ganhar 1 caractere ao custo de portabilidade, se você escolher a versão GNU.
Digital Trauma
1

Scala, 76 68 caracteres

Em 78 caracteres:

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

Nada fora do comum, exceto pelo uso de números mágicos para DAY_OF_WEEK = 7e FRIDAY = 6.

Versão de 68 caracteres:

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

Sim, o Java alterou os valores das constantes do dia da semana entre as APIs.

Karol S
fonte
É uma pena que new java.util.GregorianCalendartenha que ser tão longo :(
Cruncher
1

Python 195/204

Funciona apenas para anos anteriores, porque monthdatescalendarretorna um calendário para o ano especificado até agora . Eu acho que ainda há muito potencial de otimização :).

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)

Outra solução, funciona para todas as datas, mas não é menor:

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
fonte
No seu primeiro exemplo, o intervalo deve ser (1,13), caso contrário você perderia a sexta-feira 13 de dezembro, como em 2013.
leancz 11/11/13
1
Você nem se incomodou em jogar golfe. Remova alguns desses espaços.
mbomb007
1

Perl 6, 55 53

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

Resposta antiga:

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

Perl + lib POSIX 55

Com a idéia de não procurar, 13thmas primeiro, e como sundayé 0isso, vamos salvar 3 caracteres! Obrigado @ Iszi e Danko Durbić!

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

Poderia calcular 2010 a 2017 (por exemplo) desta maneira:

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

(Ok, não há nova linha , mas isso não foi solicitado;)

Post antigo: 63

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

Em ação:

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
fonte
0

Em Smalltalk (sabor Squeak / Pharo), implemente esse método em Inteiro ( 86 caracteres)

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

Em seguida, usá-lo como este: 2014countFriday13.

Claro, poderíamos usar um nome mais curto, mas não seria Smalltalk

aka.nice
fonte
0

Muitos bytes :(

Eu tentei uma solução que não faz uso de nenhuma biblioteca de datas.

Encontrei uma solução bem legal (se assim posso dizer). Infelizmente, não posso obtê-lo mais curto do que isso, o que realmente me incomoda, porque parece que deveria haver uma maneira melhor.

A solução depende desse algoritmo, que possui apenas 44 bytes. Infelizmente, preciso de mais 100 bytes para embrulhá-lo bem ...

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

Saída através do código de retorno (em C ++, usando coutou printfou algo assim requer outra#include , o que explodiria ainda mais a solução).

Programa de driver / teste:

# 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

Saída do programa do driver:

$ ./test_doomsday 
1766: 2
2013: 3
2013: 2
2014: 1
150 doomsday.cpp characters
CompuChip
fonte
Eu conto 88 para o algoritmo, não 44. Qual é o algoritmo e qual é a distorção? ($m<3?$y--:$y-2)+3em vez de d=13,, d+=m<3?y--:y-2,e d+4deve funcionar bem e economiza muito. +5em vez de +3e -5deve funcionar também e economiza 2 bytes. for(m=0;++m<13;)salva um byte. Mover m=0para o cabeçote da função salva outro byte; e mover ()%7||++fpara a cabeça do laço salva outra. Diminua de 149 para 136 bytes.
Titus
0

Clojure, 207 187 bytes

-20 bytes, livrando-se do importespaço em branco que perdi.

(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 partir de 1º de janeiro do ano em questão, ele volta todos os dias. Se o dia for sexta-feira 13, aumentará a contagem. Ele continua em loop até atingir o próximo ano.

(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.
Carcinigenicado
fonte
0

PHP, sem builtins, 81 bytes

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

Corra com echo <year> | php -nR '<code>'.

demolir

Os dias da semana se repetem a cada 400 anos.
Nos resultados de 1600 a 1999 (por exemplo), há um período de 28 períodos com apenas três lacunas:

  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

Depois de ajustar o ano para essas lacunas, podemos obter o resultado com um simples hash:

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

Não é curto (95 bytes), mas bonito. E nós podemos jogar golfe

  • 4 bytes usando uma cadeia ternária para o deslocamento,
  • 8 bytes, convertendo o mapa de hash de uma sequência base4 em número inteiro,
  • mais uma usando a representação hexadecimal,
  • e um, mesclando as expressões.
Titus
fonte
Uma porta da resposta C ++ da CompuChip pode ser reduzida até 84 bytes: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

Japonês -x , 10 bytes

CÆ5¥ÐUXD e

Tente

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
Shaggy
fonte