Défi de multiplication des dates

19

(Inspiré par le Riddler de la semaine dernière sur FiveThirtyEight.com. Publication Sandbox .)

Étant donné une année entre 2001 et 2099, calculez et renvoyez le nombre de jours au cours de cette année civile où mm * dd = yy(où yyest l' année à deux chiffres ).

2018, par exemple, en a 5:

  • 18 janvier (1 * 18 = 18)
  • 9 février (2 * 9 = 18)
  • 6 mars (3 * 6 = 18)
  • 3 juin (6 * 3 = 18)
  • 2 septembre (9 * 2 = 18)

L'entrée peut être une année numérique à 2 ou 4 chiffres.

La sortie doit être un entier. L'espace de fuite ou le retour facultatif est très bien.

Liste complète des entrées / sorties:

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

Il s'agit d'un défi de , le nombre d'octets le plus bas dans chaque langue gagne.

Le pré-calcul et la simple recherche des réponses sont normalement exclus selon nos règles sur les échappatoires , mais je l'autorise explicitement pour ce défi. Il permet des stratégies alternatives intéressantes, bien qu'il soit peu probable qu'une liste de recherche de 98 à 99 éléments soit la plus courte.

BradC
la source
Si cela vous facilite la tâche dans votre langue, la réponse sera la même quel que soit le siècle; 1924 et 2124 ont le même nombre de jours que 2024.
BradC
si le résultat de mm * dd est supérieur à 100, il est automatiquement filtré?
DanielIndie
@DanielIndie Correct, aucune date "enveloppante" ne doit être comptée. En d'autres termes, le 12 décembre 2044 ne compte pas, même si 12 * 12 = 144.
BradC
Comme nous n'avons besoin de gérer qu'un nombre limité d'entrées, je les ai toutes éditées. N'hésitez pas à les restaurer ou à les reformater.
Shaggy
1
@gwaugh Juste que vous pouvez décider lequel accepter comme entrée valide (vous n'avez donc pas à dépenser de caractères supplémentaires pour convertir entre les deux).
BradC

Réponses:

14

Excel, 48 octets

Hourra! Enfin, quelque chose qu'Excel est vraiment bon.

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

Prend l'entrée de A1 sous la forme d'un entier 1-99 représentant l'année, et sort à l'endroit où vous entrez cette formule. C'est une formule matricielle, utilisez donc Ctrl-Maj-Entrée au lieu de Entrée pour la saisir.

Cela tire parti du fait que les COUNTerreurs sont ignorées , de sorte que toutes les erreurs causées par le mois ne divisant pas l'année (conduisant Excel à analyser quelque chose comme 2/12.5/25ou par la date non valide, comme 2/29/58, sont simplement ignorées silencieusement.

Sophia Lechner
la source
1
Très agréable. Il vaut probablement la peine de le mentionner, il faut une année à deux chiffres A1. La saisie d'une année à 4 chiffres revient simplement 0.
BradC
Vrai! Je vais modifier cela dans la description.
Sophia Lechner
Je devrais également mentionner que c'est spécifique à l'environnement local; cela dépend d'avoir une locale qui utilise un ordre mm / jj / aa. Dans un environnement local avec un ordre jj / mm / aa, la réponse serait bien sûr le même nombre d'octets.
Sophia Lechner
1
Super intelligent; J'aime la façon dont vous ne testez que 12 candidats (un par mois), au lieu de parcourir tous les jours de l'année.
BradC
Fixer l'année à un octet de sauvegarde sans saut?
l4m2
6

Python 2 , 44 octets

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

Essayez-le en ligne!

Une fonction anonyme donnée comme objet de méthode. Produit tous les produits de (month, day)paires (m, d)telle que codée par k=32*m+davec 0≤m≤12, 0≤d≤31enveloppant autour. Élimine les 29 et 31 février en les excluant de la plage.

xnor
la source
5

Java (JDK 10) , 65 octets

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

Essayez-le en ligne!

Crédits

Olivier Grégoire
la source
Aucune année bissextile ne convient 29*n, donc pas besoin du chèque
l4m2
Merci pour votre contribution. Je pourrais supprimer 27 octets au total avec un tas d'autres changements.
Olivier Grégoire
1
Passer (m==2?29:32)à 29+m%2*3semble toujours donner tous les OKrésultats. Crédit @AsoneTuhid réponse Ruby s » .
Kevin Cruijssen
4

PowerShell , 94 octets

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

Essayez-le en ligne!

Prend l'entrée comme une année à deux chiffres, puis construit une forboucle de 1/1/yearà 12/9/year(car 12/10 et au-delà ne compteront jamais et cela économise un octet). À chaque itération, nous incrémentons $zsi le nombre de .Monthfois .Dayest égal à notre année d'entrée. En dehors de la boucle, $zest laissé sur le pipeline et la sortie est implicite.

Modifier - cela dépend de la culture. Le code ci-dessus fonctionne pour en-us. Le format de la date peut devoir changer pour d'autres cultures.

AdmBorkBork
la source
2
"culture"? Voulez-vous dire "locale"? ...
user202729
1
@ user202729 Familièrement, oui, mais la documentation PowerShell l'appelle "culture".
AdmBorkBork
"Culture" est le mot que MS utilise généralement pour parler de paramètres régionaux, par exemple. System.Globalization.CultureInfo dans .NET.
sundar
3

JavaScript (ES6), 91 octets

J'étais curieux de savoir comment le codage en dur se comparerait à un calcul itératif. C'est définitivement plus long (voir la réponse de @ Shaggy ), mais pas terriblement plus long.

Edit : Elle est cependant beaucoup plus longue qu'une formule plus directe (voir réponse @ l4m2 ).

Prend l'entrée comme un entier dans [1..99] .

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

Essayez-le en ligne!

Comment?

Les années impaires ont significativement moins de chances d'avoir mm * jj = aa que les années paires. Plus concrètement, les années impaires ont 0 à 3 correspondances, tandis que les années paires ont 0 à 7 correspondances. Cela nous permet de coder chaque paire d'années avec seulement 5 bits, qui peuvent commodément être représentés comme un seul caractère dans la base 36.

Arnauld
la source
3

Utilitaires Bash + GNU , 57

  • 1 octet enregistré grâce à @SophiaLechner
seq -f1/1/$1+%gday 0 365|date -f- +%m*%d-%y|bc|grep -c ^0

Notez que le seq commande produit toujours une liste de 366 dates - pour les années non bissextiles, le 1er janvier de l'année suivante sera inclus. Cependant, dans la plage de dates 2001..2099, MM * DD ne sera jamais YY pour le 1er janvier de l'année suivante pour aucune de ces années, donc ce jour supplémentaire n'affectera pas le résultat.

Essayez-le en ligne!

Traumatisme numérique
la source
Très bien - je ne savais même pas que dateje ferais des calculs de datation comme ça pendant l'analyse. seqn'a pas besoin d'espace après le -f, vous pouvez donc y enregistrer un octet.
Sophia Lechner
3

T-SQL, 123 121 octets

Conformément à nos règles d'E / S , l'entrée est effectuée via la table préexistante t avec un champ entier y , qui contient une année à 2 chiffres.

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

Le saut de ligne est uniquement pour la lisibilité. Inspiré en grande partie par la solution Excel de Sophia .

  • La ligne supérieure génère une table de numéros à 12 éléments c qui est jointe à la table d'entrée t .
  • Si cela réussit, j'écrase un candidat de date en utilisant CONCAT(), ce qui varcharentraîne des conversions de type de données implicites . Sinon, je devrais faire un tas de CASTouCONVERT déclarations .
  • Trouvé la fonction d'évaluation parfaite ISDATE() , qui renvoie 1 pour les dates valides et 0 pour les dates non valides.
  • Enveloppez-le dans un SUM et j'ai terminé.
  • EDIT : Déplacement de la division entière check ( y%m=0) dans la WHEREclause pour enregistrer 2 octets, merci @RazvanSocol.

Malheureusement, elle n'est pas beaucoup plus courte que la version de la table de recherche (en utilisant la chaîne de la version d' osdavison ):

Recherche T-SQL, 129 octets

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

ÉDITER : Laissant mon original ci-dessus, mais nous pouvons économiser quelques octets en utilisant quelques nouvelles fonctions:

  • STRING_SPLIT est disponible dans MS SQL 2016 et supérieur.
  • CONCAT_WS est disponible dans MS SQL 2017 et supérieur.
  • Comme ci-dessus, remplacé IIFparWHERE

MS-SQL 2017, 121118 octets

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, édition extra cheaty: 109 octets

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

Vous oblige à être dans la masterbase de données, qui contient une table système spt_valuesqui (lorsqu'elle est filtrée par TYPE='P'), vous donne des nombres de comptage de 0 à 2048.

BradC
la source
Semblable à d'autres réponses, l'ordre dans lequel j'assemble la date ( m/d/y) dépend des paramètres de localité de l'instance SQL. D'autres localités peuvent nécessiter un ordre différent ou un séparateur différent, mais je ne pense pas que cela affecterait la longueur du code.
BradC
Je suppose que vous vous êtes rendu compte que la conversion du 29/02/64 en une date donne le 29/02/1964 (pas le 2064-02-29), mais étant donné que les années 2000 et 2100 sont exclues, c'est une bonne façon de raccourcir code.
Razvan Socol
L'utilisation SPLIT_STRINGau lieu d'un CTE le ramène à 120 octets. Utiliser à la CONCAT_WSplace de CONCATsauvegarde un autre caractère, le portant à 119 octets.
Razvan Socol
@RazvanSocol Oui, je ne sais pas où se situe la pause entre les dates à 2 chiffres qui correspondent à 19xx contre 20xx, mais les deux donnent la même réponse. Je vais essayer les deux autres suggestions, merci!
BradC
1
Remplacez IIFpar WHERE.
Razvan Socol
3

Julia 0,6 , 49 44 42 octets

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

Essayez-le en ligne!

-5 octets inspirés de la réponse Ruby d'Asone Tuhid.
-2 octets remplaçant count par sum

Explication:

Pour chaque mois ide 1 à 12, calculez y/iet vérifiez s'il s'agit de l'un des jours de ce mois. Les mois avec 31 jours sont 1, 3, 5, 7, 8, 10, 12 - donc ils sont impairs en dessous de 8 et même au-dessus de 8. Donc soit i%2ou i÷8(qui est 0 pour i <8 et 1 pour i> = 8 ici) devrait être 1, mais pas les deux - nous les avons donc XOR. Si le résultat xor est vrai, nous vérifions les dates 1:28+3c. 1:31-à- d. , Sinon nous vérifions uniquement les dates1:28 .

1:28est suffisant pour le reste des mois (cette amélioration inspirée de la réponse Ruby d'Asone Tuhid ) car:

  • pour février, la seule possibilité aurait été 2*29 = 58, mais ce 2058n'est pas une année bissextile, nous pouvons donc supposer que février a toujours 28 jours.

  • les autres mois avec 30 jours sont le mois 4 et plus - pour lequel i*29(et i*30) serait supérieur à 100, ce qui peut être ignoré.

Enfin, nous comptons le nombre de fois y/iappartient à cette liste de jours (en utilisant booléen sumici), et retournons cela.

Sundar - Rétablir Monica
la source
3

JavaScript, 91 85 82 81 77 octets

Prend l'entrée comme une chaîne à 2 chiffres (ou un entier à 1 ou 2 chiffres).

Profite du fait que new Datele report au mois suivant et continue ainsi, si vous lui passez une valeur de jour qui dépasse le nombre de jours du mois que vous lui passez, donc, lors de la première itération, il essaie de construire le date yyyy-01-345qui devient yyyy-12-11, ou yyyy-12-10sur les années bissextiles. Nous n'avons pas besoin de vérifier les dates après cela, car cela 12*11+donne un nombre à 3 chiffres.

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

3 octets économisés grâce à Arnauld .


Essaye-le

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>

Hirsute
la source
2

Excel, 83 octets

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

L'entrée est dans la cellule A1au format yyyy. Il s'agit d'une formule matricielle entrée avec Ctrl+ Shift+Enter pour obtenir les accolades{} . C'est assez simple et sans aucune intelligence.

Dans une formule matricielle, DATE(A1,1,0)+ROW(1:366)nous donne un tableau de 366 valeurs de date. Les années non bissextiles, cela inclura le 1er janvier de l'année suivante, mais ce n'est pas un problème car 1*1=1et ne serait considéré comme un faux positif que si l'année suivante est2001 mais, puisque la plage d'années requise est2001 - 2099 , elle ne se présentera problème.

Si vous avez raccourci ce bit en simplement ~, la formule est beaucoup plus facile à suivre:

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

J'ai essayé d'utiliser COUNTIF()au lieu de SUM(IF())mais Excel ne me permettait même pas de le saisir sous forme de formule de tableau, encore moins de me donner un résultat. Je l' ai trouver une Sheets Google solution en utilisant , CountIf()mais la même méthode autrement que avéré être 91 octets, principalement parce qu'il utilise au ArrayFormula()lieu de simplement { }.

=CountIf(ArrayFormula(Month(Date(A1,1,0)+Row(1:366))*Day(Date(A1,1,0)+Row(1:366))),A1-2000)
Ingénieur Toast
la source
Je n'ai pas vu de consensus, mais je n'ai généralement pas inclus les accolades externes dans mon nombre d'octets pour Excel. Ils ressemblent plus à une façon dont Excel met en forme son affichage qu'à une partie de la formule. Des avis?
Sophia Lechner
@SophiaLechner Je les ai inclus au lieu de décider comment inclure les touches supplémentaires nécessaires pour le saisir comme formule de tableau. Il y a une méta-question à ce sujet et la seule réponse indique que la commande CTRL + ALT + ENTRÉE compterait comme 1 frappe. Si vous utilisez la même chose que vim ( par méta ), alors cette frappe comptera comme 1 octet. Cependant, je ne compte généralement pas l'entrée à la fin de la saisie d'une formule comme 1 octet dans les autres réponses.
Engineer Toast
2

Retina 0.8.2 , 55 octets

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

Essayez-le en ligne! Prend une année à deux chiffres; ajoutez 1 octet pour prendre en charge les années à 4 chiffres. Explication: La première étape se transforme simplement en unaire. La deuxième étape commence par faire correspondre 1 à 12 caractères avant la position de correspondance, ce qui représente le mois, puis essaie d'anticiper un nombre entier de répétitions de ce mois. Cependant, l'anticipation contient un conditionnel, qui choisit entre 27 ou 30 répétitions supplémentaires selon le mois. Le nombre de positions de match est alors le résultat souhaité.

Neil
la source
2

R , 22 122 octets

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

Essayez-le en ligne!

A décidé d'adopter une approche de table de correspondance. L'année d'entrée doit être composée de 2 chiffres.

Robert S.
la source
1
Également sur TIO, vous pouvez cliquer sur le bouton "lien" et il formatera automatiquement la réponse pour vous. Merci à Dennis de l'avoir installé!
Giuseppe
Vous pouvez supprimer l'initiale if, car l'entrée peut être à 2 ou 4 chiffres, votre choix (vous pouvez donc choisir d'accepter uniquement l'entrée à 2 chiffres). Mais il semble que le code considère que chaque mois contient 31 jours, donc par exemple, 62 (pour 2062) renvoie 1 où il devrait retourner 0.
sundar - Rétablir Monica
2
J'ai mal compris. Cela étant dit, je suis presque sûr que la table de recherche devrait être incluse dans le nombre d'octets.
ngm
@ngm Je n'étais pas sûr non plus si la table de recherche devait être incluse, mais je l'ajouterai au nombre d'octets juste pour être sûr.
Robert
Je ne sais toujours pas quelles sont toutes les règles!
ngm
2

C (gcc), 65 60 59 octets

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

Port de la réponse Java de user202729 . Essayez-le en ligne ici . Merci à Jonathan Frech d' avoir joué au golf 1 octet.

OOBalance
la source
a=0,m=13;for(;~> for(a=0,m=13;.
Jonathan Frech
@JonathanFrech Merci d'avoir souligné cela, j'ai édité.
OOBalance
2

J , 29 octets

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

Essayez-le en ligne!

Comment ça fonctionne

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

J'ai essayé dur d'obtenir moins de 2 fois la solution de gelée :)

Note latérale

Si quelqu'un veut vraiment coder en dur les données à 99 chiffres, voici quelques informations:

Divisez les 99 chiffres en morceaux de 2 chiffres. Ensuite, le premier chiffre est <4et le second <8, ce qui signifie que cinq bits peuvent coder deux nombres. Ensuite, les données entières peuvent être codées en 250 bits ou 32 octets.

Bubbler
la source
2

Python 3 , 158 162 162 215 241 octets

Supprimé 4 Merci à Stephen d'avoir joué au conditionnel.

Supprimé 53 merci Stephen pour avoir souligné l'espace blanc

Supprimé 26 grâce au lien fourni par caird

Je suis assez nouveau dans ce domaine. Je ne pouvais pas penser à comment faire cela sans avoir décrit les jours d'un mois.

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

Essayez-le en ligne!

akozi
la source
5
Bienvenue sur le site et bon premier post! Il existe plusieurs façons de jouer au
caird coinheringaahing
@cairdcoinheringaahing Merci pour les conseils, le lien a été très utile!
akozi
1
158 octets - joué au golf à l'extérieur, mais la plupart du temps, vous aviez une longue file d'attente sur votre troisième ligne, vous ne savez pas comment ils y sont arrivés
Stephen
@Stephen Merci :) J'ai ajouté le vôtre en deux modifications. Un pour l'espace blanc et l'autre pour le golf.
akozi
(28if Y%4else 29) can be shortened to [29,28][Y%4>0]. Also, the long list can be shortened to [a,...]+2*[a,b,a,b,a]. a,b,c can be added in the parameter list to save a line. int(str(Y)[2:]) can be shortened to Y%100. Finally, counter variables can mostly be shortened to lens of list comprehensions, this also allows n to be made a lambda. This makes 118.
Black Owl Kai
2

Forth (gforth), 60 59 bytes

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

Try it online!

Cette version tire parti du fait qu'il ne peut pas y avoir plus d'un jour de correspondance par mois et que l'année doit être divisible par le mois pour qu'elle corresponde.

Explication

Itère au fil des mois, vérifie si l'année est divisible par mois et si le quotient est <31 (28 pour février) Les mois après mars ne peuvent pas correspondre aux jours supérieurs à 25, nous pouvons donc supposer tous les mois (autres que février) avoir 31 jours pour le casse-tête.

Explication du code

: 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] - Forth a le concept de nombres à double longueur, qui sont stockés sur la pile sous la forme de deux nombres à longueur unique (de la forme xy, où la valeur du double = y * 2^(l) + xoù l est la taille en bits d'un simple dans le quatrième implémentation avec laquelle vous travaillez).

Dans ce cas, j'ai comparé le quotient et le reste à 32 (ou 29) 0. Si le reste était supérieur à 0 (année non divisible par mois), le premier double serait automatiquement supérieur à 32 (ou 29) 0 et le résultat serait faux. Si le reste est égal à 0, il résout efficacement un contrôle régulier du quotient <= 32 (ou 29)

Forth (gforth) , 61 octets

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

Essayez-le en ligne!

Saved some bytes by realizing that only February matters in terms of having the correct number of days in the month

Explanation

Forth (at least gforth) comparisons return -1 for true and 0 for false

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
la source
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;}

Try it online!

user202729
la source
@Shaggy Thanks! (leftover from previous version where I loop over all days)
user202729
If you change && to & it's the same answer as OlivierGrégoire's Java answer, although he has answered 19 minutes earlier.
Kevin Cruijssen
@KevinCruijssen Random coincidence. Although my version is a bit worse (unnecessary use of ternary).
user202729
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>


la source
Brute-force lookup, nice!
BradC
Welcome to PPCG!
Shaggy
1

Python 3, 132 bytes

This is really quite long of a program but I thought it might be of interest.

All the values are between 0-7 so I encode each number with 3 bits in a long binary string. I tried pasting a raw binary string into my python program but I couldn't get it to work, so I settled on base64 in the file.

I used the following string as a lookup table (ending 7 used for padding): 01223242434261334151533172234161321260115040331061312042410060032130113060021220420051013051110140127

The program takes this string and decodes it as a number, then uses bit shifting to extract the result.

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

66 bytes + 37 byte file = 103 bytes

This reads a binary file called e and avoids using base64.

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

Here is a hexdump of the read file (without padding):

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
la source
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

We may note that it does not really matter how many days in April (and later months), since 100/4 < 28. Also it's not necessary to check whether year is leap or not. We just have to specify that there are 28 days in February (not 29 because that validation will be executed only for 2058 which is not leap) otherwise it may be just 31 for any month.

Other approaches

Oracle SQL (12c Release 2 and later), 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 and later), 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

Both solution could have been 8 bytes shorter if we replace (select level l from dual connect by level<=12) with xmltable('1to 12'columns l int path'.') but Oracle throws an exception because of the bug (tested on versions 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

The only case in both solution when year does matter is 2058 which is non-leap so literal '-1' was used to specify non-leap year.

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

Update

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

(replace function becomes available)

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
la source
1

PHP, 73 bytes

Using pipe input and php -nR:

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

Try it online!

PHP, 76 bytes

Using command line arg input 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;

Try it online!

Iterative approach. Since the only leap year to look at is 2 * 29 = 58, and 2058 is not a leap year there's no need to consider leap year in the Feb days. And since wraparound is not a concern -- from April on, any day greater than 25 will exceed 100 we just say the rest of the months only have 25 days.

Input is 2 digit year via command line (-10 bytes as program, thx to suggestion from @Titus).

OR:

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;

Try it online!

Still iterative but using PHP's timestamp functions. Accepts year as four digit number. Thx to @Titus for suggestion of using strtotime() instead of mktime().

640KB
la source
First version fails for 4-digit years, second fails for two-digit. But nice thinking. Try $m<5?$m-2?31:28:25 for the first and $d=strtotime("$y-1") for the second
Titus
Uhm ... Why did you put the y in the eval in quotes?
Titus
@Titus because PHP7 now treats digits preceeded with 0 as octal, so 08 and 09 are actually not valid. tio.run/##K8go@G9jXwAkU5Mz8hUMFWxtFQwsrP//BwA Using the date() function you can only get a 2 digit, zero-padded year.
640KB
Bummer! of course.
Titus
1
@Titus, updated second version using strtotime() instead of mktime() and re-implemented as program, -7 bytes. Also, I looked at the majority of the submissions, including the top voted ones, will only accept year as either 2 or 4 digits, so I'm going to take that to mean it is up to submitter. Thx again for the suggestions!
640KB
0

PHP, 74 70 bytes

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

accepts two-digit years only.

I adopted gwaugh´s considerations and golfed them; my 1st approach was longer than his (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 allows to use 4-digit years.


Run as pipe with -nR or try them online.

Titus
la source
You can save 4 bytes by removing the %100 and only taking 2 digit input, which is OK: codegolf.stackexchange.com/questions/162137/…
640KB