Encontre o último domingo de cada mês de um determinado ano

21

Soluções F # conhecidas em 140 caracteres , e esse é um problema do Código Rosetta .

Resultado necessário no stdout ou em uma variável de sequência para o ano 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 foi solicitado, 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

E 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

Posou porque as datas parecem trazer estranheza na maioria dos idiomas. Mais do que permitir bibliotecas de datas, espero vê-las! Mas se for externo ao idioma base, declare no nome da postagem (por exemplo, NodaTime do C # + Jon Skeet).

Esclarecimentos:

  • Intervalo de anos de 1900 a 3015
  • calendário gregoriano
  • Caso contrário, o que for convencional para o Reino Unido / Londres.
  • Um programa usando uma opção de linha de comando ou stdin é bom, produzindo o resultado em stdout
  • Uma função que pega um valor para o ano e retorna uma string também é boa.

Falhas padrão excluídas . Ansioso pelas soluções APL, J, K e vendo algumas novas bibliotecas de datas.

Phil H
fonte
@ SP3000 - 1752 poderia ser particularmente difícil :-)
ossifrage escrúpulos
@ MartinBüttner: Por favor, use as bibliotecas de datas, editei a pergunta para pedir às pessoas que declarem aquelas que usam no idioma.
Phil H
1
Você deve especificar o intervalo de anos que são entradas válidas e considerações sobre a adoção gregoriana. (Ou seja, se o intervalo de anos incluir algum antes de 1930, você deve especificar que o calendário gregoriano deve ser usado para todo o intervalo, independentemente da localidade; ou que a saída possa variar por localidade; ou você deve fornecer uma data de corte antes da qual o calendário juliano deve ser usado e casos de teste pelos três anos em torno da transição).
Peter Taylor
1
@squeamishossifrage: Limitei-o a 1900 e gregoriano, porque prefiro evitar um projeto de pesquisa para estabelecer as especificações ...
Phil H
1
@ Adám: Desculpe fazer você esperar tanto tempo por uma resposta :) Sim, de fato.
Phil H

Respostas:

1

Dyalog APL com cal de dfns , 19 bytes

Antes tarde do que nunca!

Solicita o ano, retorna a lista de datas no formato aaaa md .

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

solicitar entrada numérica e deixar esse argumento à esquerda do

{... função anônima (encontrada abaixo) aplicada a cada um

⍳12 os números de 1 a 12 (os meses)

A função anônima acima é a seguinte:

⍺⍵, preceda os argumentos esquerdo e direito (ou seja, ano e mês) para

2↑ os dois primeiros caracteres de

⊢⌿ a linha mais baixa de

cal o calendário para

⍺⍵ argumento esquerdo e argumento direito (ano e mês)

TryAPL online:

  1. Retorne a esta página depois de clicar aqui para importar cale suas dependências.

  2. Clique aqui para executar os casos de teste.

Adão
fonte
Muito bom. Esperava uma biblioteca de APL que entendesse o que as datas significam, mas cal é razoável!
Phil H
Data e dias @PhilH ?
Adám
1
@PhilH Há também o namespace Dates do MiServer.
Adám
1
@PhilH E Dyalog As primitivas diádicas da APL + - < = e trabalham com objetos de data .Net .
Adám
7

Ruby, 91 + 6 = 97

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

Funciona muito bem. select(&:sunday?)é bonito e, surpreendentemente, *' 'faz toda a formatação por si só.

histocrata
fonte
Truques agradáveis! Você pode salvar mais três caracteres usando em chunkvez de group_by.
Cristian Lupascu
Então eu posso, legal.
histocrat
6

Bash 4.x + ncal, 57

Se os separadores de nova linha estiverem OK em vez de espaços, podemos remover a -nopção e o espaço à direita da echoinstrução. E acho que ainda funcionará sem o shebang, então removi isso também:

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: As versões bash anteriores a 4.0 omitem os zeros iniciais dos meses. Isso pode ser corrigido com a adição de 5 caracteres, alterando {01..12}para `seq -w 1 12)`. Além disso, tail -c-3pode causar problemas em alguns sistemas em que a saída ncalinclui espaços à direita, mas não conheço nenhum deles.

ossifrage melindroso
fonte
1
A diferença está realmente relacionada a Darwin, não apenas à versão do Bash? Foi adicionado no Bash 4.0 (embora houvesse alguns erros mais tarde). De qualquer forma, um caractere ainda pode ser poupado usando-o em `…`vez de um bom hábito $(…).
manatwork
Ah, poderia ser. Darwin diz que está usando a versão 3.2.53; O Debian está usando o 4.1.5.
squishish ossifrage
@manatwork PS: Acabei de notar seu comentário sobre os back-ticks. Boa captura, obrigado!
ossifrage squeamish
Eu não acho que você precisa contar #!/bin/bashpara o golfe.
Digital Trauma
@DigitalTrauma Isso é bom. Parece que também posso usar quebras de linha em vez de espaços. Até 57 bytes agora :-)
squeamish ossifrage
6

IBM DFSORT, 11 3 linhas de 71, 72 ou 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) 

As duas respostas com formato de saída colunar resistiram ao teste do tempo. Isso me dá um "loop", mais ou menos, em que em OUTFIL REPEAT = copia o registro atual várias vezes.

Técnica diferente para chegar ao valor, que parece mais longo, mas é mais curto, pois não consigo encontrar uma maneira incondicional de lidar com o 12º registro no ano seguinte, e torná-lo condicional significa incluir IFTHEN=(WHEN=duas vezes e outras coisas. O ganho nas oscilações (primeiro do mês é a maneira mais simples de fazê-lo) perde muito nas rotatórias (requisitos específicos de sintaxe).

Isso usa uma função embutida (todas as funções no DFSORT são embutidas) para encontrar o último dia do mês. Em seguida, adiciona um dia (função) para chegar ao primeiro mês seguinte e usa a função PREVDSUN para obter o domingo anterior (que sempre será o último domingo do mês anterior, como antes).

Ao transformar o ano (entrada) em uma data válida, um número de seqüência de dois dígitos é usado para o mês, e esse valor também é copiado para o dia, pois o ponto de partida não importa enquanto válido, pois estamos após o último dia do mês inicialmente: 5,2é menor que C'01'.

Aqui está o detalhe:

OPTION COPY - copia o arquivo de entrada para a saída

OUTFIL - para permitir que vários arquivos de saída, com seleção e formatação diferentes, produzam relatórios formatados. Utilizado de preferência ao mais curto INRECdevido ao uso de REPEAT=.

REPEAT = 12 - produza 12 cópias de cada registro. Neste exemplo, pode haver apenas um registro de entrada (diferente da versão anterior) devido ao SEQNUM.

5: - comece na coluna 5 do registro.

SEQNUM, 2, ZD - número de sequência, o padrão é iniciar com um, dois dígitos, "decimal zonado" (para não assinado, qual será o mesmo que o caractere).

1,8 - copie os bytes 1 do comprimento 8 para o local atual (9). Isso ocorre porque o Y4T precisa ver esse 8, caso contrário, um formato de data diferente será usado.

Y4T - data no formato ccyymmdd (devido aos 8 imediatamente à frente).

ÚLTIMO DIA - Último dia do mês (também possível da semana, trimestre e ano).

TOJUL = - gera conversão de data para funções de data (TOJUL é um caractere menor que TOGREG)

9,7 - agora que tem 7 anos, o Y4T será CCYYDDD.

ADDDAYS - adiciona vários dias, ajustando-se automaticamente se o mês / ano seguinte (também pode ser ADDMONS and ADDYEARS)

PREVDSUN - a data juliana chega, domingo anterior está localizado, TOGREG para obter o formato de saída correto, com o separador "-" (pode ser o que você quiser como separador)

12X - espaços em branco para esclarecer a bagunça que nos permitiu fazê-lo de maneira tão curta

O resultado acima, para 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-23
2014-12-28

É necessário algo para dizer ao SORT o que fazer. Não há padrão. OPTION COPYé o mais curto, SORT FIELDS=COPYé equivalente, mas mais longo.

O trabalho em si realizado desta vez OUTFIL(para permitir o uso de REPEAT). O código de trabalho é sem dúvida qualquer um dos 160 (2 * 80), 144 (2 * 72), 140 (72 + 69) ou 138 (70 + 68) (excluindo os espaços em branco à esquerda, continuação forçada e espaços em branco à direita).

Dado que o receptor precisaria saber o que está fazendo, acho que posso dizer que o código DFSORT para listar o último domingo de cada mês para qualquer ano de 1900 (será executado a partir do ano 0001, mas estou evitando a pesquisa como bem) até 9999 (embora o DFSORT suporte anos até 9999, a solução anterior não funcionaria no ano 9999 desde a 12ª data do ano seguinte) pode ser tweetada.

Por que o código é tão longo, se existem funções embutidas especialmente adequadas?

As definições de campo são efêmeras. Um campo é definido apenas como um local específico nos dados (que é um registro) para uso imediato. Em outras palavras, os campos não são definidos como tal, mas são definidos para cada uso e apenas para uso. As funções de data precisam saber quais (de muitos) formatos de data são usados ​​para a fonte e a saída deve estar em um formato de data, para que seja necessário especificar.

Agora que temos um encontro juliano ... TBC?


 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) 

Precisa de algum JCL

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

E um arquivo de entrada (outra linha da JCL e três itens de dados em sequência):

//SORTIN DD *
2014 
1900 
2000 

Produz:

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

Na verdade, funcionará até o ano 9999.

DFSORT é o produto de classificação de mainframe da IBM. Os dados podem ser manipulados, mas como a classificação é a chave e as classificações geralmente são grandes e de longa execução, os cartões de controle DFSORT não têm construções em loop, portanto, não podemos colocar um SORT em um loop. Torna as coisas um pouco complicadas para tarefas como o golfe.

Por que postar a resposta, é porque o DFSORT tem uma PREVDdayfunção. Então, no último domingo de um mês é fácil. É o domingo anterior (PREVDSUN) para o primeiro dia do mês seguinte.

Também foi divertido fazer isso dentro de um "operando" (OVERLAY), um pouco como fazer tudo dentro sprintfou similar.

Aqui é ungolfed:

 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) 

Embora não seja um abuso, não seria comum tentar colocar tudo isso em um OVERLAY, e há algumas coisas aparentemente desnecessárias necessárias para permitir que tudo entre em um OVERLAY. Há espaço para jogar golfe, mas, como isso removeria apenas uma linha, no máximo, não sou tentado.

O INREC é processado para cada registro.

OVERLAY permite alterar o conteúdo de um registro existente. Se o registro for estendido além do seu comprimento no processo, isso não será um problema.

1,4 é o ano que se aproxima. Ele tem um literal de 0201 anexado e, em seguida, os 1,8s sucessivos o repetem 11 vezes para dar um longo mandril de 96 bytes,

O 12º ano no registro atual estendido recebe 1 adicionado a ele e seu mês é igual a 1 (janeiro).

Os 10 meses restantes são alterados para 3 a 11.

Existem 12, na ordem inversa (devido a OVERLAY) deste tipo de coisa:

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

O n: é um número de coluna no registro. O X insere um espaço em branco. 89,8 pega os dados dessa coluna / comprimento, o Y4T os trata como uma data CCYYMMDD, PREVDSUM trabalha no domingo anterior, TOGREG = Y4T (-) o exibe como uma data gregoriana CCYY-MM-DD.

Como você recebe lixo se a origem e o destino de uma parte específica de um OVERLAY se sobrepõem destrutivamente, o final 11:X,18,120,6X)reorganiza e mascara um pouco de confusão.

Os manuais e os documentos podem ser encontrados em: http://www-01.ibm.com/support/docview.wss?uid=isg3T7000080 e inclui o Guia de programação de aplicativos DFSORT da página 900+.

Como em todos os produtos IBM, todos os manuais estão disponíveis gratuitamente (exceto uma quantidade excruciante pequena de itens muito caros que apenas um número muito pequeno de pessoas no mundo fingiria entender).

Todos os cartões de controle DFSORT devem começar com um espaço em branco. A coluna 72 é usada apenas para continuação (qualquer não em branco serve, mas * é convencional). A coluna 72 é seguida por uma área de número de sequência que é ignorada, tornando cada registro 80 bytes.

Talvez mais algumas soluções por vir.

Bill Woodger
fonte
5

Bash, 63 bytes

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

Saída:

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
michael501
fonte
for i in {1..12};{ date -v30d -v${i}m -v$1y -v0w +%Y-%m-%d;}- 60 bytes
Digital Trauma
-vparam para dateé específico da data do BSD. Portanto, isso funciona no OSX, mas não na maioria dos Linux - talvez isso deva ser indicado na resposta.
Digital Trauma
@DigitalTrauma, funciona no mac e no meu 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),

Digite a data via STDIN.

Ainda muito mais golfe pode ser feito. O programa exagera um pouco, apenas por diversão:

  • Nenhuma importação, em particular não usando nenhuma função de data interna
  • Usa a congruência de Zeller para calcular os dias da semana

Notas

  • 1322 é uma tabela de pesquisa mágica para determinar se um mês não fevereiro tem 30 ou 31 dias
  • Não zfillé necessário durante anos devido à faixa de entrada nem dias, pois eles sempre terão mais de 20 anos

Python 2 - 106 bytes

A solução não tão 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.monthrangeretorna dois números: o dia da semana em que o mês começa em ( w) e o número de dias no mês ( n). A solução é um pouco contra-intuitiva devido a um problema - o dia da semana retornado começa às 0 para segunda-feira , não domingo! No entanto, isso é compensado pelo fato de nser baseado em 1.

Sp3000
fonte
1
Resposta Pyth muito boba:$from calendar import monthrange as gt$V12AGH>QhN%"%d-%02d-%d"(QhN-H%+GH7
FryAmTheEggman
3

JavaScript (ES6) 155 145

Editar Problemas de fuso horário corrigidos poderiam ser mais curtos se tornados recursivos. Talvez.

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(' ')
}
edc65
fonte
Você pode usar new Date(y,0,++i,9). Além disso, isso falha em 2100 e acima dos anos bissextos, já que JS não possui informações sobre esses anos bissextos e, portanto, não os possui Feb 29nos anos bissextos para 2100 e acima.
Optimizer
@Optimizer não é JS: 2100,2200,2300 não são anos bissextos. 2014 é um ano bissexto e JS sabe. Quanto ao uso da hora 9, não posso verificar, mas acho que isso não funcionará se você estiver, por exemplo, em Melbourne ...
edc65
Ah ... nunca soube que perdemos 3 dias a cada 400 anos. Sobre o 9 - Mudei de fuso horário a partir -1000 (Hawaii) para 1100 (Melbourne) e new Date(2014,0,26,9)foi um domingo dando correta ISOcorda, bem como getDay()como 0.
Optimizer
3

JavaScript, ES6, 222 219 199 bytes

Não encontrei nenhuma resposta JavaScript no wiki do rosetta.

Aqui vamos nós:

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

Isso cria uma função Sque retorna uma string com a saída desejada. a função também cuida dos anos bissextos.

Devido ao ES6, isso funciona apenas no Firefox mais recente.

Obrigado aos apsillers pela dica que reduziu para 200 bytes

Encontre a versão não destruída abaixo como um snippet de pilha que você pode executar aqui:

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

Optimizer
fonte
Você pode usar o prompt + () em vez de parseInt e raspar alguns bytes
Jacob
@ Jacob Esse prompt não é adicionado à contagem de bytes.
Otimizador
OIC. Eu deveria ter lido a pergunta ...
Jacob
@apsillers Obrigado por tonelada! Corrigido o problema e reduzido muito com base na sua dica.
Optimizer
A 2100saída 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-02está incorreta.
Qwertiy
3

Rebol - 120 116 80 79 76

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


Ungolfed + algumas anotações:

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
    ]
]

Exemplo do cálculo de domingo no console 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
draegtun
fonte
Potencial 87: d: 1-1-1 d / ano: fazer impressão de entrada a cobrar [repeat m 12 [d / mês: m + 1 keep d - d / dia útil]]
rgchris
@rgchris Obrigado Chris. Foi capaz de fazer a barba outros 7 caracteres.
draegtun
Agradável!! É ruim, mas nunca pense em FOR como um atalho.
Rogchris # 1
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}/

Isso não usa nenhuma forma de biblioteca de datas. Também pode ser ainda muito jogado, eu acho.

Teste aqui.

Martin Ender
fonte
3
Estou tão espetacularmente entusiasmado que uma resposta CJam não é a melhor resposta em um desafio de código-golfe pela primeira vez. Posso morrer feliz .. Hoje é um dia bom (até que seja golfed até 6 bytes, obviamente)
Brandon
@Brandon: Esse foi o tipo de razão que pensei que seria interessante. Realmente esperando ver uma biblioteca maravilhosa que torne isso fácil, mas decepcionado até agora.
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)))))

Com quebras de linha:

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)))))
plannapus
fonte
1

C # 255

Ungolfed

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

Edit: modificado para imprimir apenas no último domingo :)

bacchusbeale
fonte
Não é o formato de saída necessário. + Este é o código golf
edc65
1

q, 67

{({{1<>x mod 7}-[;1]/x}')14h$1_til[13]+13h$"D"$(($)x),".01.01"}
tmartin
fonte
Não há bibliotecas de datas utilizáveis ​​para isso em q?
Phil H
1

"Oh, não, ele de novo!"

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))+" ");}}

Versão não destruída:

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))+" ");
        }
    }
}

Saída:

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

Ainda outra resposta "vamos colocar uma resposta Java apenas para chutes". Ah bem. Mas, pelo menos, desde que você se preocupou em chegar a esse ponto da minha resposta, tentarei incomodá-lo um pouco mais e explicar meu raciocínio.

O método grecebe o ano desejado e, para cada mês, cria um GregorianCalendarobjeto (os meses vão de 0 a 11). Então, o primeiro c.setdefine o dia da semana como domingo e o segundo declara que queremos a última semana do mês - como visto na documentação oficial . As System.out.printlnimpressões imprimem a data desse domingo (se estivéssemos fazendo isso corretamente, o ano seria impresso como c.get(c.YEAR), mas usando ynovamente os caracteres de 13 caracteres), o mês deverá ser formatado para adicionar um zero inicial de janeiro a setembro (e o o valor é incrementado porque, bem, os meses aqui são representados de 0 a 11) e o dia do último domingo é impresso. E esse procedimento é repetido pelos outros onze meses.

Rodolfo Dias
fonte
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);}}

Com quebras de linha

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

Produção 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"
Darren Breen
fonte
Não é o formato de saída necessário
edc65
Lá, consertado. Melhor?
precisa saber é o seguinte
0

C # 171

Função retornando uma string.

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

Ungolfed

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;
}
edc65
fonte
0

C # 194

usando o 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")));}

Ungolfed

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")));
}

Saída

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
Manuel Schweigert
fonte
0

Mathematica - 171

Embrulhado em uma função anônima, retorna a sequência

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

Primeiro golfe mathematica. Eu sinto que poderia ser substancialmente reduzido.

globby
fonte
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

Poderia ser pior ^^

Minha segunda e última entrada (acho que não posso diminuí-la)

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
dwana
fonte
0

Ruby 76

Usa um parâmetro de linha de comando ruby sundays.rb 1900. Usa a biblioteca de datas.

require'date';puts (1..12).map{|m|d=Date.new($*[0].to_i,m,-1);d-d.wday}*" "
steenslag
fonte