¿Cuántos viernes 13 en un año?


28

Su desafío es escribir un programa que, dado un año, arroje el número de "Viernes 13" en él.

Reglas y detalles:

  • Puede recibir información a través de STDIN, o como un argumento pasado a su programa.
  • Debe enviar el resultado a STDOUT.
  • Puede suponer que la entrada será un año válido y no es anterior al calendario gregoriano (se permite un comportamiento indefinido en estos casos).
  • Se permiten bibliotecas de calendario / fecha.

Este es un , por lo que gana el código más corto (en bytes).

(Enlace de desafío relacionado)


77
¿Cuál es el rango de entrada requerido? Si va mucho antes de 1800, ¿qué suposiciones deberían hacerse sobre el cambio del calendario juliano al gregoriano?
Peter Taylor

@PeterTaylor No lo había pensado. Si una fecha es anterior a Gregory, entonces puede tener un comportamiento indefinido.
Cruncher

1
Los primeros países en adoptar el calendario gregoriano lo hicieron en octubre de 1582, siguiendo el toro del propio Gregorio. Los países que adoptaron el nuevo calendario tarde no cambiaron hasta el siglo XX, por ejemplo, Grecia lo introdujo el 1 de marzo de 1923.
Jeppe Stig Nielsen

@JeppeStigNielsen No sé mucho sobre calendarios y demás. Si los adoptaron o no, no cambia cuáles son las fechas gregorianas. Las bibliotecas deberían poder calcular fechas desde hace mucho tiempo, supongo.
Cruncher

3
Estoy siendo fuera de tema aquí, supongo. Muchas bibliotecas escritas por programadores angloamericanos utilizan septiembre de 1752 como la hora "correcta" de cambio de calendarios. Esto fue cuando el Imperio Británico cambió. El nuevo calendario se mantuvo cuando se fundó EE. UU., Por supuesto. (Como curiosidad, algunos softwares SQL tienen 1753 como el año mínimo ya que no quieren hacer frente al problema de septiembre de 1752). Sin embargo, usar septiembre de 1752 es muy anglocéntrico. Tienes razón, las fechas gregorianas son las mismas independientemente de si se usaron históricamente o no. Ese es el llamado calendario gregoriano proleptico .
Jeppe Stig Nielsen

Respuestas:


3

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

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

Pruébalo en línea!

⍳ 12 los enteros del uno al doce

⎕ ,¨ tomar entrada numérica y anteponer a cada uno de los doce números

{...  en cada uno de los pares, aplique la función ...

cal⍵ obtener un calendario para ese año-mes

2 ↓ soltar dos filas (título y días)

 transposición (para que podamos direccionar columnas en lugar de filas)

¯5 ↑ tome los últimos cinco (dos dígitos para cada viernes y sábado más un espacio)

3 ↑ tome los dos primeros (dos dígitos para el viernes más un espacio)

 transponer (para que podamos leer el orden)

, enmarañar

 ejecutar como expresión APL (da una lista de las fechas de los viernes)

13 ∊ ¿Trece es miembro de esa lista?

+/ suma los 12 booleanos


Usando el algoritmo de @ Wrzlprmft , podemos hacerlo sin bibliotecas para 53 bytes:

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

-∘0 1 restar cero y uno

400 100 4 ∘.| tabla de resto de división para los dos años (a través) dividida por estos números (abajo)

0 ≠.= "producto" interno con 0, pero usando ≠ y = en lugar de +. ×

⊢ , anteponer el año del argumento no modificado

2 3 ¯1 +.× producto interno con estos números

14 | resto de división cuando se divide por catorce

'21232211321211' ⌷⍨ indexar en esta cadena


Son 29 caracteres, pero estos son más de 1 byte ¿verdad?
Cruncher

@Cruncher He agregado un enlace explicativo en el encabezado. Si abre el enlace TIO, verá que dice "29 caracteres, 29 bytes (SBCS)" a la derecha, es decir, Conjunto de caracteres de un solo byte.
Adám

Bueno, supongo que este es el nuevo ganador, ¿es una práctica estándar en este SE cambiar la respuesta aceptada tanto tiempo después de la pregunta?
Cruncher

@Cruncher Sí. E incluso hay insignias para ser aceptado mucho después de OP.
Adám

12

Mathematica 49 46 45 44 42

Como una función pura : 42 caracteres

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

Ejemplo

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

2


Como una función con nombre : 44 caracteres

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

Ejemplos

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

2
3
2
1


Un personaje más corto:f=DayName@{#,m,6}~Table~{m,12}~Count~Friday&
Mr.Wizard

@ Mr.Wizard Sí. Me sorprende que Mathematica pueda analizar los múltiples casos de notación infija.
DavidC

David, me sorprende que no hayas visto mi (sobre) uso de esta notación conjunta. : ^) (Ejemplos: (1) , (2) )
Mr.Wizard

8

Rubí, 49 48 47 46

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

Editar: afeitó a un personaje retrocediendo una semana, gracias a Jan, y otro cambiando de Time.new a Time.gm

Editar: a expensas de ofuscarlo un poco más, puedo llegar a 46 con

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

55
one-char ahorro si cuenta los números del viernes 6
John Dvorak

2
@JanDvorak inteligente!
histocrat

¿Por qué 6? No lo entendí.
NARKOZ

3
Si el 6 es viernes, el 13 también es viernes
TwiNight

Si el octavo es domingo, entonces el primero también lo es, y así puede usarlo Time.gm(m,i).wday<1. Además, no sé por qué estás nombrando la función.
Lee W

8

Powershell, 68 63 58 52 50

Gracias Iszi por el dato.

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

Usando el hecho de que si el primer día del mes es domingo, el 13 será el viernes.

También he intentado:

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

pero no es lo mismo $argsdentro del bloque de script.


1
Me gusta la idea de usar el primer día del mes.
Cruncher

Buen truco, ahí. Sin embargo, el @ es innecesario.
Iszi

Otra cosa, aunque soy culpable de lo mismo en muchos de mis guiones. El desafío especifica que la entrada puede provenir de un argumento. Reemplace $ncon $argsen el bucle, y puede prescindir por $n=read-host;completo. Guarda 8. Elimina @, como se mencionó anteriormente, y tienes 54.
Iszi

Corrección: ¡se reduce a 52!
Iszi

Tratando de averiguar por qué su segundo script no funcionará y estoy perdido. Lo que es interesante es que puedo cambiar a cabo $argspara $input, alimentando así el año en el de la tubería, y el script se ejecutará, pero siempre da salida 3.
Iszi

5

R 76 72 57

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

Puede bajar esto fácilmente 4 al reemplazar su "%a %d")=="Fri 13"con el "%w%d)=="513")uso de dow como número y eliminar los espacios.
chmullig

¡muy apreciado!
flodel

+1 ¡Aunque hacer el seqúnico en el mes es más corto aquí! sum(format(as.Date(paste(scan(),1:12,13,sep="-")),"%w%d")=="513")solo tiene 65 caracteres!
plannapus

wow, no habría imaginado que eso <obligaría a un personaje a un entero ¡Buen truco!
plannapus

@plannapus Es bastante común. Dado que los códigos de caracteres son todos números. Incluso Java puede comparar int y 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

El lunes 9 puede no tener el mismo tono pero funciona igual de bien.

Editar: Un año y medio para notar que datees más corto que datetime:)


Muy buena solución!
leancz

2
Puede guardar un from datetime import*
personaje

¡Agradable! Terminé con algo efectivamente idéntico, pero evitando exec: f=lambda y:sum([date(y,m,13).weekday()==4 for m in range(1,13)]).... Solución del mismo tamaño con la importación (86 bytes), sin embargo.
iwaseatenbyagrue

5

No usar ninguna biblioteca o funciones de fecha integradas:

Golfscript - 51

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

' [3/=RI[)a%:*.' bien podría ser 'feefefgeeffgfe'

Python - 82 79

Esencialmente el mismo algoritmo.

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

Usando este truco , esto se puede reducir aún más para:

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

Esto explota el hecho de que, en cuanto al calendario, solo hay 14 años diferentes, que se distinguen por su último día y si están saltando. lcalcula el número de años bisiestos hasta su argumento (si el calendario gregoriano se extendió hacia atrás hasta el año 1). (2*i+3*l(i)-l(i-1))%14es la abreviatura de l(i)-l(i-1)+(i+l(i))%7*2, donde l(i)-l(i-1)nos dice si el argumento es un año bisiesto y i+l(i)resume los turnos del último día (uno en un año normal, dos en un año bisiesto).


Dado que este es mi primer golfscript, agradecería cualquier pista para seguir jugando al golf.
Wrzlprmft

Estaba pensando en una solución de este tipo utilizando el hecho de que solo hay 14 años únicos en realidad, pero no estaba seguro del mejor lenguaje para hacerlo competitivo. Creo que esta es la respuesta más corta sin bibliotecas. Si los años bisiestos fueran uniformes cada 4 años, es posible que pueda ganar con esto
Cruncher el

4

do 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]-'`');}

No es la respuesta más corta, pero no usa bibliotecas.


Oye, ¿estarías dispuesto a dar una respuesta sin respuesta con una explicación? Estoy interesado en lo que hiciste exactamente
Cruncher

1
@Cruncher, es una tabla de búsqueda sobre la base de que el calendario gregoriano sigue un ciclo de 400 años.
Peter Taylor

1
Más explícitamente (y más), C #: static char GetNumberOfFriday13s(int year) { const string perpetualCalendar = "1221212213113213122221122131122121221311321312222112213112212122131132131222211221311221212213113213112213113213122221122131122121221311321312222112213112212122131132131222211221311221212213113213122213113213122221122131122121221311321312222112213112212122131132131222211221311221212213113213122221122213122221122131122121221311321312222112213112212122131132131222211221311221212213113213122221122131"; return perpetualCalendar[year % 400];. No funcionará por años negativos.
Jeppe Stig Nielsen

¡Linda! Como un pequeño error, v[0]debería ser v[1]. También puedes jugar golf un poco; considere usar strcat, almacenar caracteres para imprimir directamente a[]y restar constantes numéricas en lugar de constantes de caracteres. :)
user1354557

1
También mejoré la compresión: 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)

Me sorprende ver que solo hay otra solución que no utiliza herramientas de calendario integradas. Aquí hay un enfoque matemático (altamente ofuscado), también 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));}

(Lo anterior se compila en GCC sin errores)

Solución alternativa: C (287-> 215 caracteres)

Disfruté bastante la solución de Williham Totland y su uso de la compresión. Arregle dos pequeños errores y modifiqué el código para acortar su longitud:

main(int x,char**v){char p[400],*a[]={"1221212213113","213122221122131","12213113","22213113","22221122","2131"},*b="abababafcbababafdbababafebababab";*p=0;for(;*b;b++)strcat(p,a[*b-97]);putchar(p[atoi(v[1])%400]);}


4

fiesta 47 36

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

Gracias @DigitalTrauma por guardar 10 caracteres usando seqel inicio predeterminado en 1.

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

(La versión anterior usaba echopresente un error debido a la línea vacía cuando <(echo $1-{1..12}-6$'\n'). Así que esta función funcionó bien hasta hoy es viernes.

Veamos:

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

Es dependiente de la configuración regional , si no funciona, es posible que deba

export LANG=C

o

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

En una función; +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

Bono: +78 -> 121

A partir de ahí, si mi función se convierte en:

f(){ o=();for t in $(seq -f$1-%g-6 12|date -f- +%a,%b);do [ "${t:0:1}" = "F" ]&&o+=(${t#*,});done;echo ${#o[@]} ${o[@]};}

o

f(){ o=();
     for t in $(seq -f$1-%g-6 1 12|date -f- +%a,%b);do
         [ "${t:0:1}" = "F" ]&&o+=(${t#*,})
       done
     echo ${#o[@]} ${o[@]}
}

for i in {2010..2017};do echo $i $(f $i) ;done
2010 1 Aug
2011 1 May
2012 3 Jan Apr Jul
2013 2 Sep Dec
2014 1 Jun
2015 3 Feb Mar Nov
2016 1 May
2017 2 Jan Oct

Esto parece depender de la localidad.
Peter Taylor

Sí, esto se basa en el valor predeterminado C. Pero hay un error ...
F. Hauri

Ahorre un carácter entrecomillando su cadena de formato printf y escapando del \ en su lugar:%s\\n
Digital Trauma

1
O use seqpara soltar 8 caracteres:date -f<(seq -f$1-%g-6 1 12)|grep -c ^F
Digital Trauma

1
En realidad, puedes eliminar 2 caracteres más. Si omite el número de secuencia de inicio, seq comenzará en 1 de forma predeterminada, que es lo que desea: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}

y por que es -1?
Lukasz 'Severiaan' Grela

1
¡Se ve bien! Usted puede ahorrar unos cuantos bytes, mediante la eliminación ,b,cde la declaración de la función (! Está bien que la fuga vars para el golf), como también bse presenta como un Numberpuedas +=el resultado de la prueba en lugar de la &&b++: b+=/^F/.test(new Date(a,c,6)). Sin embargo, puede guardar otro byte usando !new Date(a,c,1).getDay()(esto funciona porque getDaydevuelve 0 para el domingo, y si el 13 es un viernes, el primero será un domingo) en lugar del testque debería ahorrarle 7 bytes.
Dom Hastings

@DomHastings: gracias por tus consejos !!!
guy777

3

k

64 caracteres

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

Lecturas de stdin


Ok, ¿qué está pasando aquí? : P
Williham Totland

Lea el año, cree una lista de fechas del día 13 de cada mes, día de prueba de la semana = viernes, suma de la lista resultante de booleanos
skeevey

3

Lisp común (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))))))

Oh dios, nunca pude leer lisp ..
Cruncher

2

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

Gracias a Jeppe Stig Nielsen por linq y sugerencia de verificar el domingo 8.

Gracias a Danko Durbić por sugerir en >lugar de ==.


En lugar de c+=(int)new DateTime(y,i,13).DayOfWeek==5?1:0;usar el equivalente c+=new DateTime(y,i,8).DayOfWeek==0?1:0;. El truco es restar 5, porque entonces puedes deshacerte del yeso int, y también el número 8tiene un dígito menos que el número 13. ¡Domingo 8!
Jeppe Stig Nielsen

Con LINQ: int g(int y){return Enumerable.Range(1,12).Count(m=>new DateTime(y,m,8).DayOfWeek==0);}. Por supuesto, como lambda esto es y=>Enumerable.Range(1,12).Count(m=>new DateTime(y,m,8).DayOfWeek==0).
Jeppe Stig Nielsen

Puedes guardar un personaje comparando .DayOfWeek<1.
Danko Durbić

@ DankoDurbić Esto puede aplicarse a la c#respuesta pero no está seguro de cómo aplicarla linq.
Kami

Mi error; aparentemente no se puede comparar DayOfWeekcon ningún otro número entero que no sea 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;

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

Básicamente lo mismo que intentó Oleg y Damir Kasipovic hizo, solo que con un mejor golf:
cada mes que comienza con un domingo, tiene un viernes 13.
Así que recorro los meses y cuento los primeros días que son domingos.

Descompostura

for(;++$i<13;)          // loop $i from 1 to 12
    $c+=!                   // 4. if result is not truthy (weekday==0), increment $c
        date(w,             // 3. get weekday (0 stands for Sunday)
            strtotime(      // 2. convert to timestamp (midnight 1st day of the month)
                $argn.-$i   // 1. concatenate year, "-" and month
            )
        )
    ;
echo$c;                 // output

1

K, 42

{+/1={x-7*x div 7}"D"$"."/:'$+(x;1+!12;1)}

.

k){+/1={x-7*x div 7}"D"$"."/:'$+(x;1+!12;1)}'1776 2012 2013 2014
2 3 2 1

1

Bash ( 52 47 caracteres)

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

1

Rebol, 63

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

Ejemplo de uso en la consola Rebol:

>> y: 2012
== 2012

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

La solución alternativa que recoge todo el viernes 13 en un año determinado es:

>> collect[repeat m 12[d: do ajoin["13-"m"-"y]if d/weekday = 5[keep d]]]
== [13-Jan-2012 13-Apr-2012 13-Jul-2012]

1

Bash y Sed, 39

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

ncal imprime un calendario para el año dado con los días de la semana a la izquierda.

sedcon una /gbandera subscribe los 13 con nuevas líneas

grep -c cuenta las líneas que comienzan con "2" (20 siempre sigue a 13)

¡Gracias a @DigitalTrauma por encontrar un error en mi versión anterior y proponer una solución!


No me funciona del todo: las líneas de los viernes solo se imprimen una vez, incluso si contienen más de un 13.
Digital Trauma

1
Creo que lo mejor que puedo hacer con algo como esto es 38:ncal $1|sed /F/s/13/\\n/g|grep -c ^\ 2
Digital Trauma

1
@ DigitalTrauma Tienes razón. En algún momento este script estaba funcionando. Déjame arreglarlo.
No es que Charles

1
@DigitalTrauma parece que alguna versión mucho más larga estaba funcionando. gracias por la solucion!
No es que Charles

Interesante, la expresión sed no citada que propuse funciona con GNU sed (Linux) pero no con BSD sed (OSX). Supongo que puedes ganar 1 personaje a costa de la portabilidad si eliges la versión GNU.
Trauma digital

1

Scala, 76 68 caracteres

En 78 caracteres:

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

Nada fuera de lo común, excepto el uso de números mágicos para DAY_OF_WEEK = 7y FRIDAY = 6.

Versión de 68 caracteres:

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

Sí, Java cambió los valores de las constantes del día de la semana entre las API.


Es una pena que new java.util.GregorianCalendartenga que ser tan largo :(
Cruncher

1

Pitón 195/204

Solo funciona para años anteriores, porque monthdatescalendardevuelve un calendario para el año dado hasta ahora . Creo que queda mucho potencial de optimización :).

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)

Otra solución, funciona para cada fecha pero no es más pequeña:

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)

En su primer ejemplo, el rango debería ser (1,13), de lo contrario, se perdería el viernes 13 de diciembre, como en 2013.
leancz

1
Ni siquiera te molestaste en jugar golf. Elimina algunos de esos espacios.
mbomb007

1

Perl 6, 55 53

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

Vieja respuesta:

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


0

Python (v2) 120

import datetime as d,sys
s=0
for m in range(1, 13):
    if d.datetime(int(sys.argv[1]),m,6).weekday()==4: s=s+1
print s

0

Perl + lib POSIX 55

Con la idea de no buscar 13thsino primero, y como sundayes 0esto, ¡ahorre 3 caracteres! Gracias @ Iszi y Danko Durbić!

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

Podría calcular 2010 a 2017 (para muestra) de esta manera:

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

(Ok, no hay nueva línea , pero eso no se preguntó;)

Mensaje antiguo: 63

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

En acción:

for i in {2010..2017};do
    echo $i $(
        perl -MPOSIX -E '
            $==grep{5==strftime"%w",0,0,0,13,$_,$ARGV[0]-1900}(0..11);say$=
            ' $i );
  done
2010 1
2011 1
2012 3
2013 2
2014 1
2015 3
2016 1
2017 2

0

En Smalltalk (sabor Squeak / Pharo), implemente este método en Integer ( 86 caracteres)

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

A continuación, utilizar de esta manera: 2014countFriday13.

Por supuesto, podríamos usar un nombre más corto, pero entonces no sería Smalltalk


0

C ++ - Demasiados bytes :(

Intenté una solución que no utiliza ninguna biblioteca de fechas.

Encontré una solución bastante buena (si puedo decirlo yo mismo). Lamentablemente, no puedo hacerlo más corto que esto, lo que realmente me molesta porque parece que debería haber una mejor manera.

La solución depende de este algoritmo que tiene solo 44 bytes en sí mismo. Desafortunadamente necesito otros 100 bytes para envolverlo bien ...

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

La salida a través del código de retorno (en C ++, usar couto printfalgo así requiere otro #include, lo que haría explotar aún más la solución).

Conductor / programa de prueba:

# 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

Salida del programa controlador:

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

Cuento 88 para el algoritmo, no 44. ¿Cuál es el algoritmo y cuál es la deformación? ($m<3?$y--:$y-2)+3en lugar de d=13,, d+=m<3?y--:y-2,y d+4debería funcionar tan bien y ahorra mucho. +5en lugar de +3y -5debería funcionar también y ahorra 2 bytes. for(m=0;++m<13;)ahorra un byte. Mover m=0a la cabeza de la función guarda otro byte; y pasar ()%7||++fa la cabeza del bucle guarda otro. Bajó de 149 a 136 bytes.
Titus

0

Clojure, 207 187 bytes

-20 bytes al deshacerme del importespacio en blanco que perdí.

(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 del 1 de enero del año dado, se repite cada día. Si el día es el viernes 13, aumenta el recuento. Continúa en bucle hasta que alcance el próximo año.

(import '[java.time LocalDate DayOfWeek])

(defn count-friday-13ths [year]
  (loop [d (LocalDate/parse (str year "-01-01")) ; Starting date
         c 0] ; The count
    (if (= (.getYear d) year) ; If we haven't moved onto the next year...
      (recur (.plusDays d 1) ; Add a day...
             (if (and (= (.getDayOfMonth d) 13) ; And increment the count if it's Friday the 13th
                      (= (.getDayOfWeek d) DayOfWeek/FRIDAY))
               (inc c) c))
      c))) ; Return the count once we've started the next year.

0

PHP, no incorporado, 81 bytes

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

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

Descompostura

Los días laborables se repiten cada 400 años.
En los resultados de 1600 a 1999 (por ejemplo), hay un período de 28 períodos con solo tres brechas:

  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

Después de ajustar el año para estas brechas, podemos obtener el resultado con un simple hash:

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

No corto (95 bytes) pero bonito. Y podemos jugar al golf

  • 4 bytes usando una cadena ternaria para el desplazamiento,
  • 8 bytes al convertir el mapa hash de una cadena base4 a entero,
  • uno más usando la representación hexadecimal,
  • y uno fusionando las expresiones.

Un puerto de la respuesta C ++ de CompuChip puede reducirse a 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

Japt -x , 10 bytes

CÆ5¥ÐUXD e

Intentalo

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
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.