A última segunda-feira


27

Segunda-feira, 31 de outubro, é o Halloween. E isso me fez pensar - eu me pergunto que outros meses o último dia do mês também será uma segunda-feira?

Entrada

  • Um número inteiro positivo em qualquer formato conveniente que represente um ano 10000 > y > 0,.
  • A entrada pode ser preenchida com zeros (por exemplo, 0025para o ano 25), se necessário.

Saída

  • Uma lista dos meses desse ano em que o último dia do mês é uma segunda-feira.
  • Pode ser como nomes de mês (por exemplo, January, March, October) ou nomes abreviados ( Jan, Mar, Oct) ou números ( 1, 3, 10), como linhas separadas ou uma lista ou delimitada etc. etc., desde que não seja ambíguo para o leitor.
  • O formato de saída deve ser consistente:
    • Para todos os anos de entrada (ou seja, não é possível gerar nomes de meses para algumas entradas e números de meses para outras entradas)
    • Bem como consistente por saída (ou seja, não é possível saída 1para Januaryna mesma saída Julpara July)
    • Basicamente, escolha um formato e cumpra-o.

Regras

  • Suponha que o calendário gregoriano para entrada / saída, até y = 1.
  • Os anos bissextos devem ser adequadamente contabilizados (como um lembrete: todos os anos divisíveis por 4, exceto os não divisíveis por 100, a menos que também divisíveis por 400 - 1700, 1800, 1900, todos não foram bissextos, mas 2000 foi).
  • Você pode usar quaisquer ferramentas internas ou outras ferramentas de cálculo de data que desejar.
  • Um programa completo ou uma função são aceitáveis. Se uma função, você pode retornar a saída em vez de imprimi-la.
  • As brechas padrão são proibidas.
  • Isso é portanto todas as regras usuais de golfe se aplicam e o código mais curto (em bytes) vence.

Exemplos

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

Entre os melhores



1
Relacionados, mas não duplicados ou?
— ElPedro 26/10

@ElPedro Relacionado, mas não duplicado. O primeiro não permite nenhum built-in e solicita uma combinação fixa de data / dia (sexta-feira 13), enquanto o segundo solicita o último domingo de cada mês do ano, limitado entre 1900 e 3015.
— AdmBorkBork

Desculpe @TimmD. Meu mal-entendido do seu comentário.
— ElPedro 26/10

1
@ElPedro Sem problemas! Eu preferiria ter uma pergunta e deixar claro, do que não ter uma pergunta e ter algo incerto.
— AdmBorkBork 26/10

Respostas:


2

Dyalog APL com dfns 's cal , Versão 15.0: 22; Versão 16.0: 19 bytes

A função cal vem com uma instalação padrão, basta digitar )copy dfns.

Versão 15.0: ∊⎕{⍵/⍨2=≢⍎⊢⌿cal⍺⍵}¨⍳12

∊ alistar-se (achatar)

⎕{... }¨entrada numérica como argumento esquerdo para a seguinte função anônima, assumindo cada um dos valores do lado direito como argumento direito

 ⍵/⍨ o argumento if (fornece uma lista vazia, se não)

 2= dois (domingo e segunda-feira) é igual a

 ≢ a contagem de

 ⍎ os números em

 ⊢⌿ a linha mais baixa de

 cal o calendário para

 ⍺⍵ ano argumento à esquerda, mês argumento à direita, sendo este último

⍳12 1 a 12

Versão 16.0: ⍸2=⎕{≢⍎⊢⌿cal⍺⍵}¨⍳12

⍸ os índices onde

2= dois iguais (ou seja, domingo e segunda-feira)

⎕{... }¨entrada numérica como argumento esquerdo para a seguinte função anônima, assumindo cada um dos valores do lado direito como argumento direito

 ≢ a contagem de

 ⍎ os números em

 ⊢⌿ a linha mais baixa de

 cal o calendário para

 ⍺⍵ ano argumento à esquerda, mês argumento à direita, sendo este último

⍳12 1 a 12


19

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

Olha ma, não tem embutidos!

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]

Aqui está uma versão 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)

E aqui está a minha tentativa 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]

Explicação

O dia da semana de um determinado ano é calculado da seguinte forma:

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

Em outras palavras:

  • Tome y.
  • Adicione o número do quarto ano anterior y( y>>2).
  • Subtraia o número dos 100 anos antes y( y/100|0).
  • Adicione novamente o número de 400 anos antes y; isso é 1/4 de y/100|0, então usamos *3/4|0.

Em seguida, modulamos o resultado por 7. Se deixarmos 0dizer domingo, 1segunda segunda, etc., o resultado corresponderá ao dia da semana de 31 de dezembro daquele ano. Portanto, para dezembro, queremos verificar se o resultado é 1. Isso nos dá o último caractere na string.

O último dia de novembro é 31 dias antes do último dia de dezembro. Isso significa que para o último dia de novembro ser uma segunda-feira, 31 de dezembro precisa ser uma (1 + 31) % 7 = 4= quinta-feira.

Este procedimento é repetido até voltarmos a março (a 3). Independentemente de haver ou não um dia bissexto, o último dia de fevereiro é 31 dias antes do último dia de março, para que possamos calcular isso também (é (3 + 31) % 7 = 6). A parte complicada é encontrar o valor correto para janeiro:

  • Se for um ano bissexto, o último dia de janeiro será 29 dias antes do último dia de fevereiro, resultando em (6 + 29) % 7 = 0.
  • Caso contrário, serão 28 dias antes do último dia de fevereiro, resultando em (6 + 28) % 7 = 6.

Podemos calcular se é ou não um ano bissexto com o seguinte snippet:

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

Isso indica 0se ynão é um ano bissexto e, se não, um número inteiro positivo. Isso nos leva a

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

para calcular o dia de janeiro. No entanto, podemos fazer melhor revertendo as condições:

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

Como o resultado falso é sempre 0, podemos reduzi-lo para

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

economizando mais um byte precioso.

Juntando tudo, percorremos cada caractere na string, verificando se cada um é igual ao dia da semana de 31 de dezembro. Mantemos os índices dos que correspondem, retornando essa matriz no final. E é assim que você faz cálculos de ano bissexto sem embutidos.


Owww ... Meu cérebro, você contabilizou anos bissextos em tudo isso?
— Magic Octopus Urn

2
@carusocomputing É para isso que !(y%4)*y%100|!(y%400)serve. cada divisível ano a 4, com excepção não anos divisíveis por 100, a menos que também divisível por 400
— mbomb007

Esperamos que y+(y>>2)+(z=y/25>>2)+(z>>2)ainda economize um byte.
— Neil

@ Neil Obrigado, mas eu encontrei uma maneira melhor :-)
— ETHproductions 26/16

Agradável; Salvei 6 bytes na minha porta 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 graças a @ETHproductions. Economizou outro byte, exibindo os meses na ordem inversa.


Eu acho que você pode salvar 2 bytes ao .keys()y=>[for(_ of(m=0,Array(12)))if(new Date(y+400,++m).getDay()==2)m]
— voar

@ETHproductions Posso salvar mais um byte, revertendo o pedido!
— Neil

A ordem inversa está correta. Formatar a saída não é a parte interessante desse desafio.
— AdmBorkBork 27/10

Qual é a nossa política sobre as compreensões de matriz agora que elas foram removidas das especificações?
— MayorMonty 27/10/16

Você pode salvar outros 2 bytes ignorando Array(12)completamente: 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)))

Substitua 2016pelo ano desejado. Corre.

Rev. 2: Usou a help_topicstabela na instalação padrão em vez de criar uma tabela temporária.

Rev.3: Adotou o truque de aross- e percebeu que também posso omitir as aspas de "-1".
No entanto, -1é necessário no MySQL: eu preciso de uma data completa.

Rev.4: A restrição m BETWEEN 1 AND 12pode ser feita como m>0 AND m<13(-6), mas não é necessária - valores inválidos serão ignorados; os avisos serão contados, mas não listados.


Você realmente precisa da tabela shema mysql? mariadb.com/kb/en/mariadb/mysqlhelp_topic-table
— Jörg Hülsermann 27/10

@ JörgHülsermann Não entendi seu ponto.
— Titus

Deve FROM help_topicsem mysql.trabalho? Eu tentei não
— Jörg Hülsermann 28/10

@ JörgHülsermann apenas se você pré-anexar USE mysql;O banco de dados correto deve ser selecionado de alguma forma.
— Titus

5

Perl, 64 bytes

Inclui +1 para -n

Dê entrada no 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

Lote, 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%%

Porto da resposta da @ ETHproduction. Com abreviações de mês 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

Economizou 15 bytes com a ajuda de @ Adám .

Usa o calendário interno para gerar uma matriz de seqüências representando os meses e analisa cada sequência para determinar se a última segunda-feira é o último dia do mês. Ele gera cada mês como o número do mês de cada um. Ou seja, Jan = 0, Feb = 1, ..., Dec = 11.

A saída de calendaré

   _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

Explicação

[: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

espere, o calendário realmente produz arte ASCII?
— Destructible Lemon

@DestructibleWatermelon Para ser exato, o formato de saída calendaré uma matriz de 12 caixas em que cada caixa contém uma matriz 2D de caracteres
— milhas

Eu nem sei como fazer "cada" em J, mas isso já é muito mais curto: I.7=;#&.>".&.>,&.>_2{.&.>calendar 2016se você combinar todos os "sub-abertos", deverá conseguir abreviá-lo.
— Adám 27/10/16

@ Adám Obrigado, ele usa um método melhor, mas não é um verbo em J. Acho que ainda ajudará
— miles

Minha intenção era apenas inspirar. Eu sei que não é um verbo.
— Adám 27/10/16

4

Mathematica, 62 57 bytes

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

Função anônima. Pega um número como entrada e retorna uma lista de listas de números de elemento único como saída. Sinceramente, não tenho mais certeza de como funciona.


4

Perl + cal, 46 bytes

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

Exemplo:

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

2







10


$

1
A rigor, isso é perl + cal, não apenas perl :-p. Por exemplo, minha máquina Windows possui perl, mas isso não funciona lá.
— 26416 philomory

Ponto justo, atualizei essa e minha tentativa do bash.
— steve

4

Java 7,186 182 172 bytes

Obrigado a Kevin por salvar 4 bytes
Obrigado a @cliffroot por salvar 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;}

destroçado

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 versão é fornecida 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;   }
    }

amostra de saída

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

1
Depois que eu escrevi a minha resposta eu sabia calcular tudo sozinho seria mais curto .. :) Btw, você pode golfe n%4==0para n%4<1; n%400==0para n%400<1e int c=...;int[]b=...,a=...para int c=...,b[]=...,a[]=....
— Kevin Cruijssen 27/10

1
be apode ser definido na intparte assim: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;}poucos bytes salvos
— cliffroot 27/10

1
Também é possível alterar ba b[]={3,(n%4<1&n%100>0)|n%400<1?1:0,3,2,3,2,3,3,2,3,2,3}e i+30a i+28para mais 2 bytes
— cliffroot

1
e mais 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 27/10

3

Python 2, 100 bytes

Ugh. Matemática com datas não é tão simples quanto eu gostaria.

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]

Experimente online

Mesmo comprimento:

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]

Eu nem tentaria Python com este. Bom esforço.
— ElPedro 26/10

3

MATL , 21 bytes

12:"G@QhO6(YO9XO77=?@

Os meses são exibidos como números.

Experimente online! Ou verifique todos os casos de teste .

Explicação

Isso usa funções internas de conversão de data. Para o ano determinado, ele testa quais os últimos dias do mês é segunda-feira.

Em vez de especificar explicitamente o último dia do mês k(que pode ser 28, 29, 30 ou 31), especificamos o 0-ésimo dia do mês k+1, que é equivalente e não depende do mês ou do ano.

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

Utilitários Bash + GNU, 56 bytes

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

Parece exigir a dateversão 8.25. A versão 8.23 ​​do Ideone não funciona.


3

Excel, 537 bytes

Porque - você sabe - Excel!

Recebe o ano de entrada em A1. Retorna a lista hexadecimal de meses; 1 = janeiro, C = dezembro. Como cada mês é um dígito, não é necessário 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","")

Exemplo: A1 contém 2016. B1 contém a fórmula acima e é exibida como 2A, significando fevereiro e outubro.


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,";
  • Produz o ano fornecido, nem todos (... sempre lê a pergunta)
  • Avisos ignorados (obrigado Titus)
  • Mude whilepara forcomo agora é um ano (mais uma vez, obrigado Titus)

2 velhos

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

Suporta todos os anos, do ponto ao 10000, também se livrou de um aviso indefinido de var que eu não conhecia em um PC. Sim, é mais longo que a versão antiga, mas é mais robusta.

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

Se estiver rodando no Windows ou em um sistema de 32 bits, haverá o temido bug de 2038, mas em um sistema Linux de 64 bits, tudo bem.

Tentei usar o date("t"...que deve representar a última data do mês especificado, mas os resultados não coincidem com os mencionados anteriormente neste tópico.


2
-2: "$ z" não precisa de aspas -7: ignora os avisos (eles não são impressos com as configurações padrão: não iniciam $z, sem aspas para N) -1: em forvez de while -43 : recebe a entrada conforme solicitado em vez de repetir os anos -3: em joinvez de implode-16: saída direta: 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 se você insistir em não ter vírgula à direita:echo$o=$o?",$m":$m;
— Titus

Ahh interpretou mal a pergunta! Pensei que era para todos os anos .. oops: B Obrigado pelas outras sugestões também, as seguirá
— CT14.IT 27/10/16

3

PHP, 92 bytes

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

verificar 12 vezes 1 mês após o primeiro dia do ano é terça-feira Se for, então é o dia anterior ao último dia do mês é uma segunda-feira.


Você poderia usar eco em vez de imprimir e salvar 1
— Octopus

1
@ Octopus não está dentro do operador ternário
— Jörg Hülsermann 28/10

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

Ungolfed

Com créditos para os gurus relevantes.

Michael Keith e Tom Craver, do Programa C, para encontrar o dia da semana com data .

Collin Biedenkapp para perguntas e respostas: Como faço para descobrir qual é o último dia do mês?

/* 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
E se você virar ifa outra direção, para ter o seu elseretorno 31e, portanto, puder eliminar a grande ==cadeia?
— AdmBorkBork 27/10

1
seria melhor se (x == 1) {z part} else if (x == 3 || x == 5 || x == 8 || x == 10) retorne 30 else retorne 31
— RosLuP

1
que tal: retornar 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: obrigado pelos pontos de retorno (), 100 bytes agora salvos.
— Steve #

1
é possível continuar reduzindo até que: u (y, m) {retorne m-1? 30 + ((2773 >> m) & 1): 28+ (y% 4 == 0 && y% 100 || y% 400 == 0);} onde y é o ano e o mês
— RosLuP 28/10

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

Isso usa uma tabela que contém o deslocamento dos dias da semana do último dia de cada mês para um ano bissexto, codificado em uma palavra de 32 bits assinada usando a base 7. Se não for um ano bissexto, adicionamos 1 ao deslocamento de janeiro (como você pode ver, y&3||y%25<1&&y&15é usado para verificar anos sem dias bissextos). Simplesmente percorremos todos os meses e verificamos se o último dia é segunda-feira. Muito simples, na verdade, sem truques ou truques feios. Aqui está um pouco não-destruído:

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

Eu poderia revisitar isso para reescrevê-lo como uma função para salvar alguns caracteres. O printftambém ocupa um pouco de espaço demais ...


O printf ( "% d", m) iria imprimir algo como 1, ou 2, 3, por isso há sempre um '' mais ... Eu prefiro uso somente espaços
— RosLuP

Na verdade, eu também prefiro espaços na saída, mas geralmente escrevo minhas soluções C golfadas para que elas não precisem de espaço em branco, para que eu possa usar apenas o espaço em branco da versão semi-golfada quando quiser verificar minha contagem de caracteres .
— Fors

3

PHP, 96 95 76 71 69 64 61 bytes

Nota: os números do ano devem ser preenchidos com 4 caracteres, como 0070.

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

Execute assim:

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

Explicação

Repete de -1 a -12. Crie a data usando mktime, dia 0(o último dia do mês anterior) e mês 2..13. Formate a data como número do dia e, se o resultado for 1, imprima o número atual. O sinal negativo -é usado como delimitador.

O bug do milênio ataca novamente!

Observe que, com esta versão, o intervalo 0..100é interpretado como 1970..2069. Isso não é problema para o intervalo 0..69, pois as semanas têm um padrão que se repete a cada 400 anos (146097 dias, exatamente 20871 semanas), mas para o intervalo 70..99, 1900 é adicionado ao número do ano, que não é múltiplo de 400. Para corrigir esse problema APENAS para números de 30 anos em um intervalo de 10k, a maneira mais simples é adicionar 400 ao número do ano para impedir a interpretação de 2 dígitos ( +4 bytes ):

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

Tweaks

  • Salva um byte usando !~-$ipara comparar $icom 1( -1binário é negado 0, é logicamente negado é true; todos os outros números são false), portanto, parênteses não são necessários
  • Economizou 19 bytes usando a last day ofYYYY-mnotação para criar a data
  • Salva 5 bytes usando datee em strtotimevez dedate_create
  • Salva 2 bytes contando a partir de números negativos, usando o sinal negativo como delimitador de saída (os números negativos do mês não existem) e também como delimitador na YYYY-mparte da data
  • Salva 5 bytes usando em mktimevez de strtotime. Revertida para usar o dia 0( mktimetambém suporta o mês 13, então 0-13== 31-12)
  • Salva 3 bytes usando -Rpara $argndisponibilizar

mktimeelimina a necessidade de preencher o ano, não é?
— Titus

@ Titus, afiado. Bem, acabei de descobrir que mktimeé contra-intuitivo , porque os argumentos são tomados como INTs. Isso significa que você não pode completar o ano ... então tudo no intervalo 0..100é interpretado como 1970..2070. Isso não é problema para o intervalo, 0..70porque 400 anos têm um número exato de semanas (portanto, os calendários repetem o padrão a cada 400 anos), mas 70..99adicionam 1900 (não um múltiplo de 400!). Portanto, nova versão. tem um bug.
— aross 28/10/16

A única solução que vejo para isso agora é $argv[1]+400... a menos que os dias da semana juliano e gregoriano sejam diferentes.
— Titus

@ Titus, sim. As regras dizem usar cal Gregoriano
— aross

3

Excel, 428 97 96 bytes

Entrada em A1. Valores hexadecimais não separados de saída (janeiro = 0, dezembro = B)

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

Adicionados 10 bytes ("+2000") para permitir o tratamento de datas anteriores a 1990.

Economizou 11 bytes graças a @ Engineer Toast .


Primeira tentativa (428 bytes), emprestando fortemente a solução 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","")

Como isso funciona anos antes de 1900? O caso de teste 297 -> Mayretorna 6com esta fórmula. Não deveria ser 4? 1776dá em 7Avez de apenas 8para setembro.
— Engineer Toast

Se você obtê-lo para o trabalho, no entanto, provavelmente você pode usar Date(A1,3,0)em vez deEOMONTH(DATE(A1,2,1),0)
— Engenheiro 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 exemplo, OSX), mas observe os espaços à direita no GNU cal.
— Digital Trauma

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

Uma função sem nome, leva um ano inteiro, gera uma lista dos números do mês [1-12].

Também tentei superar a contagem de bytes com aritmética sem ê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)

Uma função sem nome que retorna uma lista de valores booleanos que representam se os meses [Jan-Dec] terminam em uma segunda-feira


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

Em Java, GregorianCalendaré uma mistura entre um calendário gregoriano e juliano. Por esse motivo, o ano 1deu resultados incorretos. Alterar Calendar c=Calendar.getInstance();para GregorianCalendar c=new GregorianCalendar();c.setGregorianChange(new Date(1L<<63));corrigir isso, forçando o uso apenas do calendário gregoriano. Obrigado a @ JonSkeet no stackoverflow.com por me explicar isso.

Ungolfed & código de teste:

Experimente aqui.

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

Saída:

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 graças a Shebang

Imprima meses como números; com espaço delimitado; com espaço à direita. Agora, esta resposta também funciona para versões anteriores do C #.


Antigo, 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 graças a TimmyD

Os meses de saída são números na sequência de retorno, delimitados por vírgulas

Ungolfed

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 Sim, mas precisa de elenco explícito. Resposta atualizada
— Link Ng

LINQ é divertido, mas este é de 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);}}};) Além disso, seria mais curto para lançar o DayOfWeekque intdo que seria para lançar o intparaDayOfWeek
— Kade

@Shebang Obrigado. Eu realmente não deveria jogar golfe em uma linha linq --- Somente Jon Skeet pode fazer isso. Veja se tenho tempo para atualizar amanhã. Cansado agora.
— Link Ng

Você pode converter este seja um Action<int>para salvar alguns 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 para -rdatena linha de comando para obter a classe Date da biblioteca padrão.

Explicação: muito simples, graças à excelente Dateclasse do Ruby stdlib . Não apenas possui métodos como monday?, tuesday?etc, o construtor terá números negativos para qualquer campo do ano passado para significar 'conte esse campo de trás para frente a partir do final do período representado pelo campo anterior'. $*é uma abreviação de ARGV, então $*[0]é uma maneira rápida de obter o primeiro argumento de linha de comando.


2

PHP, 84 bytes

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

Meu primeiro código de golfe. Este é o PHP mais curto até agora nesta questão.

Edição: parece não funcionar para o ano 1. Vou ter que descobrir o porquê, mas agora eu tenho que ir.


1
Eu diria "Bem-vindo ao PPCG!" mas você está registrado aqui há mais tempo do que eu! : D Bom primeiro golfe.
— AdmBorkBork 27/10

Seu erro é que você cria 1-13-1 e 1-14-1 para o ano 1 <13 é suficiente. Se você resolver isso, você pode remover os suportes unnessary no momento e pensar em usar o operador ternário
— Jörg Hülsermann

Isso deve fixo seus 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)

A sequência dos últimos dias de cada mês é dada por seq(as.Date(paste0(x,-2,-1)),,'m',12)-1:

  • paste0força -2 e -1 a caracteres. Se a xera 2016, por exemplo, paste0(x,-2,-1)dá "2016-2-1", que é então convertido para o 01 de fevereiro de 2016 por as.Date.

  • seqaplicado a um objeto POSIXct ou Date é seq(from, to , by, length.out): aqui tonão é fornecido, byé fornecido como 'm'correspondido 'month'graças à correspondência parcial e, length.outé claro , é 12.

  • A sequência resultante é o primeiro dia dos 12 meses a partir de fevereiro do ano em questão. -1nos dá o último dia dos 12 meses a partir de janeiro do ano em questão.

Casos de teste:

> 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

Versão antiga em 95 bytes, exibindo os nomes dos meses em vez de apenas seus números:

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

Esta resposta é simplesmente brilhante. Eu não tinha idéia de sequm método para Date-objects e isso resolve o problema de as.Datenão tratar anos acima 10000na minha resposta excluída.
— Billywob

@ Billywob sim seq.Datee seq.POSIXtsão bastante impressionantes: eles podem até processar comandos como seq(time1, time2, by="10 min")ou seq(date1, date2, by="quarter"). Muito útil ao plotar uma série temporal.
— plannapus

2

Japt, 24 bytes

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

Teste online! Gera uma matriz de números,falseno lugar de meses que não terminam na segunda-feira.

Houve um erro no intérprete que não me permitiu usar Ðno corpo da função £. Após a correção do bug e outra adição de recurso, são 18 bytes no commit atual:

Do1@Ð400+UX e ¥2©X

1

Java, 143 129 bytes

Isso usa a nova API de horário do 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;}

Saída

Observe que cada linha tem um espaço extra no final.

4 12 
5 
9 
1 7 
2 10 
1 2 10 

Ungolfed and testing

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

Barbear

  1. 143 a 129 bytes: use DayOfWeek::ordinalpara comparar com uma constante numérica em vez da constante enum.
    Obrigado @ TimmyD pela idéia geral, se não a solução exata! ;-)

@ TimmyD, infelizmente, é um enum. getValue()Porém, ele possui um método que salvaria alguns bytes.
— Celos

O @Celos ordinal()economiza mais 1 byte em comparação com getValue(), mesmo que seja sugerido que nunca o use.
— Olivier Grégoire

sim, bom pensamento. Publiquei meu comentário sem primeiro atualizar, para não ver sua resposta e edição.
— 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}}}

Exemplo

$ gawk '{for(;m<13;a=mktime($0" "++m" 1 9 0 0")){if(strftime("%w",a-8e4)~1){print m-1}}}' <<<2016
2
10
$
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.