Desafio de multiplicação de datas

19

(Inspirado pelo Riddler da semana passada no FiveThirtyEight.com. Postagem na caixa de areia .)

Dado um ano entre 2001 e 2099, calcule e retorne o número de dias durante o ano civil em que mm * dd = yy(onde yyé o ano de 2 dígitos ).

2018, por exemplo, possui 5:

  • 18 de janeiro (1 * 18 = 18)
  • 9 de fevereiro (2 * 9 = 18)
  • 6 de março (3 * 6 = 18)
  • 3 de junho (6 * 3 = 18)
  • 2 de setembro (9 * 2 = 18)

A entrada pode ser um ano numérico de 2 ou 4 dígitos.

A saída deve ser um número inteiro. O espaço à direita ou o retorno opcional é bom.

Lista completa de entrada / saída:

Input = Output
 2001 = 1     2021 = 3     2041 = 0     2061 = 0     2081 = 2
 2002 = 2     2022 = 3     2042 = 4     2062 = 0     2082 = 0
 2003 = 2     2023 = 1     2043 = 0     2063 = 3     2083 = 0
 2004 = 3     2024 = 7     2044 = 3     2064 = 2     2084 = 5
 2005 = 2     2025 = 2     2045 = 3     2065 = 1     2085 = 1
 2006 = 4     2026 = 2     2046 = 1     2066 = 3     2086 = 0
 2007 = 2     2027 = 3     2047 = 0     2067 = 0     2087 = 1
 2008 = 4     2028 = 4     2048 = 6     2068 = 1     2088 = 3
 2009 = 3     2029 = 1     2049 = 1     2069 = 1     2089 = 0
 2010 = 4     2030 = 6     2050 = 3     2070 = 3     2090 = 5
 2011 = 2     2031 = 1     2051 = 1     2071 = 0     2091 = 1
 2012 = 6     2032 = 3     2052 = 2     2072 = 6     2092 = 1
 2013 = 1     2033 = 2     2053 = 0     2073 = 0     2093 = 1
 2014 = 3     2034 = 1     2054 = 4     2074 = 0     2094 = 0
 2015 = 3     2035 = 2     2055 = 2     2075 = 2     2095 = 1
 2016 = 4     2036 = 6     2056 = 4     2076 = 1     2096 = 4
 2017 = 1     2037 = 0     2057 = 1     2077 = 2     2097 = 0
 2018 = 5     2038 = 1     2058 = 0     2078 = 2     2098 = 1
 2019 = 1     2039 = 1     2059 = 0     2079 = 0     2099 = 2
 2020 = 5     2040 = 5     2060 = 6     2080 = 4

Este é um desafio do , com a menor contagem de bytes em cada idioma.

Pré-calcular e simplesmente procurar as respostas normalmente é excluído de acordo com nossas regras de brecha , mas estou explicitamente permitindo esse desafio. Ele permite algumas estratégias alternativas interessantes, embora não seja provável que uma lista de pesquisa de 98 99 itens seja a mais curta.

BradC
fonte
Se isso facilitar o seu idioma, a resposta será a mesma, independentemente do século; 1924 e 2124 têm o mesmo número de dias, 2024.
BradC
se o resultado de mm * dd for maior que 100, ele será filtrado automaticamente?
DanielIndie
@DanielIndie Correto, nenhuma data "envolvente" deve ser contada. Em outras palavras, 12 de dezembro de 2044 não conta, embora 12 * 12 = 144.
BradC
Como precisamos lidar apenas com um número limitado de entradas, editei todas elas. Sinta-se à vontade para reverter ou reformatar.
Shaggy
1
@ gwaugh Apenas você pode decidir qual aceitar como entrada válida (para que você não precise gastar caracteres extras convertendo entre os dois).
BradC

Respostas:

14

Excel, 48 bytes

Viva! Finalmente, algo em que o Excel é realmente bom.

=COUNT(VALUE(ROW(1:12)&"/"&A1/ROW(1:12)&"/"&A1))

Recebe a entrada de A1 na forma de um número inteiro de 1 a 99 representando o ano e sai para onde quer que você insira essa fórmula. É uma fórmula de matriz, então use Ctrl-Shift-Enter em vez de Enter para inseri-lo.

Isso tira vantagem do fato de COUNTignorar erros; portanto, todos os erros causados ​​pelo mês que não divide o ano (levando o Excel a analisar algo como 2/12.5/25ou a data que não é válida, por exemplo 2/29/58, são ignorados silenciosamente.

Sophia Lechner
fonte
1
Muito agradável. Provavelmente vale a pena mencionar que requer um ano de dois dígitos A1. A entrada de um ano de 4 dígitos simplesmente retorna 0.
BradC
Verdade! Vou editar isso na descrição.
Sophia Lechner
Também devo mencionar que é específico da localidade; depende de ter um código de idioma que use um pedido em mm / dd / aa. Em uma localidade com ordenação dd / mm / aa, a resposta seria o mesmo número de bytes, é claro.
Sophia Lechner
1
Super inteligente; Gosto de como você está testando apenas 12 candidatos à data (um por mês), em vez de executar todos os dias do ano.
BradC
Corrigir o ano com um byte salvo sem salto?
L4m2
6

Python 2 , 44 bytes

[k/32%13*(k%32)for k in range(96,509)].count

Experimente online!

Uma função anônima fornecida como um objeto de método. Produz todos os produtos de (month, day)pares (m, d)como codificado por k=32*m+dcom 0≤m≤12, 0≤d≤31, envolvendo em torno. Elimina os dias 29 e 31 de fevereiro, excluindo-os do intervalo.

xnor
fonte
5

Java (JDK 10) , 65 bytes

y->{int m=13,c=0;for(;m-->1;)if(y%m<1&y/m<29+m%2*3)c++;return c;}

Experimente online!

Créditos

Olivier Grégoire
fonte
Nenhum ano bissexto se encaixa 29*n, então não há necessidade do check
l4m2
Obrigado pela sua contribuição. Eu poderia remover 27 bytes no total com várias outras alterações.
Olivier Grégoire
1
Mudar (m==2?29:32)para 29+m%2*3ainda parece dar todos os OKresultados. Crédito para a resposta Ruby de @AsoneTuhid .
Kevin Cruijssen
4

PowerShell , 94 bytes

param($a)for($x=Date 1/1/$a;$x-le(Date 12/9/$a);$x=$x.AddDays(1)){$z+=$x.Month*$x.Day-eq$a};$z

Experimente online!

Recebe a entrada como um ano de dois dígitos e constrói um forloop de 1/1/yearpara 12/9/year(porque 12/10 e além nunca contarão e isso economiza um byte). A cada iteração, incrementamos $zse o .Monthtempo .Dayfor igual ao nosso ano de entrada. Fora do loop, $zé deixado no pipeline e a saída é implícita.

Editar - isso depende da cultura. O código acima funciona para en-us. O formato da data pode precisar ser alterado para outras culturas.

AdmBorkBork
fonte
2
"cultura"? Você quis dizer "localidade"? ...
user202729
1
@ user202729 Coloquialmente, sim, mas a documentação do PowerShell se refere a ela como "cultura".
AdmBorkBork
"Cultura" é a palavra que a MS geralmente usa para falar sobre localidade, por exemplo. System.Globalization.CultureInfo no .NET.
sundar - Restabelece Monica
3

JavaScript (ES6), 91 bytes

Eu estava curioso para saber como a codificação seria comparada a uma computação iterativa. Definitivamente, é mais longo (veja a resposta de @ Shaggy ), mas não muito mais.

Edit : É, no entanto, muito mais longo que uma fórmula mais direta (consulte a resposta na l4m2 ).

Recebe a entrada como um número inteiro em [1..99] .

n=>(k=parseInt('8ijkskercdtbnqcejh6954r1eb2kc06oa3936gh2k0d83d984h'[n>>1],36),n&1?k>>3:k&7)

Experimente online!

Quão?

Anos ímpares têm significativamente menos chance de ter mm * dd = aa do que anos pares. Mais concretamente, anos ímpares têm 0 a 3 correspondências, enquanto anos pares têm 0 a 7 correspondências. Isso nos permite codificar cada par de anos com apenas 5 bits, o que pode ser convenientemente representado como um único caractere na base 36.

Arnauld
fonte
3

Python 2 e 3 , 55 52 bytes

lambda y:sum(y%i<(y/i<29+i%2*3)for i in range(1,13))

Experimente online!

Asone Tuhid
fonte
3

Utilitários Bash + GNU , 57

  • 1 byte salvo graças a @SophiaLechner
seq -f1/1/$1+%gday 0 365|date -f- +%m*%d-%y|bc|grep -c ^0

Observe que o seqcomando sempre produz uma lista de 366 datas - para os anos que não são bissextos, o 1º de janeiro do próximo ano será incluído. No entanto, no período de 2001 a 2099, MM * DD nunca será AA para 1º de janeiro do próximo ano em nenhum desses anos, portanto esse dia extra não afetará o resultado.

Experimente online!

Trauma Digital
fonte
Muito bom - eu nem sabia dateque faria matemática de datas assim enquanto analisava. seqnão precisa de um espaço após o -f, então você pode salvar um byte lá.
Sophia Lechner
3

T-SQL, 123 121 bytes

De acordo com nossas regras de IO , a entrada é obtida através da tabela preexistente t com um campo inteiro y , que contém um ano de 2 dígitos.

WITH c AS(SELECT 1m UNION ALL SELECT m+1FROM c WHERE m<12)
SELECT SUM(ISDATE(CONCAT(m,'/',y/m,'/',y)))FROM c,t WHERE y%m=0

A quebra de linha é apenas para legibilidade. Inspirado em grande parte pela solução Excel da Sophia .

  • A linha superior gera uma tabela de números de 12 itens c, que é associada à tabela de entrada t .
  • Se isso passar, misturo um candidato a data usando CONCAT(), o que implica varcharconversões implícitas de tipo de dados. Caso contrário, eu teria que fazer várias declarações CASTou CONVERT.
  • Foi encontrada a função de avaliação perfeita ISDATE(), que retorna 1 para datas válidas e 0 para datas inválidas.
  • Embrulhe em uma soma e pronto.
  • EDIT : Moveu a divisão inteira check ( y%m=0) na WHEREcláusula para salvar 2 bytes, obrigado @RazvanSocol.

Infelizmente, não é muito menor que a versão da tabela de pesquisa (usando a string da versão do osdavison ):

Pesquisa T-SQL, 129 bytes

SELECT SUBSTRING('122324243426133415153317223416132126011504033106131204241006003213011306002122042005101305111014012',y,1)FROM t

EDIT : deixando o original acima, mas podemos salvar alguns bytes usando algumas novas funções:

  • STRING_SPLIT está disponível no MS SQL 2016 e acima.
  • CONCAT_WS está disponível no MS SQL 2017 e acima.
  • Como acima, substituído IIFporWHERE

MS-SQL 2017, 121 118 bytes

SELECT SUM(ISDATE(CONCAT_WS('/',value,y/value,y)))
FROM t,STRING_SPLIT('1-2-3-4-5-6-7-8-9-10-11-12','-')
WHERE y%value=0

MS-SQL 2017, edição mais barata: 109 bytes

SELECT SUM(ISDATE(CONCAT_WS('/',number,y/number,y)))
FROM t,spt_values WHERE number>0AND y%number=0AND'P'=TYPE

Requer que você esteja no masterbanco de dados, que contém uma tabela do sistema spt_valuesque (quando filtrada por TYPE='P') fornece números de 0 a 2048.

BradC
fonte
Semelhante a outras respostas, a ordem em que montei a data ( m/d/y) depende das configurações de localidade da instância SQL. Outras localidades podem exigir uma ordem diferente ou um separador diferente, mas acho que isso não afetaria o tamanho do código.
BradC
Eu acho que você percebeu que a conversão de '2/29/64' para uma data dá 1964-02-29 (não 2064-02-29), mas considerando que os anos 2000 e 2100 foram excluídos, é uma boa maneira de diminuir código.
Razvan Socol
Usar em SPLIT_STRINGvez de um CTE reduz para 120 bytes. Usar em CONCAT_WSvez de CONCATsalva outro caractere, atingindo 119 bytes.
Razvan Socol
@RazvanSocol Sim, não tenho certeza de onde está o intervalo entre as datas de dois dígitos que mapeiam 19xx vs 20xx, mas ambos dão a mesma resposta. Vou tentar as outras duas sugestões, obrigado!
BradC
1
Substitua IIFpor WHERE.
Razvan Socol
3

Julia 0.6 , 49 44 42 bytes

y->sum(y/i1:28+3(i%2i÷8)for i=1:12)

Experimente online!

-5 bytes inspirados na resposta Ruby de Asone Tuhid.
-2 bytes substituindo contagem por soma

Explicação:

Para cada mês, ide 1 a 12, calcule y/ie verifique se é um dos dias desse mês. Meses com 31 dias são 1, 3, 5, 7, 8, 10, 12 - portanto, são ímpares abaixo de 8 e pares iguais ou superiores a 8. Portanto, i%2ou i÷8( ou seja, que é 0 para i <8 e 1 para i> = 8 aqui) deve ser 1, mas não os dois - então nós os XORamos. Se o resultado xor for verdadeiro, verificamos as datas , 1:28+3ou seja 1:31, apenas as datas 1:28.

1:28é suficiente para o resto dos meses (essa melhoria inspirada na resposta Ruby de Asone Tuhid ) porque:

  • para fevereiro, a única possibilidade seria 2*29 = 58, mas 2058não é um ano bissexto, portanto, podemos assumir que fevereiro sempre tem 28 dias.

  • os outros meses com 30 dias são o mês 4 e superior - para o qual i*29(e i*30) seria superior a 100, o que pode ser ignorado.

Finalmente, contamos o número de vezes que y/iessa lista de dias pertence (usando booleano sumaqui) e retornamos.

sundar - Restabelecer Monica
fonte
3

JavaScript, 91 85 82 81 77 bytes

Recebe a entrada como uma sequência de 2 dígitos (ou um número inteiro de 1 ou 2 dígitos).

Aproveita o fato de que new Dateserá transferido para o próximo mês e continuará fazendo isso, se você passar um valor de dia que excede o número de dias no mês em que você passa para ele, na primeira iteração, ele tenta construir o data yyyy-01-345que se torna yyyy-12-11, ou yyyy-12-10em anos bissextos. Não precisamos verificar as datas depois disso, pois isso 12*11+resulta em um número de três dígitos.

y=>(g=d=>d&&([,M,D]=new Date(y,0,d).toJSON().split(/\D/),D*M==y)+g(--d))(345)

3 bytes salvos graças ao Arnauld .


Teste-o

f=
y=>(g=d=>d&&([,M,D]=new Date(y,0,d).toJSON().split(/\D/),D*M==y)+g(--d))(345)
o.innerText=[...Array(99)].map((_,x)=>(2001+x++)+` = `+f(x)).join`\n`
pre{column-count:5;width:480px;}
<pre id=o></pre>

Shaggy
fonte
2

Excel, 83 bytes

{=SUM(IF(MONTH(DATE(A1,1,0)+ROW(1:366))*DAY(DATE(A1,1,0)+ROW(1:366))=A1-2000,1,0))}

A entrada está na célula A1no formato yyyy. Esta é uma fórmula de matriz e é inserida com Ctrl+ Shift+ Enterpara obter os colchetes {}. É bastante direto e sem nenhuma esperteza.

Quando em uma fórmula de matriz, DATE(A1,1,0)+ROW(1:366)fornece uma matriz de 366 valores de data. Em anos não bissextos, isso incluirá 1º de janeiro do próximo ano, mas isso não é um problema, porque 1*1=1só contaria como falso positivo se o próximo ano for 2001, mas, como o intervalo de anos exigido 2001 - 2099, nunca surgirá como um questão.

Se você colocou um pouco mais simples ~, a fórmula é muito mais fácil de seguir:

{=SUM(IF(MONTH(~)*DAY(~)=A1-2000,1,0))}

Eu tentei usar em COUNTIF()vez de, SUM(IF())mas o Excel nem me deixou entrar como uma fórmula de matriz, muito menos me deu um resultado. I fez encontrar um Sheets Google solução usando CountIf(), mas o mesmo método de outra forma que acabou por ser 91 bytes, principalmente porque ele usa ArrayFormula()em vez de simplesmente { }.

=CountIf(ArrayFormula(Month(Date(A1,1,0)+Row(1:366))*Day(Date(A1,1,0)+Row(1:366))),A1-2000)
Engenheiro Toast
fonte
Não vi um consenso, mas geralmente não incluo os colchetes externos nas contagens de bytes do Excel. Eles se parecem mais com o modo como o Excel está formatando sua exibição do que com parte da fórmula. Opiniões?
Sophia Lechner
@SophiaLechner Eu os incluí em vez de decidir como incluir as teclas extras necessárias para inseri-lo como uma fórmula de matriz. Há uma meta pergunta sobre isso e a única resposta diz que o comando CTRL + ALT + ENTER contaria como 1 pressionamento de tecla. Se você usar o mesmo que o vim ( por meta ), esse pressionamento de tecla contará como 1 byte. No entanto, normalmente não conto o ENTER no final da inserção de uma fórmula como 1 byte em outras respostas.
Engineer Toast
2

Retina 0.8.2 , 55 bytes

..
$*
(?<=^(1{1,12}))(?=(?(?<=^11$)\1{0,27}|\1{0,30})$)

Experimente online! Leva um ano de dois dígitos; adicione 1 byte para oferecer suporte a anos de 4 dígitos. Explicação: O primeiro estágio simplesmente se converte em unário. O segundo estágio inicia correspondendo de 1 a 12 caracteres antes da posição de correspondência, representando o mês e, em seguida, tenta olhar para a frente por um número inteiro de repetições daquele mês. No entanto, o lookahead contém uma condicional, que escolhe entre 27 ou 30 repetições adicionais, dependendo do mês. A contagem de posições de partida é o resultado desejado.

Neil
fonte
2

R , 22 122 bytes

x=scan();substr("122324243426133415153317223416132126011504033106131204241006003213011306002122042005101305111014012",x,x)

Experimente online!

Decidiu ir com uma abordagem de tabela de pesquisa. O ano de entrada precisa ter 2 dígitos.

Robert S.
fonte
1
Também no TIO, você pode clicar no botão "link" e formatará automaticamente a resposta para você. Agradecemos a Dennis por configurá-lo!
Giuseppe
Você pode remover a inicial if, uma vez que a entrada pode ser qualquer um de 2 dígitos ou 4 dígitos, a sua escolha (de modo que você pode optar por aceitar apenas a entrada de 2 dígitos). . Mas parece que o código considera todos os meses para conter 31 dias, por isso, para, por exemplo, 62 (para 2062) retorna 1, onde ele deve retornar 0.
sundar - Reintegrar Monica
2
Eu entendi errado. Dito isto, tenho certeza de que a tabela de pesquisa precisaria ser incluída na contagem de bytes.
ngm
@ngm Eu também não tinha certeza se a tabela de pesquisa precisava ser incluída, mas vou adicioná-la à contagem de bytes para garantir a segurança.
Robert S.
Ainda não tenho certeza de quais são todas as regras!
ngm
2

C (gcc), 65 60 59 bytes

d(a,t,e){for(t=0,e=13;e-->1;)t+=a%e<1&a/e<(e-2?32:29);a=t;}

Porta da resposta Java do user202729 . Experimente online aqui . Agradecimentos a Jonathan Frech por jogar 1 byte.

OOBalance
fonte
a=0,m=13;for(;~> for(a=0,m=13;.
precisa
@ JonathanFrech Obrigado por apontar isso, eu editei.
OOBalance
2

J , 29 bytes

1#.(,x*i."+29+3*2~:x=.i.13)=]

Experimente online!

Como funciona

1#.(,x*i."+29+3*2~:x=.i.13)=]    Input: year (2-digit, 1..99)
                   x=.i.13       array of 0..12; assign to x
                2~:              1 1 0 1 .. 1
              3*                 3 3 0 3 .. 3
           29+                   32 32 29 32 .. 32
       i."+                      for each item of above, generate a row 0 .. n
    ,x*                          each row times 0 .. 12 and flatten
                           =]    1 for each item == input, 0 otherwise
1#.                              sum

Tentei muito menos de 2 vezes a solução Jelly :)

Nota

Se alguém realmente deseja codificar os dados de 99 dígitos, aqui estão algumas informações:

Divida os 99 dígitos em pedaços de 2 dígitos. Então o primeiro dígito é <4e o segundo <8, o que significa que cinco bits podem codificar dois números. Em seguida, todos os dados podem ser codificados em 250 bits ou 32 bytes.

Bubbler
fonte
2

Python 3 , 158 162 215 241 bytes

Removido 4 Obrigado a Stephen por jogar golfe nos condicionais.

Removido 53 agradecimentos Stephen por apontar o espaço em branco

Removido 26 graças ao link fornecido por caird

Eu sou muito novo nisso. Não conseguia pensar em como fazer isso sem que os dias do mês fossem descritos.

r=range
def n(Y):
 a,b,c=31,30,0
 for x in r(12):
  for y in r([a,(28if Y%4else 29),a,b,a,b,a,a,b,a,b,a][x]):
   if(x+1)*(y+1)==int(str(Y)[2:]):c+=1
 return c

Experimente online!

akozi
fonte
5
Bem-vindo ao site e bom primeiro post! Há um justo algumas maneiras que você pode golfe esta, como a remoção de alguns espaços em branco, por isso não deixe de verificar essas dicas para golfe em Python
caird coinheringaahing
@cairdcoinheringaahing Obrigado pelo conselho, o link foi muito útil!
akozi
1
158 bytes - jogou golfe fora, mas na maioria das vezes você tinha uma grande fila de espaços na terceira linha, não sei como eles chegaram lá
Stephen
@ Stephen Obrigado :) Eu adicionei o seu como duas edições. Um para o espaço em branco e outro para o golfe.
akozi 03/02
(28if Y%4else 29)pode ser reduzido para [29,28][Y%4>0]. Além disso, a lista longa pode ser reduzida para [a,...]+2*[a,b,a,b,a]. a,b,cpode ser adicionado na lista de parâmetros para salvar uma linha. int(str(Y)[2:])pode ser reduzido para Y%100. Finalmente, as variáveis ​​do contador podem ser abreviadas para lens de lista, o que também permite nque seja feito a lambda. Isso faz 118 .
Black Owl Kai
2

Quarto (gforth) , 60 59 bytes

: f 0 13 1 do over i /mod swap 32 i 2 = 3 * + 0 d< - loop ;

Experimente online!

Esta versão aproveita o fato de que não pode haver mais de um dia correspondente por mês e que o ano deve ser divisível por mês para que ele corresponda.

Explicação

Repete ao longo dos meses, verifica se o ano é divisível por mês e se o quociente é <31 (28 de fevereiro). Os meses após março não podem corresponder para dias superiores a 25, para que possamos assumir todos os meses (exceto fevereiro) tem 31 dias para o objetivo do quebra-cabeça.

Código Explicação

: f                   \ start new word definition
  0                   \ set up counter
  13 1 do             \ start a counted loop from 1 to 12
    over i /mod       \ get the quotient and remainder of dividing year by month
    swap              \ default order is remainder-quotient, but we want to swap them
    32 i 2= 3 * +     \ we want to compare to 32 days unless month is Feb
    0 d<=             \ treat the 4 numbers on the stack as 2 double-length numbers
                      \ and compare [1]
    -                 \ subtract result from counter (-1 is true in Forth)
  loop                \ end loop
;                     \ end word definition    

[1] - A seguir, o conceito de números de comprimento duplo, que são armazenados na pilha como dois números de comprimento único (da forma xy, em que o valor de double = y * 2^(l) + xonde l é o tamanho em bits de um único no com a qual você está trabalhando).

Nesse caso, comparei o quociente e o restante com 32 (ou 29) 0. Se o restante fosse maior que 0 (ano não divisível por mês), o primeiro dobro seria automaticamente maior que 32 (ou 29) 0 e o resultado seria falso. Se o restante for 0, ele resolverá efetivamente uma verificação regular do quociente <= 32 (ou 29)

Quarto (gforth) , 61 bytes

: f 0 13 1 do i 2 = 3 * 32 + 1 do over i j * = - loop loop ; 

Experimente online!

Economizou alguns bytes ao perceber que apenas fevereiro é importante em termos de número correto de dias no mês

Explicação

As comparações adiante (pelo menos adiante) retornam -1 para verdadeiro e 0 para falso

0                     \ place 0 on top of the stack to use as a counter
13 1 do               \ begin the outer loop from 1 to 12
  i 2 = 3 *           \ if i is 2 place -3 on top of the stack, otherwise 0
  32 + 1 do           \ begin the inner loop from 1 to 31 (or 28)
    over              \ copy the year from stack position 2 and place it on top of the stack
    i j * = -         \ multiply month and day compare to year, subtract result from counter 
  loop                \ end the inner loop
loop                  \ end the outer loop
reffu
fonte
1

Java (JDK 10) , 79 72 70 bytes

y->{int a=0,m=13;for(;m-->1;)a+=y%m<1&&y/m<(m==2?29:32)?1:0;return a;}

Experimente online!

user202729
fonte
@ Shaggy Thanks! (remanescente da versão anterior, onde I loop sobre todos os days)
user202729
Se você mudar &&para &, é a mesma resposta que a resposta Java de OlivierGrégoire, embora ele tenha respondido 19 minutos antes.
Kevin Cruijssen
@KevinCruijssen Random coincidence. Embora minha versão seja um pouco pior (uso desnecessário de ternário).
usar o seguinte comando
1

JavaScript (Node.js) , 108 bytes

a=>'0122324243426133415153317223416132126011504033106131204241006003213011306002122042005101305111014012'[a]

f=a=>'0122324243426133415153317223416132126011504033106131204241006003213011306002122042005101305111014012'[a]
o.innerText=[...Array(99)].map((_,x)=>(2001+x++)+` = `+f(x)).join`\n`
pre{column-count:5;width:480px;}
<pre id=o></pre>


fonte
Pesquisa de força bruta, legal!
BradC
Bem-vindo ao PPCG!
Shaggy
1

Python 3, 132 bytes

Este é realmente um programa bastante longo, mas achei que poderia ser interessante.

Todos os valores estão entre 0 e 7, então eu codifico cada número com 3 bits em uma cadeia binária longa. Tentei colar uma string binária bruta no meu programa python, mas não consegui fazê-la funcionar, por isso decidi pela base64 no arquivo.

Usei a seguinte string como uma tabela de pesquisa (as 7 finalizações usadas para preenchimento): 01223242434261334151533172234161321260115040331061312042410060032130113060021220420051013051110140127

O programa pega essa string e a decodifica como um número e usa a mudança de bits para extrair o resultado.

import base64
lambda n:int.from_bytes(base64.b64decode(b'pNRRxYtw01s9Jw4tFYE0QNkYsoRQgYBosEsYBFIRAUgsUkgwFQM='),'big')>>(6306-3*n)&7

66 bytes + arquivo de 37 bytes = 103 bytes

Isso lê um arquivo binário chamado ee evita o uso de base64.

lambda n:int.from_bytes(open('e','rb').read(),'big')>>(6306-3*n)&7

Aqui está um hexdump do arquivo lido (sem preenchimento):

00000000  a4 d4 51 c5 8b 70 d3 5b  3d 27 0e 2d 15 81 34 40  |..Q..p.[='.-..4@|
00000010  d9 18 b2 84 50 81 80 68  b0 4b 18 04 52 11 01 48  |....P..h.K..R..H|
00000020  2c 52 48 30 0a                                    |,RH0.|
qwr
fonte
1

Oracle SQL, 115 bytes

select count(decode(sign(decode(l,2,29,32)-y/l),1,1))from t,
xmltable('1to 12'columns l int path'.')where mod(y,l)=0

Podemos notar que, na verdade, não importa quantos dias em abril (e meses posteriores), desde 100/4 <28. Também não é necessário verificar se o ano é bissexto ou não. Nós apenas temos que especificar que há 28 dias em fevereiro (não 29, porque essa validação será executada apenas para 2058, o que não é um salto), caso contrário, pode ser apenas 31 por qualquer mês.

Outras abordagens

Oracle SQL (12c Release 2 e posterior), 151 bytes

select count(to_date(y/l||'-'||l||'-1' default '' on conversion error,'dd-mm-y'))from t,
(select level l from dual connect by level<=12)where mod(y,l)=0

Oracle SQL (12c Release 2 e posterior), 137 bytes

select sum(validate_conversion(y/l||'-'||l||'-1'as date,'dd-mm-y'))from t,
(select level l from dual connect by level<=12)where mod(y,l)=0

Ambas as soluções poderiam ter sido 8 bytes mais curtas se substituirmos (select level l from dual connect by level<=12)por, xmltable('1to 12'columns l int path'.')mas o Oracle lança uma exceção por causa do bug (testado nas versões 12.2.0.1.0, 18.3.0.0.0).

SQL> select count(to_date(y/l||'-'||l||'-1' default '' on conversion error,'dd-mm-y'))from t,
  2  xmltable('1to 12'columns l int path'.')where mod(y,l)=0
  3  /
select count(to_date(y/l||'-'||l||'-1' default '' on conversion error,'dd-mm-y'))from t,
*
ERROR at line 1:
ORA-00932: inconsistent datatypes: expected DATE got DATE


SQL> select sum(validate_conversion(y/l||'-'||l||'-1'as date,'dd-mm-y'))from t,
  2  xmltable('1to 12'columns l int path'.')where mod(y,l)=0
  3  /
select sum(validate_conversion(y/l||'-'||l||'-1'as date,'dd-mm-y'))from t,
*
ERROR at line 1:
ORA-43909: invalid input data type

O único caso em ambas as soluções, quando o ano importa, é 2058, que é sem salto, então literalmente '-1' foi usado para especificar o ano sem salto.

Oracle SQL, 128 bytes

select count(d)from t,(select date'1-1-1'+level-1 d from dual connect by level<365)
where to_char(d(+),'mm')*to_char(d(+),'dd')=y

Oracle SQL, 126 bytes

select substr('122324243426133415153317223416132126011504033106131204241006003213011306002122042005101305111014012',y,1)from t

Atualizar

Oracle SQL, 110 bytes

select-sum(least(sign(y/l-decode(l,2,29,32)),0))from t,
xmltable('1to 12'columns l int path'.')where mod(y,l)=0

Oracle SQL, 108 bytes

select sum(decode(sign(decode(l,2,29,32)-y/l)*mod(y+1,l),1,1))from t,
xmltable('1to 12'columns l int path'.')

Spark SQL, 137 bytes

select count(cast(regexp_replace(concat_ws('-','2001',l,y/l),'.0$','')as date))
from(select explode(array(1,2,3,4,5,6,7,8,9,10,11,12))l),t

Spark 2.3+ SQL, 126 bytes

(a replacefunção fica disponível)

select count(cast(replace(concat_ws('-','2001',l,y/l),'.0')as date))
from(select explode(array(1,2,3,4,5,6,7,8,9,10,11,12))l),t
Dr. Y Wit
fonte
1

PHP , 73 bytes

Usando entrada de tubo e php -nR:

for(;++$m<13;$d=1)while($d<25+($m-2?$m>4?:7:4))$c+=$argn==$m*$d++;echo$c;

Experimente online!

PHP , 76 bytes

Usando a entrada de linha de comando arg php dm.php 18:

for(;++$m<13;$d=1)while($d<25+($m-2?$m>4?:7:4))$c+=$argv[1]==$m*$d++;echo$c;

Experimente online!

Abordagem iterativa. Como o único ano bissexto a ser observado é 2 * 29 = 58, e 2058 não é um ano bissexto, não há necessidade de considerar o ano bissexto nos dias de fevereiro. E como a envolvente não é uma preocupação - a partir de abril, qualquer dia maior que 25 excederá 100, apenas dizemos que o restante dos meses tem apenas 25 dias.

A entrada é de 2 dígitos ano via linha de comando (-10 bytes como programa, thx à sugestão de @Titus).

OU:

PHP , 101 bytes

$y=$argv[1];for($d=strtotime("$y-1");date(Y,$d)==$y;$d+=86400)eval(date("$\x+=j*n=='y';",$d));echo$x;

Experimente online!

Ainda iterativo, mas usando as funções de carimbo de data / hora do PHP. Aceita ano como número de quatro dígitos. Thx para @Titus por sugestão de uso em strtotime()vez de mktime().

640KB
fonte
A primeira versão falha por anos de 4 dígitos, a segunda falha por dois dígitos. Mas bom pensamento. Tente $m<5?$m-2?31:28:25pela primeira e $d=strtotime("$y-1")pela segunda
Tito
Uhm ... Por que você colocou yo eval entre aspas?
Titus
@Titus porque o PHP7 agora trata os dígitos precedidos por 0 como octal, portanto 08 e 09 não são válidos. tio.run/##K8go@G9jXwAkU5Mz8hUMFWxtFQwsrP//BwA Usando a função date (), você pode obter apenas um ano com 2 dígitos e preenchimento de zero.
640KB 04/02
Vadio! claro.
Titus
1
@Titus, segunda versão atualizada usando em strtotime()vez de mktime()e reimplementado como programa, -7 bytes. Além disso, observei a maioria dos envios, incluindo os mais votados, aceitarão o ano apenas com 2 ou 4 dígitos, por isso vou considerar que isso depende do remetente. Obrigado novamente pelas sugestões!
640KB 04/02
0

PHP, 74 70 bytes

while(++$m<13)for($d=$m<5?$m-2?31:28:25;$d;)$n+=$d--*$m==$argn;echo$n;

aceita apenas dois anos.

Eu adotei considerações gwaugh's e golfed-los; minha primeira abordagem foi maior que a dele (92 bytes):

for($y=$argn%100;++$m<13;)for($d=$m-2?30+($m+$m/8)%2:29-($y%4>0);$d;)$n+=$d--*$m==$y;echo$n;

%100 permite usar anos de 4 dígitos.


Execute como pipe -nRou experimente-os online .

Titus
fonte
Você pode salvar 4 bytes removendo o% 100 e aceitando apenas a entrada de 2 dígitos, o que é bom: codegolf.stackexchange.com/questions/162137/…
640 KB