El ultimo lunes


27

El lunes 31 de octubre es Halloween. Y me hizo pensar: ¿me pregunto qué otros meses el último día del mes también será lunes?

Entrada

  • Un entero positivo en cualquier formato conveniente que represente un año 10000 > y > 0,.
  • La entrada se puede rellenar con ceros (por ejemplo, 0025para el año 25) si es necesario.

Salida

  • Una lista de los meses de ese año donde el último día del mes es un lunes.
  • Esto puede ser como nombres de mes (por ejemplo, January, March, October), o nombres cortos ( Jan, Mar, Oct), o números ( 1, 3, 10), como líneas separadas o una lista o delimitado, etc., siempre que no sea ambiguo para el lector.
  • El formato de salida debe ser consistente:
    • Para la entrada de todos los años (es decir, no puede generar nombres de mes para algunas entradas y números de mes para otras entradas)
    • Así como por salida constante (es decir, se pueden emitir 1por Januaryel mismo resultado que Julpara July)
    • Básicamente, elija un formato y manténgalo.

Reglas

  • Asuma el calendario gregoriano para entrada / salida, incluso hasta y = 1.
  • Los años bisiestos deben tenerse debidamente en cuenta (como recordatorio: cada año divisible por 4, excepto los años divisibles por 100, a menos que también sean divisibles por 400 - 1700, 1800, 1900, no todos fueron años bisiestos, pero 2000 sí).
  • Puede utilizar cualquier herramienta integrada de cálculo de fechas que desee.
  • Un programa completo o una función son aceptables. Si es una función, puede devolver el resultado en lugar de imprimirlo.
  • Las lagunas estándar están prohibidas.
  • Este es el por lo que se aplican todas las reglas habituales de golf, y gana el código más corto (en bytes).

Ejemplos

   1 --> Apr, Dec
 297 --> May
1776 --> Sep
2000 --> Jan, Jul
2016 --> Feb, Oct
3385 --> Jan, Feb, Oct

Tabla de clasificación



1
Relacionados pero no duplicados o?
ElPedro

@ElPedro Relacionados pero no duplicados. El primero no permite ninguna integración y solicita un combo de fecha / día fijo (viernes 13), mientras que el segundo solicita el último domingo de cada mes del año, limitado entre 1900 y 3015.
AdmBorkBork

Lo siento @TimmD. Mi malentendido de tu comentario.
ElPedro

1
@ElPedro ¡No hay problema! Prefiero tener una pregunta y que quede clara, que no tener una pregunta y tener algo poco claro.
AdmBorkBork

Respuestas:


2

Dyalog APL con dfns 's cal , Versión 15.0: 22; Versión 16.0: 19 bytes

La función cal viene con una instalación predeterminada, solo ingrese )copy dfns.

Versión 15.0: ∊⎕{⍵/⍨2=≢⍎⊢⌿cal⍺⍵}¨⍳12

alistarse (aplanar)

⎕{... entrada numérica como argumento izquierdo para la siguiente función anónima, tomando cada uno de los valores del lado derecho como argumento correcto a su vez

⍵/⍨ el argumento if (da una lista vacía si no)

2= dos (a saber, domingo y lunes) es igual a

la cuenta de

los números en

⊢⌿ la fila más baja de

cal el calendario para

⍺⍵ año argumento izquierdo, mes argumento derecho, siendo este último

⍳12 1 a 12

Versión 16.0: ⍸2=⎕{≢⍎⊢⌿cal⍺⍵}¨⍳12

los índices donde

2= dos iguales (a saber, domingo y lunes)

⎕{... entrada numérica como argumento izquierdo para la siguiente función anónima, tomando cada uno de los valores del lado derecho como argumento correcto a su vez

la cuenta de

los números en

⊢⌿ la fila más baja de

cal el calendario para

⍺⍵ año argumento izquierdo, mes argumento derecho, siendo este último

⍳12 1 a 12


19

JavaScript (Firefox 30+), 112 109 103 95 bytes

Mira ma, no hay complementos!

y=>[for(m of(i=0,y%4|y%400*!(y%100)&&6)+"63153042641")if((i++,y+(y>>2)-(y/100|0)*3/4|0)%7==m)i]

Aquí hay una versión ES6 de 107 bytes:

y=>[...(y%4|y%400*!(y%100)&&6)+"63153042641"].map((m,i)=>(y+(y>>2)-(y/100|0)*3/4|0)%7-m?0:i+1).filter(x=>x)

Y aquí está mi intento anterior, 123 113 bytes de ES6:

y=>[(l=y%4|y%400*!(y%100))?[7]:[1,7],[4,12],[9],[3,6],[8,11],[5],l?[1,2,10]:[2,10]][(y+(y>>2)-(y/100|0)*3/4|0)%7]

Explicación

El día de la semana de un año en particular se calcula así:

y+(y>>2)-(y/100|0)*3/4|0)%7

En otras palabras:

  • Tomar y.
  • Agregue el número de 4 años antes y( y>>2).
  • Resta el número de centésimos años antes y( y/100|0).
  • Agregue nuevamente el número de 400 años antes y; esto es 1/4 de y/100|0, por lo que usamos *3/4|0.

Luego modulamos el resultado por 7. Si dejamos 0el domingo medio, 1el lunes medio, etc., el resultado corresponde al día de la semana del 31 de diciembre de ese año. Por lo tanto, para diciembre, queremos verificar si el resultado es 1. Esto nos da el último carácter de la cadena.

El último día de noviembre es 31 días antes del último día de diciembre. Esto significa que para que el último día de noviembre sea lunes, el 31 de diciembre debe ser a (1 + 31) % 7 = 4= jueves.

Este procedimiento se repite hasta que regresemos a marzo (a 3). Ya sea que haya o no un día bisiesto, el último día de febrero es 31 días antes del último día de marzo, por lo que también podemos calcularlo (es (3 + 31) % 7 = 6). La parte difícil es encontrar el valor correcto para enero:

  • Si es un año bisiesto, el último día de enero es 29 días antes del último día de febrero, lo que resulta en (6 + 29) % 7 = 0.
  • De lo contrario, es 28 días antes del último día de febrero, lo que resulta en (6 + 28) % 7 = 6.

Podemos calcular si es o no un año bisiesto con el siguiente fragmento:

!(y%400)|y%100*!(y%4)

Esto da 0si yno es un año bisiesto y un número entero positivo de lo contrario. Esto nos lleva a

!(y%400)|y%100*!(y%4)?0:6

para calcular el día de enero. Sin embargo, podemos hacerlo mejor al revertir las condiciones:

y%4|y%400*!(y%100)?6:0

Como el resultado falso es siempre 0 de todos modos, podemos reducirlo a

y%4|y%400*!(y%100)&&6

salvando un byte precioso más.

Al poner todo junto, recorremos cada char en la cadena, verificando si cada uno es igual al día de la semana del 31 de diciembre. Mantenemos los índices de los que coinciden, devolviendo esta matriz al final. Y así es como se hacen los cálculos del año bisiesto sin elementos integrados.


Owww ... Mi cerebro, ¿explicaste los años bisiestos en todo eso?
Urna mágica del pulpo

2
@carusocomputing Para eso !(y%4)*y%100|!(y%400)está. cada año divisible por 4, excepto no años divisibles por 100, a menos que también sea divisible por 400
mbomb007

Esperemos que y+(y>>2)+(z=y/25>>2)+(z>>2)aún te ahorre un byte.
Neil

@Neil Gracias, pero encontré una mejor manera :-)
ETHproductions

Agradable; Ahorré 6 bytes en mi puerto Batch usando (y*5/4-(y/100)*3/4).
Neil

11

JavaScript (Firefox 30-57), 67 65 64 63 61 bytes

y=>[for(_ of(m='')+1e11)if(new Date(y+400,++m).getDay()==2)m]

Guardado 2 4 6 bytes gracias a @ETHproductions. Se guardó otro byte al mostrar los meses en orden inverso.


Creo que puede ahorrar 2 bytes volando sin .keys():y=>[for(_ of(m=0,Array(12)))if(new Date(y+400,++m).getDay()==2)m]
ETHproductions

@ETHproductions ¡Puedo guardar un byte adicional invirtiendo el orden!
Neil

El orden inverso está bien. Formatear la salida no es la parte interesante de este desafío.
AdmBorkBork

¿Cuál es nuestra política sobre las comprensiones de matriz ahora que se han eliminado de la especificación?
MayorMonty

Puede guardar otros 2 bytes omitiendo por Array(12)completo: y=>[for(_ of(m=0,1e11+""))if(new Date(y+400,++m).getDay()==2)m]
ETHproductions

8

MySQL, 183 134 129 106 bytes

SET @y=2016;SELECT help_topic_id AS m FROM mysql.help_topic HAVING m BETWEEN 1 AND 12 AND 2=DAYOFWEEK(LAST_DAY(CONCAT(@y,-m,-1)))

Reemplazar 2016con el año deseado. Correr.

Rev. 2: usó la help_topicstabla en la instalación predeterminada en lugar de crear una tabla temporal.

Rev.3: adoptó el truco de aross- y noté que también puedo omitir las comillas "-1".
Sin embargo, -1se requiere en MySQL: necesito una fecha completa.

Rev.4: La restricción m BETWEEN 1 AND 12podría hacerse como m>0 AND m<13(-6), pero no es necesaria en absoluto: los valores no válidos serán ignorados; Las advertencias se contarán pero no se enumerarán.


¿Realmente necesitas la tabla shema mysql? mariadb.com/kb/en/mariadb/mysqlhelp_topic-table
Jörg Hülsermann

@ JörgHülsermann No entiendo tu punto.
Titus

Debe FROM help_topicsin mysql.trabajo? No lo he intentado
Jörg Hülsermann

@ JörgHülsermann solo si antepone USE mysql;La base de datos correcta debe seleccionarse de alguna manera.
Titus

5

Perl, 64 bytes

Incluye +1 para -n

Dar entrada en STDIN:

perl -M5.010 mon.pl <<< 2016

mon.pl:

#!/usr/bin/perl -n
map$b.=$/.gmtime$_.e4,-7e6..3e7;say$b=~/on (\S+ )\S.* $_.* 1 /g

5

Lotes, 160 152 bytes

@set/ay=%1,m=0,j=6*!(!(y%%4)*(y%%100)+(y%%400)),y=(y*5/4-y/100*3/4)%%7
@for %%d in (%j% 6 3 1 5 3 0 4 2 6 4 1)do @set/am+=1&if %%d==%y% call echo %%m%%

Puerto de la respuesta de @ ETHproduction. Con abreviaturas de mes para 197 189 bytes:

@set/ay=%1,j=6*!(!(y%%4)*(y%%100)+(y%%400)),y=(y*5/4-y/100*3/4)%%7
@for %%m in (Jan.%j% Feb.6 Mar.3 Apr.1 May.5 Jun.3 Jul.0 Aug.4 Sep.2 Oct.6 Nov.4 Dec.1)do @if %%~xm==.%y% call echo %%~nm

4

J, 48 34 33 bytes

[:I.(2=7|_2#@".@,@{.])&>@calendar

Guardado 15 bytes con ayuda de @ Adám .

Utiliza el calendario integrado para generar una serie de cadenas que representan los meses, luego analiza cada cadena para determinar si el último lunes es el último día del mes. Produce cada mes como el número de mes de cada uno. Es decir, Jan = 0, Feb = 1, ..., Dec = 11.

La salida de calendares

   _3 ]\ calendar 2016
┌─────────────────────┬─────────────────────┬─────────────────────┐
│         Jan         │         Feb         │         Mar         │
│ Su Mo Tu We Th Fr Sa│ Su Mo Tu We Th Fr Sa│ Su Mo Tu We Th Fr Sa│
│                 1  2│     1  2  3  4  5  6│        1  2  3  4  5│
│  3  4  5  6  7  8  9│  7  8  9 10 11 12 13│  6  7  8  9 10 11 12│
│ 10 11 12 13 14 15 16│ 14 15 16 17 18 19 20│ 13 14 15 16 17 18 19│
│ 17 18 19 20 21 22 23│ 21 22 23 24 25 26 27│ 20 21 22 23 24 25 26│
│ 24 25 26 27 28 29 30│ 28 29               │ 27 28 29 30 31      │
│ 31                  │                     │                     │
├─────────────────────┼─────────────────────┼─────────────────────┤
│         Apr         │         May         │         Jun         │
│ Su Mo Tu We Th Fr Sa│ Su Mo Tu We Th Fr Sa│ Su Mo Tu We Th Fr Sa│
│                 1  2│  1  2  3  4  5  6  7│           1  2  3  4│
│  3  4  5  6  7  8  9│  8  9 10 11 12 13 14│  5  6  7  8  9 10 11│
│ 10 11 12 13 14 15 16│ 15 16 17 18 19 20 21│ 12 13 14 15 16 17 18│
│ 17 18 19 20 21 22 23│ 22 23 24 25 26 27 28│ 19 20 21 22 23 24 25│
│ 24 25 26 27 28 29 30│ 29 30 31            │ 26 27 28 29 30      │
│                     │                     │                     │
├─────────────────────┼─────────────────────┼─────────────────────┤
│         Jul         │         Aug         │         Sep         │
│ Su Mo Tu We Th Fr Sa│ Su Mo Tu We Th Fr Sa│ Su Mo Tu We Th Fr Sa│
│                 1  2│     1  2  3  4  5  6│              1  2  3│
│  3  4  5  6  7  8  9│  7  8  9 10 11 12 13│  4  5  6  7  8  9 10│
│ 10 11 12 13 14 15 16│ 14 15 16 17 18 19 20│ 11 12 13 14 15 16 17│
│ 17 18 19 20 21 22 23│ 21 22 23 24 25 26 27│ 18 19 20 21 22 23 24│
│ 24 25 26 27 28 29 30│ 28 29 30 31         │ 25 26 27 28 29 30   │
│ 31                  │                     │                     │
├─────────────────────┼─────────────────────┼─────────────────────┤
│         Oct         │         Nov         │         Dec         │
│ Su Mo Tu We Th Fr Sa│ Su Mo Tu We Th Fr Sa│ Su Mo Tu We Th Fr Sa│
│                    1│        1  2  3  4  5│              1  2  3│
│  2  3  4  5  6  7  8│  6  7  8  9 10 11 12│  4  5  6  7  8  9 10│
│  9 10 11 12 13 14 15│ 13 14 15 16 17 18 19│ 11 12 13 14 15 16 17│
│ 16 17 18 19 20 21 22│ 20 21 22 23 24 25 26│ 18 19 20 21 22 23 24│
│ 23 24 25 26 27 28 29│ 27 28 29 30         │ 25 26 27 28 29 30 31│
│ 30 31               │                     │                     │
└─────────────────────┴─────────────────────┴─────────────────────┘

Uso

   f =: [:I.(2=7|_2#@".@,@{.])&>@calendar
   f 1
3 11
   f 297
4
   f 1776
8
   f 2000
0 6
   f 2016
1 9
   f 3385
0 1 9

Explicación

[:I.(2=7|_2#@".@,@{.])&>@calendar  Input: year Y
                         calendar  Get 12 boxes each containing a month
    (                )&>@          Operate on each box
                    ]                Identity, get the box
         _2       {.                 Take the last two strings
                ,@                   Flatten it
             ".@                     Parse it into an array of integers
           #@                        Get the length
       7|                            Take it modulo 7
     2=                              Test if it equals 2 - it will either
                                     have two days or 9 days in the last
                                     two lines if the end is on a Monday
[:I.                               Return the indices containing a true value

espera, ¿el calendario realmente produce arte ascii?
Destructible Lemon

@DestructibleWatermelon Para ser exactos, el formato de salida de calendares un conjunto de 12 cuadros donde cada cuadro contiene un conjunto de caracteres 2D
millas

Ni siquiera sé cómo hacer "cada" en J, pero esto ya es mucho más corto: I.7=;#&.>".&.>,&.>_2{.&.>calendar 2016si combina todos los "sub-abiertos", debería poder hacerlo bastante corto.
Adám

@ Adám Gracias, que utiliza un método mejor, pero no es un verbo en J. Creo que va siendo ayuda embargo
milla

Mi intención era solo inspirar. Sé que no es un verbo.
Adám

4

Mathematica, 62 57 bytes

DayName@DayRange[{#},{#+1},"EndOfMonth"]~Position~Monday&

Función anónima. Toma un número como entrada y devuelve una lista de listas de elementos de un solo elemento como salida. Sinceramente, ya no estoy seguro de cómo funciona.


4

Perl + cal, 46 bytes

say`cal $_ $ARGV[0]`=~/\n.{5}\n/&&$_ for 1..12

Ejemplo:

$ perl -E 'say`cal $_ $ARGV[0]`=~/\n.{5}\n/&&$_ for 1..12' 2016

2







10


$

1
Estrictamente hablando, esto es perl + cal, no solo perl :-p. Por ejemplo, mi máquina Windows tiene perl, pero esto no funcionará allí.
philomory

Punto justo, actualizado esto y mi intento de bash.
Steve

4

Java 7186 182 172 bytes

Gracias a Kevin por guardar 4 bytes
Gracias a @cliffroot por guardar 10 bytes

int[]f(int n){int c=n-1,x=c*365+c/4+c/400-c/100,k=0,b[]={3,(n%4<1&n%100>0)|n%400<1?1:0,3,2,3,2,3,3,2,3,2,3},a[]=new int[12];for(int i:b)a[k++]=(x+=i+28)%7==1?1:0;return a;}

sin golf

int[] f(int n) {
 int c=n-1,x=c*365+(c/4)+(c/400)-(c/100),k=0,
   b[] = {3,(n % 4 < 1 & n % 100 > 0) | n % 400 < 1 ? 1 : 0
                                     ,3,2,3,2,3,3,2,3,2,3},a = new int[ 12 ];

 if ( (n % 4 < 1 & n % 100 > 1) | n % 400 < 1 )
     b[ 1 ] = -1;
 for (int i : b)
    a[ k++ ] = (x += i + 28) % 7 == 1 ? 1 : 0;

return a;
     }

Esta versión es proporcionada por @cliffroot ( 168 bytes )

 static int[] f(int n) {
 int b = 13561787 | ( (n%4 < 1 & n%100 > 0) | n%400 < 1 ? 1 << 20 : 0 ),
           x = --n*365 + n/4 + n/400 - n/100,a[]=new int[12],k=0;
    while (k < 12)
    a[k++] = (x += (b >> 24 - k*2&3 ) + 28) % 7 == 1 ? 1 : 0;
  return a;   }
    }

muestra de salida

1 1 0 0 0 0 0 0 0 1 0 0(for input 3385)

1
Después de escribir mi respuesta sabía calcular todo usted mismo sería más corta .. :) Por cierto, se puede jugar golf n%4==0a n%4<1; n%400==0a n%400<1y int c=...;int[]b=...,a=...a int c=...,b[]=...,a[]=....
Kevin Cruijssen

1
by ase puede definir en la intparte como esta:int ... ,b[]=...,a[]=...
Olivier Grégoire

1
int[]f(int n){int x=--n*365+n/4+n/400-n++/100,k=0,b[]={1,(n%4<1&n%100>0)|n%400<1?-1:-2,1,0,1,0,1,1,0,1,0,1},a[]=new int[12];for(int i:b)a[k++]=(x+=i+30)%7==1?1:0;return a;}pocos bytes guardados
cliffroot

1
También puede cambiar ba b[]={3,(n%4<1&n%100>0)|n%400<1?1:0,3,2,3,2,3,3,2,3,2,3}y i+30a i+28por 2 bytes más
cliffroot

1
y otros 3 bytesint[]f(int n){int b=13561787|((n%4<1&n%100>0)|n%400<1?1<<20:0),x=--n*365+n/4+n/400-n/100,a[]=new int[12],k=0;while(k<12)a[k++]=(x+=(b>>24-k*2&3)+28)%7==1?1:0;return a;}
cliffroot

3

Python 2, 100 bytes

Ugh Matemáticas con fechas no es tan simple como me gustaría.

lambda y:[m+1for m in range(12)if(date(y,12,31)if m>10else(date(y,m+2,1)-timedelta(1))).weekday()<1]

Pruébalo en línea

Mismo largo:

lambda y:[m-1for m in range(2,14)if(date(y,12,31)if m>12else(date(y,m,1)-timedelta(1))).weekday()<1]

Ni siquiera iba a probar Python con este. Buen esfuerzo
ElPedro

3

MATL , 21 bytes

12:"G@QhO6(YO9XO77=?@

Los meses se muestran como números.

Pruébalo en línea! O verificar todos los casos de prueba .

Explicación

Esto utiliza funciones integradas de conversión de fecha. Para el año dado, prueba qué último día del mes es el lunes.

En lugar de especificar explícitamente el último día del mes k(que puede ser 28, 29, 30 o 31), especificamos el 0día del mes k+1, que es equivalente y no depende del mes o año.

12:      % Push [1 2 ... 12] (months)
"        % For each month k
  G      %   Push input
  @Q     %   Push k+1
  h      %   Concatenate
  O6(    %   Postpend four zeros. For example, for input 2016 and month k=1 
         %   (first iteration) this gives [2016 2 0 0 0 0] (year, month, day,
         %   hour, min, sec). The 0-th day of month k+1 is the same as the
         %   last day of month k.
  YO     %   Convert the above 6-element date vector to date number
  9XO    %   Convert date number to date string with output format 9, which 
         %   is weekday as a capital letter
  77=    %   Is it an 'M'?
  ?      %   If so
    @    %     Push current month (will be implicitly displayed)

3

Bash + utilidades GNU, 56 bytes

seq -f1month-1day$1-%g-1 12|date -f- +%B%u|sed -n s/1//p

Parece requerir la dateversión 8.25. La versión 8.23 ​​en Ideone no es suficiente.


3

Excel, 537 bytes

Porque, ya sabes, ¡Excel!

Toma año de entrada en A1. Devuelve la lista hexadecimal de meses; 1 = enero, C = diciembre. Como cada mes es un solo dígito, no se necesita separador.

=IF(2=WEEKDAY(EOMONTH(DATE(A1,1,1),0)),1,"")&IF(2=WEEKDAY(EOMONTH(DATE(A1,2,1),0)),2,"")&IF(2=WEEKDAY(EOMONTH(DATE(A1,3,1),0)),3,"")&IF(2=WEEKDAY(EOMONTH(DATE(A1,4,1),0)),4,"")&IF(2=WEEKDAY(EOMONTH(DATE(A1,5,1),0)),5,"")&IF(2=WEEKDAY(EOMONTH(DATE(A1,6,1),0)),6,"")&IF(2=WEEKDAY(EOMONTH(DATE(A1,7,1),0)),7,"")&IF(2=WEEKDAY(EOMONTH(DATE(A1,8,1),0)),8,"")&IF(2=WEEKDAY(EOMONTH(DATE(A1,9,1),0)),9,"")&IF(2=WEEKDAY(EOMONTH(DATE(A1,10,1),0)),"A","")&IF(2=WEEKDAY(EOMONTH(DATE(A1,11,1),0)),"B","")&IF(2=WEEKDAY(EOMONTH(DATE(A1,12,1),0)),"C","")

Ejemplo: A1 contiene 2016. B1 contiene la fórmula anterior y se muestra como 2A, lo que significa febrero y octubre.


3

PHP, 109 180 159 bytes

for($z=$argv[1];$m++<12;)if(date(N,strtotime(sprintf("%04d-$m-",$z).cal_days_in_month(0,$m,$z)))<2)echo"$m,";
  • Produce el año proporcionado, no todos (... siempre lea la pregunta)
  • Avisos ignorados (gracias Titus)
  • Cambie whilea forcomo ahora es un solo año (de nuevo, gracias Titus)

Viejo 2

$z=0;while($z++<9999){$o=[];$m=0;while($m++<12)if(date("N",strtotime(sprintf("%04d-$m-","$z").cal_days_in_month(0,$m,$z)))<2)$o[]=$m;echo count($o)>0?"$z:".implode(",",$o)."
":"";}

Admite todos los años desde punto hasta 10000, también eliminó una advertencia de var indefinida que no conocía en una PC. Sí, es más largo que la versión anterior, pero es más robusto.

Viejo 1

while($z++<9999){$o=[];$m=0;while($m++<12)if(date("N",strtotime("$z-$m-".cal_days_in_month(0,$m,$z)))<2)$o[]=$m;echo count($o)>0?"$z:".implode(",",$o)."
":"";}

Si se ejecuta en Windows o en un sistema de 32 bits, habrá el temido error 2038, pero en un sistema Linux de 64 bits está bien.

Intenté usar lo date("t"...que está destinado a representar la última fecha del mes dado, pero los resultados no coincidieron con los mencionados anteriormente en este hilo.


2
-2: "$ z" no necesita comillas -7: ignora los avisos (no se imprimen con la configuración predeterminada: no inicie $z, no hay comillas N) -1: en forlugar de while -43 : tome la entrada como se solicitó en lugar de recorrer los años -3: en joinlugar de implode-16: salida directa: for($z=$argv[1];$m++<12;)if(date(N,strtotime(sprintf("%04d-$m-",$z).cal_days_in_month(0,$m,$z)))<2)echo"$m,";+9 si insiste en no tener una coma final:echo$o=$o?",$m":$m;
Titus

Ahh leyó mal la pregunta! Pensé que era para todos los años ... oops: B Gracias por las otras sugerencias también, las
recibiré

3

PHP, 92 bytes

for($d=new DateTime("$argv[1]-1-1");$i++<12;)$d->modify("1month")->format(w)!=2?:print"$i,";

marque 12 veces 1 mes después del primer día de un año. Si es así, es el día anterior al último día del mes que es lunes.


Puede usar echo en lugar de imprimir y guardar 1
Octopus

1
@Octopus no está dentro del operador ternario
Jörg Hülsermann

3

C, 214 bytes

main(int a,char *b[]){for(int x,y,d,m=12;m;m--){y=atoi(b[1]);x=m-1;d=x==1?(y%4==0?(y%100==0?(y%400==0?29:28):29):28):(x==3||x==5||x==10?30:31);if((d+=m<3?y--:y-2,23*m/9+d+4+y/4-y/100+y/400)%7==1)printf("%d\n",m);}}

Compilar

gcc -std=c99 -o foo foo.c

Sin golf

Con créditos a los gurús relevantes.

Michael Keith y Tom Craver para el Programa C encontrarán la fecha dada para el día de la semana .

Collin Biedenkapp para preguntas y respuestas: ¿Cómo puedo averiguar cuál es el último día del mes?

/* credit to Collin Biedenkapp */
short _get_max_day(short x, int z) {
    if(x == 0 || x == 2 || x == 4 || x == 6 || x == 7 || x == 9 || x == 11)
        return 31;
    else if(x == 3 || x == 5 || x == 8 || x == 10)
        return 30;
    else {
        if(z % 4 == 0) {
            if(z % 100 == 0) {
                if(z % 400 == 0)
                    return 29;
                return 28;
            }
            return 29;
        }
        return 28;
    }
}

main(int argc,char *argv[]) {
 for(int y,d,m=12;m;m--) {
  y=atoi(argv[1]);
  d=_get_max_day(m-1,y);
  /* credit to Michael Keith and Tom Craver */
  if ((d+=m<3?y--:y-2,23*m/9+d+4+y/4-y/100+y/400)%7 == 1)
    printf("%d\n",m);
 }
}

1
¿Qué pasa si voltea su ifotra dirección, para tener su elseregreso 31, y por lo tanto puede eliminar la gran ==cadena?
AdmBorkBork

1
sería mejor si (x == 1) {parte z} más si (x == 3 || x == 5 || x == 8 || x == 10) devuelve 30 más devuelve 31
RosLuP

1
¿qué pasa con: return x == 1? (z% 4 == 0? (z% 100 == 0? (z% 400 == 0? 29: 28): 29): 28) :( x == 3 | | x == 5 || x == 8 || x == 10? 30: 31)
RosLuP

TimmyD + RosLuP: gracias por los puntos return (), 100 bytes ahora guardados.
Steve

1
es posible continuar reduciendo por fin hasta esto: u (y, m) {return m-1? 30 + ((2773 >> m) & 1): 28+ (y% 4 == 0 && y% 100 || y% 400 == 0);} donde y es el año ym el mes
RosLuP

3

C, 119 bytes

t=1248700335,m;main(y){for(scanf("%d",&y),t+=y&3||y%25<1&&y&15;m++,(6+y+y/4-y/100+y/400+t)%7||printf("%d,",m),t;t/=7);}

Utiliza una tabla que contiene el desplazamiento de los días de la semana del último día de cada mes para un año bisiesto, codificado en una palabra firmada de 32 bits utilizando la base 7. Si no es un año bisiesto, sumamos 1 al desplazamiento de enero (como puede ver, y&3||y%25<1&&y&15se usa para verificar años sin días bisiestos). Luego, simplemente recorremos cada mes y verificamos si su último día es un lunes. Bastante simple en realidad, no hay trucos ni trucos feos. Aquí está un poco ignorado:

t=1248700335,m;
main(y){
  for(
    scanf("%d",&y),t+=y&3||y%25<1&&y&15;
    m++,(6+y+y/4-y/100+y/400+t)%7||printf("%d,",m),t;
    t/=7
  );
}

Podría volver a visitar esto para reescribirlo como una función para guardar algunos caracteres. El printftambién ocupa demasiado espacio ...


Printf ("% d", m) imprimiría algo como 1, o 2, 3, por lo que siempre hay uno ',' más ... Prefiero usar solo espacios
RosLuP

De hecho, también prefiero espacios en la salida en realidad, pero generalmente escribo mis soluciones C de golf para que no necesiten ningún espacio en blanco, por lo que puedo eliminar todos los espacios en blanco de mi versión de medio golf cuando quiero verificar mi recuento de caracteres .
Fors

3

PHP, 96 95 76 71 69 64 61 bytes

Nota: los números de año deben rellenarse con 4 caracteres, como 0070.

for(;13+$i-=1;)date(N,mktime(0,0,0,1-$i,0,$argn))-1||print$i;

Corre así:

echo 3385 | php -nR 'for(;13+$i-=1;)date(N,mktime(0,0,0,1-$i,0,$argn))-1||print$i;';echo
> -1-2-10

Explicación

Itera de -1 a -12. Crear fecha usando mktime, día 0(el último día del mes anterior) y mes 2..13. Formatee la fecha como número de día y, si el resultado es 1, imprima el número actual. El signo negativo -se usa como delimitador.

¡El bicho del milenio ataca de nuevo!

Tenga en cuenta que con esta versión, el rango 0..100se interpreta como 1970..2069. Esto no es un problema para el rango 0..69, ya que las semanas tienen un patrón que se repite cada 400 años (146097 días, exactamente 20871 semanas), pero para el rango 70..99, 1900 se agrega al número del año, que no es un múltiplo de 400. Para corregir ese problema SOLO para números de 30 años en un rango de 10k, la forma más simple es agregar 400 al número del año para evitar la interpretación de 2 dígitos ( +4 bytes ):

for(;13+$i-=1;)date(N,mktime(0,0,0,1-$i,0,$argn+400))-1||print$i;

Ajustes

  • Se guardó un byte usando !~-$ipara comparar $icon 1( -1binario negado es 0, lógicamente negado es true; cualquier otro número es false), por lo que no se necesitan paréntesis
  • Se guardaron 19 bytes usando last day ofYYYY-mnotación para crear la fecha
  • Guardado 5 bytes usando datey en strtotimelugar dedate_create
  • Se guardaron 2 bytes contando desde números negativos, utilizando el signo negativo como delimitador de salida (no existen números de mes negativos) y también como delimitación en la YYYY-mparte de la fecha
  • Guardado 5 bytes usando en mktimelugar de strtotime. Volvió a usar el día 0( mktimetambién es compatible con el mes 13, entonces 0-13== 31-12)
  • Guardado 3 bytes al usar -Rpara poner a $argndisposición

mktimeelimina la necesidad de rellenar el año, ¿no?
Titus

@Titus, agudo. Bueno, acabo de darme cuenta de que mktimees contra-intuitivo , porque los argumentos se toman como INTs. Eso significa que no puede rellenar el año ... así que todo en el rango 0..100se interpreta como 1970..2070. Eso no es problema para el rango 0..70porque 400 años tienen un número exacto de semanas (por lo que los calendarios repiten el patrón cada 400 años), pero 70..99agrega 1900 (¡no un múltiplo de 400!). Por lo tanto, nuevo ver. tiene un error
aross

La única solución que veo para eso en este momento es $argv[1]+400... a menos que los días de semana de Julian y Gregorian difieran.
Titus

@Titus, sí. Las reglas dicen que use cal gregoriana
aross

3

Excel, 428 97 96 bytes

Entrada en A1. Salida de valores hexadecimales no separados (enero = 0, diciembre = B)

=IF(2=WEEKDAY(DATE(A1+2000,1,31)),0,"")&CHOOSE(WEEKDAY(DATE(A1+2000,3,0)),4,19,6,"3B",8,25,"7A")

Se agregaron 10 bytes ("+2000") para permitir el manejo de fechas anteriores a 1990.

Guardado 11 bytes gracias a @ Engineer Toast .


Primer intento (428 bytes), tomando prestado mucho de la solución de @ Adám .

=IF(2=WEEKDAY(DATE(A1,1,31)),1,"")&IF(2=WEEKDAY(EOMONTH(DATE(A1,2,1),0)),2,"")&IF(2=WEEKDAY(DATE(A1,3,31)),3,"")&IF(2=WEEKDAY(DATE(A1,4,30)),4,"")&IF(2=WEEKDAY(DATE(A1,5,31)),5,"")&IF(2=WEEKDAY(DATE(A1,6,30)),6,"")&IF(2=WEEKDAY(DATE(A1,7,31)),7,"")&IF(2=WEEKDAY(DATE(A1,8,31)),8,"")&IF(2=WEEKDAY(DATE(A1,9,30)),9,"")&IF(2=WEEKDAY(DATE(A1,10,31)),"A","")&IF(2=WEEKDAY(DATE(A1,11,30)),"B","")&IF(2=WEEKDAY(DATE(A1,12,31)),"C","")

¿Cómo funciona esto en años anteriores a 1900? El caso de prueba 297 -> Mayregresa 6con esta fórmula. ¿No deberían ser 4? 1776da en 7Alugar de solo 8para septiembre.
Engineer Toast

Sin embargo, si lo hace funcionar, probablemente pueda usarlo en Date(A1,3,0)lugar deEOMONTH(DATE(A1,2,1),0)
Engineer Toast

2

Bash + cal, 58 bytes

$ cat t.sh
for A in {1..12};do cal $A $1|grep -qx .....&&echo $A;done
$ bash t.sh 2016
2
10
$

+1: funciona para BSD cal(por ejemplo, OSX), pero esté atento a los espacios finales en GNU cal.
Trauma digital

2

Python 2, 94 bytes

from datetime import*
lambda y:[m for m in range(1,13)if date(y+(m>11),m%12+1,1).weekday()==1]

repl.it

Una función sin nombre, toma un año entero, genera una lista de los números de mes [1-12].

También intenté superar el recuento de bytes con aritmética sin éxito (110 bytes). :

lambda y:map(lambda x,v:(23*((x+2)%13or 1)/9+y-2*(0<x<11)+(x>10)+v/4-v/100+v/400)%7==4,range(12),[y-1]+[y]*11)

Una función sin nombre que devuelve una lista de valores booleanos que representan si los meses [enero-diciembre] terminan en un lunes


2

Java 7, 200 249 bytes

import java.util.*;String c(int y){String r="";GregorianCalendar c=new GregorianCalendar();c.setGregorianChange(new Date(1L<<63));c.set(1,y);c.set(2,0);for(int i=0;i++<12;c.add(2,1)){c.set(5,c.getActualMaximum(5));if(c.get(7)==2)r+=i+" ";}return r;}

En Java, GregorianCalendares una mezcla entre un calendario gregoriano y juliano. Debido a esto, el año 1dio resultados incorrectos. Cambiar Calendar c=Calendar.getInstance();a GregorianCalendar c=new GregorianCalendar();c.setGregorianChange(new Date(1L<<63));arregla esto forzando el uso del calendario gregoriano solamente. Gracias a @JonSkeet en stackoverflow.com por explicarme esto.

Ungolfed y código de prueba:

Pruébalo aquí

import java.util.*;
class M{
  static String c(int year){
    String r = "";
    GregorianCalendar calendar = new GregorianCalendar();
    calendar.setGregorianChange(new Date(Long.MIN_VALUE));
    calendar.set(Calendar.YEAR, year);
    calendar.set(Calendar.MONTH, 0);
    for(int i = 0; i++ < 12; calendar.add(Calendar.MONTH, 1)){
      calendar.set(Calendar.DATE, calendar.getActualMaximum(Calendar.DATE));
      if(calendar.get(Calendar.DAY_OF_WEEK) == 2){
        r += i+" ";
      }
    }
    return r;
  }

  public static void main(String[] a){
    System.out.println(c(1));
    System.out.println(c(297));
    System.out.println(c(1776));
    System.out.println(c(2000));
    System.out.println(c(2016));
    System.out.println(c(3385));
  }
}

Salida:

4 12
5 
9 
1 7 
2 10 
1 2 10 

2

C # 6 C #, 171 167 135 bytes

using System;
void d(int n){for(int i=0;++i<13;)if((int)new DateTime(n,i,DateTime.DaysInMonth(n,i)).DayOfWeek==1)Console.Write(i+" ");}

-32 bytes gracias a Shebang

Imprimir meses como números; con espacio delimitado; con espacio posterior. Ahora esta respuesta también funciona para versiones anteriores de C #.


Antiguo, 167 bytes

using System;using System.Linq;
c(int n)=>string.Join(",",Enumerable.Range(1,12).Where(i=>new DateTime(n,i,DateTime.DaysInMonth(n,i)).DayOfWeek==(DayOfWeek)1));

-4 bytes gracias a TimmyD

Los meses de salida son números en la cadena de retorno, delimitados por comas

Sin golf

string c(int n)=>
    string.Join(",",                                        // Join them with commas
        Enumerable.Range(1,12)                              // For 1-12 inclusive
        .Where(                                             // Select only
            i=>new DateTime(n,i,DateTime.DaysInMonth(n,i)   // Get last day of that year-month
            ).DayOfWeek                                     // Get its day of week
            ==(DayOfWeek)1                              // Is Monday
        )
    )
;

@TimmyD Sí, pero necesita un reparto explícito. Respuesta actualizada
Link Ng

LINQ es divertido, pero esto es 126 bytes:; void q(int y){for(int m=1;m<13;m++){if((int)new DateTime(y,m,DateTime.DaysInMonth(y,m)).DayOfWeek==1){Console.WriteLine(m);}}}) Además, sería más corto emitir el DayOfWeekto intde lo que sería lanzar el inttoDayOfWeek
Kade

@ Shebang Gracias. Realmente no debería jugar golf en una línea linq --- Solo Jon Skeet puede hacer eso. Vea si tengo tiempo para actualizar mañana. Cansado ahora.
Enlace del

Puede convertir esto para Action<int>guardar algunos bytes
TheLethalCoder

2

Ruby, 54 + 6 = 60 bytes

λ cat monday.rb
p (1..12).select{|m|Date.new($*[0].to_i,m,-1).monday?}
λ ruby -rdate monday.rb 2016
[2, 10]

6 bytes -rdateen la línea de comando para obtener la clase Date de la biblioteca estándar.

Explicación: bastante sencillo gracias a la gran Dateclase de Ruby stdlib . No solo tiene métodos como monday?, tuesday?etc., el constructor tomará números negativos para cualquier campo el año pasado para significar 'contar este campo hacia atrás desde el final del período representado por el campo anterior'. $*es una forma abreviada de ARGV, por lo que $*[0]es una forma rápida de obtener el primer argumento de línea de comando.


2

PHP, 84 bytes

for($m=1;$m++<14;){if(strftime('%w',strtotime($argv[1]."-$m-1"))==2)echo($m-1)." ";}

Mi primer código de golf. Este es el PHP más corto hasta ahora en esta pregunta.

EDITAR: no parece funcionar para el año 1. Tendré que averiguar por qué, pero ahora tengo que irme.


1
Yo diría "¡Bienvenido a PPCG!" ¡pero has estado registrado aquí por más tiempo que yo! : D Bonito primer golf.
AdmBorkBork

Su error es que crea 1-13-1 y 1-14-1 para el año 1 <13 es suficiente. Si resuelve esto, puede eliminar los paréntesis poco precisos en el momento y pensar en usar el operador ternario
Jörg Hülsermann

Esto debería solucionar sus problemasfor(;$m++<12;)strftime("%w",strtotime($argv[1]+($m/12^0)."-".($m%12+1)."-1"))!=2?:print"$m ";
Jörg Hülsermann

2

R, 106 99 95 83 78 77 74 bytes

g=function(x)which(format(seq(as.Date(paste0(x,-2,-1)),,'m',12)-1,"%u")<2)

La secuencia de los últimos días de cada mes viene dada por seq(as.Date(paste0(x,-2,-1)),,'m',12)-1:

  • paste0coacciona -2 y -1 a los personajes. Si xfue 2016, por ejemplo, paste0(x,-2,-1)da "2016-2-1"cuál se convierte al 1 de febrero de 2016 por as.Date.

  • seqaplicado a un POSIXct o un objeto Date es seq(from, to , by, length.out): aquí tono se da, byse da como el 'm'que coincide 'month'con una coincidencia parcial y, length.outpor supuesto , es 12.

  • La secuencia resultante es el primer día de los 12 meses a partir de febrero del año en cuestión. -1nos da entonces el último día de los 12 meses a partir de enero del año en cuestión.

Casos de prueba:

> g(1)
[1]  4 12
> g(25)
[1] 3 6
> g(297)
[1] 5
> g(2000)
[1] 1 7
> g(2016)
[1]  2 10
> g(3385)
[1]  1  2 10
> g(9999)
[1] 5

Versión anterior a 95 bytes, que muestra los nombres de los meses en lugar de solo sus números:

g=function(x)format(S<-seq(as.Date(sprintf("%04i-02-01",x)),,'m',12)-1,"%B")[format(S,"%u")==1]

Esta respuesta es simplemente brillante. No tenía idea de seqtener un método para Date-objects y esto resuelve el problema de as.Dateno manejar los años anteriores 10000en mi respuesta eliminada.
Billywob

@Billywob sí seq.Datey seq.POSIXtson bastante impresionantes: incluso pueden procesar comandos como seq(time1, time2, by="10 min")o seq(date1, date2, by="quarter"). Muy útil al trazar una serie temporal.
plannapus

2

Japt, 24 bytes

Do1 £Ov"Ð400+U"+X e ¥2©X

¡Pruébalo en línea! Emite una matriz de números, confalse en lugar de meses que no terminan en lunes.

Hubo un error en el intérprete que no me permitió usarlo Ðen el cuerpo de la función £. Después de la corrección de errores y otra característica adicional, esto es 18 bytes en la confirmación actual:

Do1@Ð400+UX e ¥2©X

1

Java, 143 129 bytes

Esto usa la nueva API de tiempo de Java 8.

y->{String s="";for(int m=0;++m<13;)if(java.time.YearMonth.of(y,m).atEndOfMonth().getDayOfWeek().ordinal()==0)s+=m+" ";return s;}

Salida

Tenga en cuenta que cada línea tiene un espacio adicional al final.

4 12 
5 
9 
1 7 
2 10 
1 2 10 

Sin golf y probando

import java.time.*;
import java.util.function.*;

public class Main {
    public static void main (String[] args) {
        IntFunction<String> func = year -> {
          String result = "";
          for (int month=1; month <= 12; month++) {
            if (YearMonth.of(year, month).atEndOfMonth().getDayOfWeek().ordinal() == 0) {
              result += month + " ";
            }
          }
          return result;
        };
        System.out.println(func.apply(1));
        System.out.println(func.apply(297));
        System.out.println(func.apply(1776));
        System.out.println(func.apply(2000));
        System.out.println(func.apply(2016));
        System.out.println(func.apply(3385));
    }
}

Afeitado

  1. 143 a 129 bytes: se usa DayOfWeek::ordinalpara comparar con una constante numérica en lugar de la constante enum.
    ¡Gracias @TimmyD por la idea general, si no la solución exacta! ;-)

@TimmyD tristemente, es una enumeración. Sin embargo, tiene un getValue()método que ahorraría unos pocos bytes.
Celos

@Celos ordinal()ahorra 1 byte más en comparación con getValue(), aunque se sugiere que nunca lo use.
Olivier Grégoire

Sí, bien pensado. Publiqué mi comentario sin actualizar primero, por lo que no vi su respuesta y edición.
Celos

1

GNU awk, 80 bytes

{for(;m<13;a=mktime($0" "++m" 1 9 0 0")){if(strftime("%w",a-8e4)~1){print m-1}}}

Ejemplo

$ gawk '{for(;m<13;a=mktime($0" "++m" 1 9 0 0")){if(strftime("%w",a-8e4)~1){print m-1}}}' <<<2016
2
10
$
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.