Encuentra el último domingo de cada mes de un año determinado


21

Soluciones F # conocidas dentro de 140 caracteres , y este es un problema del Código Rosetta .

Resultado requerido en stdout o en una variable de cadena para el año de entrada 2014:

2014-01-26 2014-02-23 2014-03-30 2014-04-27 2014-05-25 2014-06-29 2014-07-27 2014-08-31 2014-09-28 2014-10-26 2014-11-30 2014-12-28

Como se solicitó, para 1900:

1900-01-28 1900-02-25 1900-03-25 1900-04-29 1900-05-27 1900-06-24 1900-07-29 1900-08-26 1900-09-30 1900-10-28 1900-11-25 1900-12-30

Y 2000:

2000-01-30 2000-02-27 2000-03-26 2000-04-30 2000-05-28 2000-06-25 2000-07-30 2000-08-27 2000-09-24 2000-10-29 2000-11-26 2000-12-31

Planteado porque las fechas parecen poner de manifiesto la incomodidad en la mayoría de los idiomas. Más que permitir bibliotecas de fechas, ¡espero verlas! Pero si es externo al idioma base, declare en el nombre de la publicación (por ejemplo, C # + Jon Skeet's NodaTime).

Aclaraciones:

  • Rango de años 1900 a 3015
  • Calendario Gregoriano
  • Si de otra manera importa, lo que sea convencional para el Reino Unido / Londres
  • Un programa que toma un interruptor de línea de comando o stdin está bien, produciendo el resultado en stdout
  • Una función que toma un valor para el año y devuelve una cadena también está bien.

Lagunas estándar excluidas . Estamos ansiosos por las soluciones APL, J, K y ver algunas nuevas bibliotecas de fechas.


@ Sp3000 - 1752 podría ser particularmente incómodo :-)
apremiante ossifrage

@ MartinBüttner: Utilice las bibliotecas de fechas, edite la pregunta para pedir a las personas que declaren las que usan con el idioma.
Phil H

1
Debe especificar el rango de años que son aportes válidos y las consideraciones sobre la adopción gregoriana. (Es decir, si el rango de años incluye alguno anterior a 1930, entonces debe especificar que el calendario gregoriano debe usarse para todo el rango, independientemente de la configuración regional; o que la salida puede variar según la configuración regional; o debe indicar una fecha límite antes de la cual se debe usar el calendario juliano y probar casos durante los tres años posteriores al cambio).
Peter Taylor

1
@squeamishossifrage: lo he limitado a 1900 y gregoriano, porque prefiero evitar un proyecto de investigación para establecer la especificación ...
Phil H

1
@ Adám: Perdón por hacerte esperar tanto tiempo por una respuesta :) Sí, de hecho.
Phil H

Respuestas:


1

Dyalog APL con cal de dfns , 19 bytes

¡Mejor tarde que nunca!

Solicitudes para el año, devuelve la lista de fechas en formato aaaa md .

⎕{⍺⍵,2↑⊢⌿cal⍺⍵}¨⍳12

solicitar entrada numérica y dejar que ese sea el argumento izquierdo para el

{... función anónima (que se encuentra a continuación) aplicada a cada uno de

⍳12 los números del 1 al 12 (los meses)

La función anónima anterior es la siguiente:

⍺⍵, anteponer los argumentos izquierdo y derecho (es decir, año y mes) a

2↑ los dos primeros personajes de

⊢⌿ la fila más baja de

cal el calendario para

⍺⍵ argumento izquierdo y argumento derecho (año y mes)

TryAPL en línea:

  1. Regrese a esta página después de hacer clic aquí para importar caly sus dependencias.

  2. Haga clic aquí para ejecutar los casos de prueba.


Muy bien. Había esperado una biblioteca APL que entendiera lo que significan las fechas, ¡pero cal es razonable!
Phil H

@PhilH fecha y días ?
Adám

1
@PhilH También está el espacio de nombres Fechas de MiServer.
Adám

1
Las primitivas diádicas de @PhilH y Dyalog APL + - < = y funcionan con objetos de fecha .Net .
Adám

7

Rubí, 91 + 6 = 97

#!ruby -prdate
$_=(Date.new(y=$_.to_i)...Date.new(y+1)).select(&:sunday?).chunk(&:mon).map{|k,v|v[-1]}*' '

Funciona bastante bien. select(&:sunday?)es bonito y, sorprendentemente, *' 'formatea todo por sí mismo.


Buenos trucos! Puede guardar tres caracteres más utilizando en chunklugar de group_by.
Cristian Lupascu

Entonces puedo, bien.
histocrat

6

Bash 4.x + ncal, 57

Si los separadores de nueva línea están bien en lugar de espacios, entonces podemos eliminar el -ninterruptor y el espacio final de la echodeclaración. Y supongo que todavía funcionará sin el shebang, así que también lo eliminé:

for i in {01..12};{ echo "$1-$i-`ncal $i $1|tail -c-3`";}

Script original (73 bytes):

#!/bin/bash
for i in {01..12};{ echo -n "$1-$i-`ncal $i $1|tail -c-3` ";}

Uso:

$ bash sundays.sh 2014
2014-01-26
2014-02-23
2014-03-30
2014-04-27
2014-05-25
2014-06-29
2014-07-27
2014-08-31
2014-09-28
2014-10-26
2014-11-30
2014-12-28
$

Nota: Las versiones Bash anteriores a la 4.0 omitirán los ceros iniciales de los meses. Esto se puede solucionar con la adición de 5 caracteres cambiando {01..12}a `seq -w 1 12)`. Además, tail -c-3puede causar problemas en algunos sistemas donde la salida de ncalincluye espacios finales, pero no conozco ninguno que lo haga.


1
¿La diferencia está realmente relacionada con Darwin, no solo con la versión Bash? Se agregó en Bash 4.0 (aunque hubo algunos errores más adelante). De todos modos, 1 personaje aún se puede salvar usando en `…`lugar de un buen hábito $(…).
manatwork

Ah, podría ser. Darwin dice que está usando la versión 3.2.53; Debian está utilizando 4.1.5.
aprensivo ossifrage

@manatwork PD: Acabo de notar tu comentario sobre los ticks. Buena captura, gracias!
aprensivo ossifrage

No creo que necesites contarlo #!/bin/bashpara jugar golf.
Trauma digital

@DigitalTrauma Eso está bien. Parece que también puedo usar saltos de línea en lugar de espacios. Ahora hasta 57 bytes :-)
squeamish ossifrage

6

IBM DFSORT, 11 3 líneas de 71, 72 u 80 caracteres

 OPTION COPY 
 OUTFIL REPEAT=12,OVERLAY=(5:SEQNUM,2,ZD,5,2,1,8,Y4T,LASTDAYM,TOJUL=Y4T*
 ,9,7,Y4T,ADDDAYS,+1,TOJUL=Y4T,1:16,7,Y4T,PREVDSUN,TOGREG=Y4T(-),12X) 

Las dos respuestas con formato de salida en columna han resistido la prueba del tiempo. Eso me da un "bucle", más o menos, en que en OUTFIL REPEAT = copia el registro actual que muchas veces.

Una técnica diferente para llegar al valor, que parece más larga pero más corta, ya que no puedo encontrar ninguna forma incondicional de lidiar con el duodécimo registro en el año siguiente, y hacerlo condicional significa que incluye IFTHEN=(WHEN=, dos veces y algunas otras cosas. Gane en los cambios (el primer mes es la forma más sencilla de hacerlo) pierda mucho en las rotondas (requisitos de sintaxis particulares).

Esto utiliza una función incorporada (todas las funciones en DFSORT están incorporadas) para encontrar el último día del mes. Luego agrega un día (función) para llegar al primero del mes siguiente y usa la función PREVDSUN para obtener el domingo anterior (que siempre será el último domingo del mes anterior, como antes).

Al convertir el año (entrada) en una fecha válida, se usa un número de secuencia de dos dígitos para el mes, y ese valor también se copia para el día, ya que el punto de partida no importa mientras sea válido, ya que somos después del último día del mes inicialmente: 5,2 es más corto queC'01' .

Aquí está el detalle:

OPTION COPY - copia el archivo de entrada a la salida

OUTFIL: para permitir múltiples archivos de salida, con diferente selección y formato, producir informes formateados. Se usa con preferencia al más corto INRECdebido al uso de REPEAT=.

REPETIR = 12 - produce 12 copias de cada registro. En este ejemplo, solo puede haber un registro de entrada (a diferencia de la versión anterior) debido a SEQNUM.

5: comienza en la columna 5 del registro.

SEQNUM, 2, ZD: número de secuencia, por defecto comienza en uno, dos dígitos, "decimal con zona" (para sin signo, que serán, igual que el carácter).

1,8 - copie los bytes 1 para la longitud 8 en la ubicación actual (9). Esto se debe a que el Y4T necesita ver ese 8, de lo contrario se usará un formato de fecha diferente.

Y4T: fecha de formato ccyymmdd (debido a los 8 que se encuentran inmediatamente delante).

LASTDAYM - Último día del mes (también posible de semana, trimestre y año).

TOJUL = - conversión de fecha de salida para funciones de fecha (TOJUL es un carácter menos que TOGREG)

9,7 - ahora que tiene 7 largos, Y4T será CCYYDDD.

ADDDAYS: agrega una cantidad de días, ajustándose automáticamente si entra en el siguiente mes / año (también podría ser ADDMONS y ADDYEARS)

PREVDSUN: aparece la fecha juliana, se ubica el domingo anterior, TOGREG para obtener el formato de salida correcto, con el separador "-" (podría ser cualquier cosa que desee como separador)

12X: espacios en blanco para aclarar el desorden que nos ha permitido hacerlo de una manera tan corta

El resultado de lo anterior, para 2014, es:

2014-01-26
2014-02-23
2014-03-30
2014-04-27
2014-05-25
2014-06-29
2014-07-27
2014-08-31
2014-09-28
2014-10-26
2014-11-23
2014-12-28

Se requiere algo para decirle al SORT qué hacer. No hay defecto. OPTION COPYes el más corto, SORT FIELDS=COPYes equivalente pero más largo.

El trabajo en sí lo hizo esta vez OUTFIL(para permitir el uso de REPEAT). Podría decirse que el código de trabajo es cualquiera de 160 (2 * 80), 144 (2 * 72), 140 (72 + 69) o 138 (70 + 68) (excluyendo los espacios en blanco iniciales, la continuación forzada y los espacios en blanco finales).

Dado que el receptor tendría que saber lo que está haciendo, creo que puedo decir que el código DFSORT para enumerar el último domingo de cada mes para cualquier año desde 1900 (se ejecutará desde el año 0001, pero estoy evitando la investigación como bien) hasta 9999 (aunque DFSORT admite años hasta 9999, la solución anterior no funcionaría en el año 9999 ya que la duodécima fecha entra en el año siguiente) se puede tuitear.

¿Por qué el código es tan largo si hay funciones incorporadas especialmente adecuadas?

Las definiciones de campo son efímeras. Un campo solo se define como una ubicación particular dentro de los datos (que es un registro) para su uso inmediato. En otras palabras, los campos no se definen como tales, sino que se definen para cada uso y solo para su uso. Las funciones de fecha necesitan saber qué (de muchos) formatos de fecha se utilizan para la fuente, y la salida debe estar en un formato de fecha, por lo que debe especificarse.

Ahora que tenemos una cita juliana ... ¿Por confirmar?


 OPTION COPY 
 INREC OVERLAY=(1,4,C'0201',1,8,1,8,1,8,1,8,1,8,1,8,1,8,1,8,1,8,1,8,1,8*
 ,94:C'1',89:1,4,ZD,ADD,+1,ZD,LENGTH=4,14:C'3',22:C'4',30:C'5',38:C'6',*
 46:C'7',54:C'8',62:C'9',69:C'10',77:C'11',85:C'12',127:X,89,8,Y4T,PREV*
 DSUN,TOGREG=Y4T(-),116:X,81,8,Y4T,PREVDSUN,TOGREG=Y4T(-),105:X,73,8,Y4*
 T,PREVDSUN,TOGREG=Y4T(-),94:X,65,8,Y4T,PREVDSUN,TOGREG=Y4T(-),83:X,57,*
 8,Y4T,PREVDSUN,TOGREG=Y4T(-),72:X,49,8,Y4T,PREVDSUN,TOGREG=Y4T(-),61:X*
 ,41,8,Y4T,PREVDSUN,TOGREG=Y4T(-),50:X,33,8,Y4T,PREVDSUN,TOGREG=Y4T(-),*
 39:X,25,8,Y4T,PREVDSUN,TOGREG=Y4T(-),28:X,17,8,Y4T,PREVDSUN,TOGREG=Y4T*
 (-),17:X,09,8,Y4T,PREVDSUN,TOGREG=Y4T(-),1:1,8,Y4T,PREVDSUN,TOGREG=Y4T*
 (-),11:X,18,120,6X) 

Necesita algo JCL

//LASTSUNG EXEC PGM=SORT 
//SYSOUT   DD SYSOUT=* 
//SORTOUT  DD SYSOUT=* 
//SYSIN    DD * 

Y un archivo de entrada (otra línea de JCL y tres elementos de datos integrados):

//SORTIN DD *
2014 
1900 
2000 

Produce:

2014-01-26 2014-02-23 2014-03-30 2014-04-27 2014-05-25 2014-06-29 2014-07-27 2014-08-31 2014-09-28 2014-10-26 2014-11-30 2014-12-28
1900-01-28 1900-02-25 1900-03-25 1900-04-29 1900-05-27 1900-06-24 1900-07-29 1900-08-26 1900-09-30 1900-10-28 1900-11-25 1900-12-30
2000-01-30 2000-02-27 2000-03-26 2000-04-30 2000-05-28 2000-06-25 2000-07-30 2000-08-27 2000-09-24 2000-10-29 2000-11-26 2000-12-31

Realmente funcionará hasta el año 9999.

DFSORT es el producto de clasificación de mainframe de IBM. Los datos se pueden manipular, pero dado que la clasificación es clave y los tipos son a menudo grandes y de larga duración, las tarjetas de control DFSORT no tienen construcciones de bucle, por lo que no podemos poner un SORT en un bucle. Hace las cosas un poco largas para tareas como Golf.

Por qué publicar la respuesta, es porque DFSORT tiene una PREVDdayfunción. Así que el último domingo de un mes es fácil. Es el domingo anterior (PREVDSUN) al primer día del mes siguiente.

También fue divertido hacerlo dentro de un "operando" (OVERLAY), un poco como hacerlo todo dentro sprintfo similar.

Aquí no tiene golf:

 OPTION COPY 

 INREC OVERLAY=(1,4,C'0201',1,8,1,8,1,8,1,8,1,8,1,8, 
         1,8,1,8,1,8,1,8, 
         1,8,94:C'1',89:1,4,ZD,ADD,+1,ZD,LENGTH=4, 
         14:C'3',22:C'4',30:C'5',38:C'6',46:C'7',54:C'8',
         62:C'9',69:C'10',77:C'11',85:C'12', 
        127:X,89,8,Y4T,PREVDSUN,TOGREG=Y4T(-), 
        116:X,81,8,Y4T,PREVDSUN,TOGREG=Y4T(-), 
        105:X,73,8,Y4T,PREVDSUN,TOGREG=Y4T(-), 
         94:X,65,8,Y4T,PREVDSUN,TOGREG=Y4T(-), 
         83:X,57,8,Y4T,PREVDSUN,TOGREG=Y4T(-), 
         72:X,49,8,Y4T,PREVDSUN,TOGREG=Y4T(-), 
         61:X,41,8,Y4T,PREVDSUN,TOGREG=Y4T(-), 
         50:X,33,8,Y4T,PREVDSUN,TOGREG=Y4T(-), 
         39:X,25,8,Y4T,PREVDSUN,TOGREG=Y4T(-), 
         28:X,17,8,Y4T,PREVDSUN,TOGREG=Y4T(-), 
         17:X,09,8,Y4T,PREVDSUN,TOGREG=Y4T(-), 
          1:1,8,Y4T,PREVDSUN,TOGREG=Y4T(-), 
         11:X,18,120,6X) 

Si bien no es un abuso, no sería habitual tratar de agrupar todo esto en un REVESTIMIENTO, y hay algunas cosas aparentemente innecesarias que se necesitan para permitir que todo entre en un REVESTIMIENTO. Hay espacio para jugar al golf, pero como solo eliminaría una línea como máximo, no estoy tentado.

El INREC se procesa para cada registro.

OVERLAY permite cambiar el contenido de un registro existente. Si el registro se extiende más allá de su longitud en el proceso, eso no es un problema.

1,4 es el año entrante. Tiene un literal de 0201 adjunto, y luego los sucesivos 1,8s lo repiten 11 veces para dar una tirada larga de 96 bytes,

El duodécimo año en el registro actual extendido obtiene 1 agregado y su mes se convierte en 1 (enero).

Los 10 meses restantes se cambian de 3 a 11.

Luego hay 12, en orden inverso (debido a la REVESTIMIENTO) de este tipo de cosas:

127:X,89,8,Y4T,PREVDSUN,TOGREG=Y4T(-),

El n: es un número de columna en el registro. La X inserta un espacio en blanco. 89,8 toma los datos de esa columna / longitud, Y4T los trata como una fecha CCYYMMDD, PREVDSUM funciona el domingo anterior, TOGREG = Y4T (-) los emite como una fecha gregoriana CCYY-MM-DD.

Debido a que obtienes basura si la fuente y el objetivo de una parte particular de un OVERLAY se superponen destructivamente, el 11:X,18,120,6X)reordenamiento final y enmascara un poco de desorden.

Los manuales y documentos se pueden encontrar en: http://www-01.ibm.com/support/docview.wss?uid=isg3T7000080 , e incluye la Guía de programación de aplicaciones DFSORT de más de 900 páginas.

Al igual que con todos los productos de IBM, todos los manuales están disponibles de forma gratuita (excepto una cantidad insoportablemente pequeña de costosos que solo un número muy pequeño de personas en el mundo fingiría entender).

Todas las tarjetas de control DFSORT deben comenzar con un espacio en blanco. La columna 72 solo se usa para la continuación (cualquier no en blanco servirá, pero * es convencional). La columna 72 es seguida por un área de número de secuencia que se ignora, haciendo que cada registro sea de 80 bytes.

Otro par de soluciones por venir, tal vez.


5

Bash, 63 bytes

for i in {01..12};{  date -v30d -v${i}m  -v2014y  -vsun +%Y-%m-%d;}

Salida:

2014-01-26
2014-02-23
2014-03-30
2014-04-27
2014-05-25
2014-06-29
2014-07-27
2014-08-24
2014-09-28
2014-10-26 
2014-11-30
2014-12-28

for i in {1..12};{ date -v30d -v${i}m -v$1y -v0w +%Y-%m-%d;}- 60 bytes
Trauma digital

-vparam to datees específico de la fecha BSD. Entonces esto funciona en OSX, pero no en la mayoría de Linux, tal vez eso debería indicarse en la respuesta.
Trauma digital

@ DigitalTrauma, funciona en Mac y mi Linux.
michael501

4

Python 2 - 189 bytes

y=input()
for m in range(12):
 d=[31-(1322>>m&1),28+(y%400<1or 1>y%4<y%100)][m==1];Y=y-(m<2);Z=Y%100;C=Y/100
 while(d+13*((m-2)%12+4)/5+Z+Z/4+C/4-2*C)%7-1:d-=1
 print"%d-%02d-%d"%(y,m+1,d),

Ingrese la fecha a través de STDIN.

Todavía se puede hacer mucho más golf. El programa se va un poco por la borda, solo por diversión:

  • No hay importaciones, en particular no se utilizan funciones de fecha incorporadas
  • Utiliza la congruencia de Zeller para calcular los días de la semana.

Notas

  • 1322 es una tabla de búsqueda mágica para determinar si un mes que no es de febrero tiene 30 o 31 días
  • No zfillse necesita durante años debido al rango de entrada, ni días, ya que siempre serán mayores de 20

Python 2 - 106 bytes

La solución no tan divertida:

from calendar import*
y=input();m=1
while m<13:w,n=monthrange(y,m);print"%d-%02d-%d"%(y,m,n-(n+w)%7),;m+=1

calendar.monthrangedevuelve dos números: el día de la semana en que comienza el mes ( w) y el número de días en el mes ( n). La solución es un poco contradictoria debido a una captura: ¡el día de la semana devuelto comienza a las 0 para el lunes , no para el domingo! Sin embargo, esto se compensa con el hecho de que nestá basado en 1.


1
Una respuesta Pyth muy tonta:$from calendar import monthrange as gt$V12AGH>QhN%"%d-%02d-%d"(QhN-H%+GH7
FryAmTheEggman

3

JavaScript (ES6) 155 145

Editar problemas de zona horaria fija Podría ser más corto si se hace recursivo. Tal vez.

F=y=>{
  for(n=i=o=[];!o[11];)
    d=new Date(Date.UTC(y,0,++i)),m=d.getMonth(),
    d.getDay()||(m!=n&&o.push(p.toISOString().slice(0,10)),p=d,n=m);
  return o.join(' ')
}

Puedes usar new Date(y,0,++i,9). Además, esto falla para los años bisiestos de 2100 y superiores, ya que JS no tiene información sobre esos años bisiestos y, por lo tanto, no tiene ninguno Feb 29en los años bisiestos para 2100 y superiores.
Optimizador

@Optimizer no es JS: 2100,2200,2300 no son años bisiestos. 2014 es un año bisiesto y JS lo sabe. En cuanto al uso de la hora 9, no puedo verificarlo, pero creo que eso no funciona si estás, por ejemplo, en Melbourne ...
edc65

Ah .. Nunca supe que bajamos 3 días por 400 años. Sobre el 9 - Cambié mi zona horaria de -1000 (Hawai) a +1100 (Melbourne) y new Date(2014,0,26,9)fue un domingo dando la ISOcadena correcta , así getDay()como 0.
Optimizador

3

JavaScript, ES6, 222 219 199 bytes

No vi ninguna respuesta de JavaScript en el wiki de rosetta.

Aquí vamos:

S=Y=>{for(l=[],p=new Date(Y,i=0);i<365+!(Y%4);)if(!(d=new Date(Y,0,++i,9)).getDay()){p.getMonth()-d.getMonth()&&l.push(p);p=new Date(d)}return[...l,p].map(x=>x.toISOString().split("T")[0]).join(" ")}

Esto crea una función Sque devuelve una cadena con la salida deseada. La función también se encarga de los años bisiestos.

Debido a ES6, esto solo funciona en una versión más reciente de Firefox.

Gracias a apsillers por el consejo que lo redujo a 200 bytes

Encuentre la versión no protegida a continuación como un fragmento de pila que puede ejecutar aquí mismo:

S=Y=>{
  for(l=[],p=new Date(Y,i=0);i<365+!(Y%4);)
    if(!(d=new Date(Y,0,++i,9)).getDay()){
      p.getMonth()-d.getMonth()&&l.push(p);
      p=new Date(d)
    }
  return[...l,p].map(x=>x.toISOString().split("T")[0]).join(" ")
}

alert(S(parseInt(prompt())))


Puede usar + prompt () en lugar de parseInt y eliminar algunos bytes
Jacob

@Jacob Ese aviso no se agrega al recuento de bytes.
Optimizador

OIC Debería haber leído la pregunta ...
Jacob

@apsillers Gracias una tonelada! Solucionó el problema y lo redujo mucho en función de su propina.
Optimizador

La 2100salida de entrada 2100-01-31 2100-02-28 2100-03-28 2100-04-25 2100-05-30 2100-06-27 2100-07-25 2100-08-29 2100-09-26 2100-10-31 2100-11-28 2100-12-26 2101-01-02es incorrecta.
Qwertiy

3

Rebol - 120116 80 79 76

d: do join"1-1-"input print collect[for m 2 13 1[d/2: m keep d - d/weekday]]


Ungolfed + algunas anotaciones:

d: do join "1-1-" input         ;; golfy way to create Rebol date! datatype 1-Jan-(year)

print collect [
    for m 2 13 1 [              ;; loop thru months 2 to 13!
        d/2: m                  ;; move to (1st of) next month
        keep d - d/weekday      ;; collect/keep last sunday of month
    ]
]

Ejemplo del cálculo del domingo en la consola Rebol:

>> ; get last sunday of Jan 2014

>> d: 1-1-2014
== 1-Jan-2014

>> d/month: d/month + 1
== 2

>> d
== 1-Feb-2014

>> d/weekday
== 6

>> d - d/weekday
== 26-Jan-2014

>> ; above is last sunday of Jan 2014
>> ; and when pass end of year (ie. month 13!)

>> d/month: 13
== 13

>> d
== 1-Jan-2015

Potencial 87: d: 1-1-1 d / año: hacer entrada imprimir recolectar [repetir m 12 [d / mes: m + 1 mantener d - d / día de la semana]]
rgchris

@rgchris Gracias Chris. Pude afeitarme otros 7 caracteres.
draegtun

¡¡Agradable!! Es malo, pero nunca pienses que FOR es un atajo.
rgchris

2

CJam, 122 102 bytes

30li:X400%){[1387Yb30f+~28I!I4%!I100%e&|g+\]W%{\_2$>7*-\7%7\m1$+}/}fI;]12/W=12,{101+s1>}%]z{X+W%'-*S}/

Esto no usa ninguna forma de biblioteca de fechas. También se puede jugar mucho al golf, creo.

Pruébalo aquí.


3
Estoy tan espectacularmente emocionado que una respuesta de CJam no es la mejor respuesta en un desafío de código de golf por una vez. Puedo morir feliz ... Hoy es un buen día (hasta que se haya reducido a 6 bytes, obviamente)
Brandon

@ Brandon: Esa fue la razón por la que pensé que sería interesante. Realmente espero ver alguna biblioteca maravillosa que lo haga fácil, pero decepcionado hasta ahora.
Phil H

1

R, 128 caracteres

P=paste;f=format;a=strptime(P(1:366,scan()),"%j %Y");cat(sort(sapply(split(a,f(a,"%B")),function(x)P(tail(x[f(x,"%u")==7],1)))))

Con saltos de línea:

P=paste
f=format
a=strptime(P(1:366,scan()),"%j %Y")
cat(sort(sapply(split(a,f(a,"%B")),function(x)P(tail(x[f(x,"%u")==7],1)))))

1

C # 255

Sin golf

static void Main(string[] a)
    {
        int y = Int32.Parse(Console.ReadLine());
        DateTime d = new DateTime(y, 1, 1);
        while (d.Year == y)
        {
            if (d.DayOfWeek == DayOfWeek.Sunday && d.Day>(DateTime.DaysInMonth(y,d.Month)-7))
                Console.WriteLine(d.ToShortDateString());
            d = d.AddDays(1);
        }
        Console.ReadKey();
    }

Editar: modificado para imprimir solo el último domingo :)


No es el formato de salida requerido. + Este es el código de golf
edc65

1

q, 67

{({{1<>x mod 7}-[;1]/x}')14h$1_til[13]+13h$"D"$(($)x),".01.01"}

¿No hay bibliotecas de fechas utilizables para esto en q?
Phil H

1

"¡Oh, no, él otra vez!"

Java - 259 246 bytes

void g(int y){for(int i=;i<12;i++){GregorianCalendar c=new GregorianCalendar(y,i,0);c.set(c.DAY_OF_WEEK,c.SUNDAY);c.set(c.DAY_OF_WEEK_IN_MONTH,-1);System.out.print(y+"-"+String.format("%02d",(c.get(c.MONTH)+1))+"-"+(c.get(c.DAY_OF_MONTH))+" ");}}

Versión sin golf:

void g(int y){
    for (int i = 0; i < 12;i++) {
        GregorianCalendar c = new GregorianCalendar(y, i, 0);
        c.set(c.DAY_OF_WEEK, c.SUNDAY);
        c.set(c.DAY_OF_WEEK_IN_MONTH, -1);
        System.out.print(y+"-"+String.format("%02d",(c.get(c.MONTH)+1))+"-"+(c.get(c.DAY_OF_MONTH))+" ");
    }
}

Uso:

import java.util.GregorianCalendar;
import java.util.Scanner;

public class LastSundayInYear {

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.println("Year?");
        int year = scanner.nextInt();
        LastSundayInYear sunday = new LastSundayInYear();
        sunday.g(year); 
    }

    void g(int y){
        for (int i = -1; ++i < 12;) {
            GregorianCalendar c = new GregorianCalendar(y, i, 0);
            c.set(c.DAY_OF_WEEK, c.SUNDAY);
            c.set(c.DAY_OF_WEEK_IN_MONTH, -1);
            System.out.print(y+"-"+String.format("%02d",(c.get(c.MONTH)+1))+"-"+(c.get(c.DAY_OF_MONTH))+" ");
        }
    }
}

Salida:

2014-01-26 2014-02-23 2014-03-30 2014-04-27 2014-05-25 2014-06-29 2014-07-27 2014-08-31 2014-09-28 2014-10-26 2014-11-30 2014-12-28

Sin embargo, otra respuesta "pongamos una respuesta de Java solo por diversión". Oh bien. Pero, al menos, como te molestaste en llegar a este punto de mi respuesta, intentaré aburrirte un poco más y explicarte mi razonamiento.

El método grecibe el año deseado y, para cada mes, crea un GregorianCalendarobjeto (los meses van de 0 a 11). Luego, el primero c.setestablece el día de la semana como domingo y el segundo declara que queremos la última semana del mes, como se ve en la documentación oficial . Los System.out.printlnimprime la fecha de que el domingo (si es que estábamos haciendo este derecho, el año se imprimiría como c.get(c.YEAR), pero utilizando yde nuevo afeita 13 caracteres), el mes tiene que ser formateado para añadir un cero a la izquierda de enero a septiembre (y la el valor se incrementa porque, bueno, los meses aquí se representan 0-11) y se imprime el día del último domingo. Y este procedimiento se repite durante los otros once meses.


0

C #, 212 , 237

string x(int y){var s="";var t="";var d=new DateTime(y,1,1);for(;;){if(d.Year!=y){return s;}t=(d.DayOfWeek==DayOfWeek.Sunday)?t=string.Format("{0}-{1}-{2} ",d.Year,d.Month,d.Day):t;s=(d.AddDays(1).Month!=d.Month)?s+=t:s;d=d.AddDays(1);}}

Con saltos de línea

string x(int y)
    {
        var s = "";
        var t = "";
        var d = new DateTime(y,1,1);
        for (;;)
        {
            if (d.Year != y) {
                return s;
            }
            t = (d.DayOfWeek == DayOfWeek.Sunday) ? t = string.Format("{0}-{1}-{2} ", d.Year, d.Month, d.Day) : t;
            s=(d.AddDays(1).Month!=d.Month)?s+=t:s;
            d=d.AddDays(1);
        }
    }

Salida para 2014

"2015-1-25 2015-2-22 2015-3-29 2015-4-26 2015-5-31 2015-6-28 2015-7-26 2015-8-30 2015-9-27 2015-10-25 2015-11-29 2015-12-27"

No es el formato de salida requerido
edc65

Ahí, arreglado. ¿Mejor?
Darren Breen

0

C # 171

Función que devuelve una cadena.

string S(int y){var r="";for(int m=1;m<13;++m){var d=new System.DateTime(y,1,1).AddMonths(m).AddDays(-1);r+=y+string.Format("-{0:00}-{1} ",m,d.Day-d.DayOfWeek);}return r;}

Sin golf

string S(int y)
{
    var r="";
    for (int m=1;m<13;++m)
    {
        var d = new System.DateTime(y, 1, 1).AddMonths(m).AddDays(-1);
        r += y + string.Format("-{0:00}-{1} ", m, d.Day - d.DayOfWeek);
    }
    return r;
}

0

C # 194

usando Linq:

string d(int y){return string.Join(" ",Enumerable.Range(1,12).Select(m=>new DateTime(y,m,DateTime.DaysInMonth(y,m))).Select(d=>d.AddDays(-(int)d.DayOfWeek)).Select(d=>d.ToString("yyy-MM-dd")));}

Sin golf

string d(int y)
{
    return string.Join(" ",Enumerable.Range(1,12)
        .Select(m => new DateTime(y, m, DateTime.DaysInMonth(y, m)))
        .Select(d => d.AddDays(-(int)d.DayOfWeek))
        .Select(d => d.ToString("yyy-MM-dd")));
}

Salida

2013-01-27 2013-02-24 2013-03-31 2013-04-28 2013-05-26 2013-06-30 2013-07-28 2013-08-25 2013-09-29 2013-10-27 2013-11-24 2013-12-29

0

Mathematica - 171

Envuelto en una función anónima, devuelve la cadena

StringJoin[Last@#~DateString~{"Year","-","Month","-","Day"," "}&/@GatherBy[Select[DateRange[DateObject[{#}],DateObject[{#+1}]],DayName@#==Sunday&],DateValue[#,"Month"]&]]&

Primero Mathica Golf. Siento que podría reducirse sustancialmente.


0

VB-192

Function z(y)
For i = 1 To 11
a = 0
s = IIf(i <> 11, DateSerial(y, i + 1, 1), DateSerial(y + 1, 1, 1))
While Weekday(s - a) <> 1
a = a + 1
Wend
r = r + Str(s - a) + " "
Next
z = r
End Function

Podría ser peor ^^

Mi segunda y última entrada (no creo que pueda hacerlo más pequeño)

142

Function z(y)
Dim m(12)
For i = 1 To 366
s = DateSerial(y, 1, 1) + i
If Weekday(s) = 1 Then m(Month(s)) = s
Next
z = Join(m, " ")
End Function

0

Rubí 76

Utiliza un parámetro de línea de comandos ruby sundays.rb 1900. Utiliza la biblioteca de fechas.

require'date';puts (1..12).map{|m|d=Date.new($*[0].to_i,m,-1);d-d.wday}*" "
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.