Combien de vendredi le 13 dans une année?

28

Votre défi est d'écrire un programme qui, compte tenu d'une année, affiche le nombre de "vendredi 13".

Règles et détails:

  • Vous pouvez saisir des informations via STDINou comme argument transmis à votre programme.
  • Vous devez afficher le résultat dans STDOUT.
  • Vous pouvez supposer que la saisie sera une année valide et ne date pas d'avant le calendrier grégorien (un comportement indéfini est autorisé dans ces cas).
  • Les bibliothèques de calendrier / date sont autorisées.

Il s'agit d'un , donc le code le plus court (en octets) l'emporte.

(Lien de défi connexe)

Cruncher
la source
7
Quelle est la plage d'entrée requise? Si cela va bien avant 1800, quelles hypothèses faut-il faire sur le passage du calendrier julien au calendrier grégorien?
Peter Taylor
@PeterTaylor Je n'y avais pas pensé. Si une date est antérieure à la date grégorienne, vous pouvez avoir un comportement indéfini.
Cruncher
1
Les premiers pays à adopter le calendrier grégorien l'ont fait en octobre 1582, à la suite de la bulle de Grégoire lui-même. Les pays qui ont adopté le nouveau calendrier tardivement n'ont pas changé avant le 20e siècle, par exemple la Grèce l'a introduit le 1er mars 1923.
Jeppe Stig Nielsen
@JeppeStigNielsen Je ne connais pas grand-chose aux calendriers et autres. Qu'ils les aient adoptés ou non ne change pas les dates grégoriennes. Les bibliothèques devraient être en mesure de calculer les dates depuis bien longtemps, je suppose?
Cruncher
3
Je suis hors sujet ici, je suppose. De nombreuses bibliothèques écrites par des programmeurs anglo-américains utilisent septembre 1752 comme heure "correcte" de changement de calendrier. C'est à ce moment que l'Empire britannique a changé. Bien entendu, le nouveau calendrier a été conservé lors de la fondation des États-Unis. (Par curiosité, certains logiciels SQL ont 1753 comme année minimale car ils ne veulent pas faire face au problème de septembre 1752.) Cependant, l'utilisation de septembre 1752 est très anglocentrique. Vous avez raison, les dates grégoriennes sont les mêmes, qu'elles aient été utilisées historiquement ou non. C'est le soi-disant calendrier grégorien proleptique .
Jeppe Stig Nielsen

Réponses:

3

APL (Dyalog APL) avec cal des dfns , 29 octets

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

Essayez-le en ligne!

⍳ 12 les entiers un à douze

⎕ ,¨ prendre une entrée numérique et ajouter à chacun des douze nombres

{ Sur chacune des paires, appliquez la fonction…

cal⍵ obtenir un calendrier pour cette année-mois

2 ↓ déposer deux lignes (légende et jours)

 transposer (afin que nous puissions adresser des colonnes au lieu de lignes)

¯5 ↑ prendre les cinq derniers (deux chiffres pour chacun des vendredis et samedis plus un espace)

3 ↑ prendre les deux premiers (deux chiffres pour vendredi plus un espace)

 transposer (donc on obtient l'ordre de lecture)

, effilochage

 exécuter comme expression APL (donne la liste des dates du vendredi)

13 ∊ treize est-il membre de cette liste?

+/ additionner les 12 booléens


En utilisant l'algorithme de @ Wrzlprmft , nous pouvons le faire sans bibliothèques pour 53 octets:

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

-∘0 1 soustraire zéro et un

400 100 4 ∘.| tableau des divisions restantes pour les deux années (dans l'ensemble) divisé par ces chiffres (vers le bas)

0 ≠.= "produit" intérieur avec 0, mais en utilisant ≠ et = au lieu de +. ×

⊢ , ajouter l'année de l'argument non modifié

2 3 ¯1 +.× produit intérieur avec ces chiffres

14 | reste de division divisé par quatorze

'21232211321211' ⌷⍨ indexer dans cette chaîne

Adam
la source
C'est 29 caractères, mais ce sont plus de 1 octet, n'est-ce pas?
Cruncher
@Cruncher J'ai ajouté un lien explicatif dans la rubrique. Si vous ouvrez le lien TIO, vous verrez qu'il indique "29 caractères, 29 octets (SBCS)" sur la droite, c'est-à-dire le jeu de caractères à octet unique.
Adám
Eh bien, je suppose que c'est le nouveau gagnant alors, est-ce une pratique standard dans cette SE de changer la réponse acceptée aussi longtemps après la question?
Cruncher
@Cruncher Oui. Et il y a même des badges à avoir pour être accepté longtemps après OP.
Adám
12

Mathematica 49 46 45 44 42

En tant que fonction pure : 42 caractères

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

Exemple

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

2


En tant que fonction nommée : 44 caractères

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

Exemples

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

2
3
2
1

DavidC
la source
Un caractère plus court:f=DayName@{#,m,6}~Table~{m,12}~Count~Friday&
Mr.Wizard
@ Mr.Wizard Oui. Cela m'étonne que Mathematica puisse analyser les multiples cas de notation infixe.
DavidC
David surprend moi que vous ne l' avez pas vu mon (plus) l' utilisation de cette notation conjointe. : ^) (Exemples: (1) , (2) )
Mr.Wizard
8

Rubis, 49 48 47 46

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

Edit: Rasé un personnage en remontant une semaine, grâce à Jan, et un autre en passant de Time.new à Time.gm

Edit: Au détriment de l'obscurcir un peu plus, je peux arriver à 46 avec

f=->m{(1..12).count{|i|Time.gm(m,i,8).wday<1}}
histocrate
la source
5
économie d'un caractère si vous comptez le nombre de vendredis 6
John Dvorak
2
@JanDvorak intelligent!
histocrate
pourquoi 6? Je ne l'ai pas compris.
NARKOZ
3
Si le 6 est un vendredi, alors le 13 est également un vendredi
TwiNight
Si le 8 est un dimanche, le 1er l'est également, et vous pouvez donc l'utiliser Time.gm(m,i).wday<1. De plus, je ne sais pas pourquoi vous nommez la fonction.
Lee W
8

Powershell, 68 63 58 52 50

Merci Iszi pour l'astuce.

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

En utilisant le fait que si le 1er jour du mois est dimanche, le 13 sera vendredi.

J'ai aussi essayé:

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

mais ce n'est pas la même chose $argsà l'intérieur du bloc de script.

Danko Durbić
la source
1
J'aime l'idée d'utiliser le premier jour du mois.
Cruncher
Bon tour, là. Le @ n'est cependant pas nécessaire.
Iszi
Une autre chose, même si je suis coupable de la même chose dans beaucoup de mes scripts. Le défi spécifie que l'entrée peut provenir d'un argument. Remplacez-le $npar $argsdans la boucle, et vous pouvez vous en passer $n=read-host;complètement. Enregistre 8. Supprimez @, comme mentionné ci-dessus, et vous êtes à 54.
Iszi
Correction: descend à 52!
Iszi
J'essaie de comprendre pourquoi votre deuxième script ne fonctionnera pas et je suis perdu. Ce qui est intéressant, c'est que je peux changer $argspour $input, alimentant ainsi l'année depuis le pipeline, et le script s'exécutera mais il sort toujours 3.
Iszi
5

R 76 72 57

sum(format(as.Date(paste(scan(),1:12,1,sep="-")),"%w")<1)
flodel
la source
Peut facilement réduire cela 4 en remplaçant votre "%a %d")=="Fri 13"par "%w%d)=="513")en utilisant dow comme nombre et en supprimant les espaces.
chmullig
très appréciée!
flodel
+1 Bien que faire le seqseul du mois soit en fait plus court ici! sum(format(as.Date(paste(scan(),1:12,13,sep="-")),"%w%d")=="513")c'est seulement 65 caractères!
plannapus
wow, je n'aurais pas deviné que <cela contraindrait un caractère à un entier. Joli tour!
plannapus
@plannapus C'est assez courant. Puisque les codes de caractères sont tous des nombres. Même java peut comparer int et 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

Lundi 9 mai ne pas avoir la même sonnerie, mais fonctionne aussi bien.

Edit: Un an et demi pour remarquer que datec'est plus court que datetime:)

ejrb
la source
Solution vraiment sympa!
leancz
2
Vous pouvez enregistrer un caractère en faisantfrom datetime import*
user80551
Agréable! Je me suis retrouvé avec quelque chose effectivement identique, mais en évitant exec: f=lambda y:sum([date(y,m,13).weekday()==4 for m in range(1,13)]).... Solution de même taille avec l'importation (86 octets), cependant.
iwaseatenbyagrue
5

Ne pas utiliser de bibliothèques ou de fonctions de date intégrées:

Golfscript - 51

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

' [3/=RI[)a%:*.' pourrait aussi bien être 'feefefgeeffgfe'

Python - 82 79

Essentiellement le même algorithme.

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

En utilisant cette astuce , cela peut être approfondi pour:

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

Cela exploite le fait que, par calendrier, il n'y a que 14 années différentes, qui se distinguent par leur dernier jour et si elles sautent. lcalcule le nombre d'années bissextiles jusqu'à son argument (si le calendrier grégorien s'étendait en arrière jusqu'à l'année 1). (2*i+3*l(i)-l(i-1))%14est l'abréviation de l(i)-l(i-1)+(i+l(i))%7*2, où l(i)-l(i-1)nous indique si l'argument est une année bissextile et i+l(i)résume les changements du dernier jour (un dans une année normale, deux dans une année bissextile).

Wrzlprmft
la source
Puisqu'il s'agit de mon premier golf golfscript, j'apprécierais tout conseil sur la poursuite du golf.
Wrzlprmft
Je pensais à une telle solution en utilisant le fait qu'il n'y a en fait que 14 années uniques, mais je n'étais pas sûr de la meilleure langue pour la rendre compétitive. Je pense que c'est la réponse la plus courte sans bibliothèque. Si les années bissextiles étaient uniformément tous les 4 ans, vous pourriez gagner avec cela
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]-'`');}

Pas la réponse la plus courte, mais n'utilise aucune bibliothèque.

Williham Totland
la source
Hé, seriez-vous prêt à fournir une explication à la réponse non approuvée? Je suis intéressé par ce que vous avez fait exactement
Cruncher
1
@Cruncher, c'est une table de recherche sur la base que le calendrier grégorien suit un cycle de 400 ans.
Peter Taylor
1
De façon plus explicite (et plus), C #: static char GetNumberOfFriday13s(int year) { const string perpetualCalendar = "1221212213113213122221122131122121221311321312222112213112212122131132131222211221311221212213113213112213113213122221122131122121221311321312222112213112212122131132131222211221311221212213113213122213113213122221122131122121221311321312222112213112212122131132131222211221311221212213113213122221122213122221122131122121221311321312222112213112212122131132131222211221311221212213113213122221122131"; return perpetualCalendar[year % 400];. Ne fonctionnera pas pendant des années négatives.
Jeppe Stig Nielsen
Mignonne! Comme un petit bug, v[0]devrait l'être v[1]. Vous pouvez également jouer au golf un peu; envisagez d'utiliser strcat, de stocker des caractères pour imprimer directement a[]et de soustraire des constantes numériques au lieu de constantes de caractères. :)
user1354557
1
J'ai également amélioré la compression: 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 caractères)
user1354557
4

C ( 151 145 137 131 131 130 car.)

Je suis surpris de voir qu'il n'y a qu'une seule autre solution qui n'utilise pas d'outils de calendrier intégrés. Voici une approche mathématique (très obscure), également en 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));}

(Ce qui précède se compile dans GCC sans erreur)

Solution alternative: C (287-> 215 caractères)

J'ai plutôt apprécié la solution de Williham Totland et son utilisation de la compression. J'ai corrigé deux petits bugs et ajusté le code pour raccourcir sa longueur:

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

Basé sur

"Tout mois qui commence un dimanche contient un vendredi 13 et il y a au moins un vendredi 13 dans chaque année civile."

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

Damir Kasipovic
la source
4

bash 47 36

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

Merci à @DigitalTrauma d'avoir enregistré 10 caractères en utilisant seqle démarrage par défaut de 1.

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

(La version précédente utilisant echoprésentait un bogue à cause de la ligne vide quand <(echo $1-{1..12}-6$'\n'). Donc, cette fonction a bien fonctionné jusqu'à aujourd'hui est un vendredi.

Voyons voir:

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

Est dépend des paramètres régionaux , si cela ne fonctionne pas, vous devrez peut-être

export LANG=C

ou

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

Dans une fonction; +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

De là, si ma fonction devient:

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
la source
Cela semble dépendre des paramètres régionaux.
Peter Taylor
Oui, cela est basé sur la valeur par défaut C. Mais il y a un bug ...
F. Hauri
Enregistrez un caractère en ne citant pas votre chaîne de format printf et en échappant à la place \:%s\\n
Digital Trauma
1
Ou utilisez seqpour supprimer 8 caractères:date -f<(seq -f$1-%g-6 1 12)|grep -c ^F
Digital Trauma
1
En fait, vous pouvez raser 2 caractères supplémentaires. Si vous omettez le numéro de séquence de départ, seq commencera à 1 par défaut, ce que vous voulez: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
la source
et pourquoi c'est -1?
Lukasz 'Severiaan' Grela
1
Cela semble bon! Vous pouvez économiser quelques octets, en supprimant ,b,cde la déclaration de fonction (! Il est correct de fuite vars pour le golf), aussi best jeté comme Numbervous pouvez +=le résultat du test au lieu de &&b++: b+=/^F/.test(new Date(a,c,6)). Cependant, vous pouvez enregistrer un autre octet en utilisant !new Date(a,c,1).getDay()(cela fonctionne car getDayretourne 0 pour dimanche et si le 13 est un vendredi, le 1er sera un dimanche) au lieu de ce testqui devrait vous faire économiser 7 octets!
Dom Hastings
@DomHastings: merci pour vos conseils !!!
guy777
3

k

64 caractères

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

Lit à partir de stdin

skeevey
la source
Ok, qu'est-ce qui se passe ici? : P
Williham Totland
Lire l'année, construire la liste des dates du 13e jour de chaque mois, tester le jour de la semaine = vendredi, additionner la liste résultante des booléens
skeevey
3

Lisp commun (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
la source
Oh mon dieu, je n'ai jamais pu lire le 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);}

Merci à Jeppe Stig Nielsen pour linq et suggestion de vérifier dimanche le 8.

Merci à Danko Durbić d'avoir suggéré à la >place de ==.

Kami
la source
Au lieu de c+=(int)new DateTime(y,i,13).DayOfWeek==5?1:0;, utilisez l'équivalent c+=new DateTime(y,i,8).DayOfWeek==0?1:0;. L'astuce consiste à soustraire 5, car alors vous pouvez vous débarrasser de la distribution int, et le nombre 8a également un chiffre de moins que le nombre 13. Dimanche huitième!
Jeppe Stig Nielsen
Avec Linq: int g(int y){return Enumerable.Range(1,12).Count(m=>new DateTime(y,m,8).DayOfWeek==0);}. Bien sûr, en tant que lambda, c'est y=>Enumerable.Range(1,12).Count(m=>new DateTime(y,m,8).DayOfWeek==0).
Jeppe Stig Nielsen
Vous pouvez enregistrer un caractère en comparant .DayOfWeek<1.
Danko Durbić
@ DankoDurbić Cela peut s'appliquer à la c#réponse mais vous ne savez pas comment l'appliquer linq.
Kami
Mon erreur; apparemment, vous ne pouvez pas comparer DayOfWeekavec un autre entier que 0- error CS0019: Operator '<' cannot be applied to operands of type 'System.DayOfWeek' and 'int'.
Danko Durbić
2

PHP, 55 octets

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

Courez avec echo <year> | php -nR '<code>'.

Fondamentalement, la même chose qu'Oleg a essayé et Damir Kasipovic a fait, juste avec un meilleur golf:
chaque mois qui commence par un dimanche, a un vendredi 13.
Je passe donc en revue les mois et compte les premiers jours qui sont des dimanches.

panne

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

Bash ( 52 47 caractères)

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

Rebol, 63

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

Exemple d'utilisation dans la console Rebol:

>> y: 2012
== 2012

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

Une solution alternative qui recueille tous les vendredis 13 dans une année donnée est:

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

Bash et Sed, 39 ans

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

ncal imprime un calendrier pour l'année donnée avec les jours de la semaine en bas à gauche.

sedavec un /gdrapeau sous-marin tous les 13 avec des nouvelles lignes

grep -c compte les lignes commençant par "2" (20 suit toujours 13)

Merci à @DigitalTrauma d'avoir trouvé un bug dans mon ancienne version et d'avoir proposé une solution!

Pas que Charles
la source
Cela ne fonctionne pas tout à fait pour moi - les lignes du vendredi ne sont imprimées qu'une seule fois, même si elles en contiennent plus d'un 13.
Digital Trauma
1
Je pense que le mieux que je puisse faire avec quelque chose comme ça est 38:ncal $1|sed /F/s/13/\\n/g|grep -c ^\ 2
Digital Trauma
1
@DigitalTrauma Vous avez raison. À un moment donné, ce script fonctionnait. permettez-moi de le réparer.
Pas que Charles
1
@DigitalTrauma ressemble à une version beaucoup plus longue qui fonctionnait. merci pour le correctif!
Pas que Charles
Intéressant, l'expression sed non citée que j'ai proposée fonctionne avec GNU sed (Linux) mais pas avec BSD sed (OSX). Je suppose que vous pouvez gagner 1 char au prix de la portabilité si vous choisissez la version GNU.
Digital Trauma
1

Scala, 76 68 caractères

En 78 caractères:

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

Rien d'extraordinaire, sauf pour utiliser des nombres magiques pour DAY_OF_WEEK = 7et FRIDAY = 6.

Version 68 caractères:

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

Oui, Java a changé les valeurs des constantes du jour de la semaine entre les API.

Karol S
la source
C'est dommage, new java.util.GregorianCalendarça doit être si long :(
Cruncher
1

Python 195/204

Fonctionne uniquement pour les années précédentes, car monthdatescalendarrenvoie un calendrier pour l'année donnée jusqu'à présent . Je pense qu'il reste encore beaucoup de potentiel d'optimisation :).

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)

Une autre solution, fonctionne pour chaque date mais elle n'est pas plus petite:

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
la source
Dans votre premier exemple, la plage devrait être (1,13), sinon vous manqueriez le vendredi 13 décembre, comme en 2013.
leancz
1
Vous n'avez même pas pris la peine de jouer au golf. Supprimez certains de ces espaces.
mbomb007
1

Perl 6, 55 53

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

Ancienne réponse:

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

Perl + lib POSIX 55

Avec l'idée de ne pas chercher 13thmais d'abord, et comme sundayc'est le cas, 0économisons 3 caractères! Merci @ Iszi et Danko Durbić!

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

Pourrait calculer 2010 à 2017 (pour exemple) de cette façon:

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

(Ok, il n'y a pas de nouvelle ligne , mais cela n'a pas été demandé;)

Ancien poste: 63

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

En action:

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

Dans Smalltalk (saveur Squeak / Pharo), implémentez cette méthode dans Integer ( 86 caractères)

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

Puis l' utiliser comme ceci: 2014countFriday13.

Bien sûr, nous pourrions utiliser un nom plus court, mais ce ne serait pas Smalltalk

aka.nice
la source
0

C ++ - Trop d'octets :(

J'ai essayé une solution qui n'utilise aucune bibliothèque de dates.

J'ai trouvé une solution plutôt sympa (si je puis dire moi-même). Malheureusement, je ne peux pas le raccourcir, ce qui me dérange vraiment car il me semble qu'il devrait y avoir une meilleure solution.

La solution repose sur cet algorithme qui ne fait que 44 octets en soi. Malheureusement, j'ai besoin de 100 autres octets pour bien envelopper ...

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

Sortie via le code retour (en C ++, utiliser coutou printfou quelque chose comme ça en nécessite un autre #include, ce qui ferait exploser encore plus la solution).

Pilote / programme de 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

Sortie du programme pilote:

$ ./test_doomsday 
1766: 2
2013: 3
2013: 2
2014: 1
150 doomsday.cpp characters
CompuChip
la source
Je compte 88 pour l'algorithme, pas 44. Qu'est-ce que l'algorithme et quelle est la déformation? ($m<3?$y--:$y-2)+3au lieu de d=13,, d+=m<3?y--:y-2,et d+4devrait fonctionner aussi bien et économise beaucoup. +5au lieu de +3et -5devrait fonctionner aussi et économise 2 octets. for(m=0;++m<13;)enregistre un octet. Passer m=0à la tête de fonction enregistre un autre octet; et passer ()%7||++fà la tête de boucle en enregistre une autre. De 149 à 136 octets.
Titus
0

Clojure, 207 187 octets

-20 octets en se débarrassant de la import, et des espaces blancs que j'ai manqués.

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

À partir du 1er janvier de l'année donnée, il se boucle chaque jour. Si le jour est le vendredi 13, il incrémente le décompte. Il continue de boucler jusqu'à ce qu'il atteigne l'année prochaine.

(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.
Carcigenicate
la source
0

PHP, pas de code intégré, 81 octets

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

Courez avec echo <year> | php -nR '<code>'.

panne

Les jours de la semaine se répètent tous les 400 ans.
Dans les résultats de 1600 à 1999 (par exemple), il y a une période de 28 longueurs avec seulement trois lacunes:

  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

Après avoir ajusté l'année pour ces écarts, nous pouvons obtenir le résultat avec un hachage simple:

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

Pas court (95 octets) mais joli. Et nous pouvons jouer au golf

  • 4 octets en utilisant une chaîne ternaire pour le décalage,
  • 8 octets en convertissant la carte de hachage d'une chaîne base4 en entier,
  • un de plus en utilisant la représentation hexadécimale,
  • et un en fusionnant les expressions.
Titus
la source
Un port de la réponse C ++ de CompuChip peut être joué jusqu'à 84 octets: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 octets

CÆ5¥ÐUXD e

Essayez-le

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