A simetria dos meses

32

Introdução

Alguns meses são completamente simétrica , ou seja, eles têm simetria central, bem como simetria de reflexão , como February of 2010:

     February 2010
┌──┬──┬──┬──┬──┬──┬──┐ 
│  │  │  │  │  │  │  │ 
├──┼──┼──┼──┼──┼──┼──┤ 
│  │  │  │  │  │  │  │ 
├──┼──┼──┼──┼──┼──┼──┤ 
│  │  │  │  │  │  │  │ 
├──┼──┼──┼──┼──┼──┼──┤ 
│  │  │  │  │  │  │  │ 
└──┴──┴──┴──┴──┴──┴──┘ 

Alguns meses têm apenas simetria central, como no February of 1996mês atual, o April of 2018:

      February 1996
          ┌──┬──┬──┬──┐
          │  │  │  │  │
 ┌──┬──┬──┼──┼──┼──┼──┤
 │  │  │  │  │  │  │  │
 ├──┼──┼──┼──┼──┼──┼──┤
 │  │  │  │  │  │  │  │
 ├──┼──┼──┼──┼──┼──┼──┤
 │  │  │  │  │  │  │  │
 ├──┼──┼──┼──┼──┴──┴──┘
 │  │  │  │  │
 └──┴──┴──┴──┘

       April 2018  ┌──┐
                   │  │
 ┌──┬──┬──┬──┬──┬──┼──┤
 │  │  │  │  │  │  │  │
 ├──┼──┼──┼──┼──┼──┼──┤
 │  │  │  │  │  │  │  │
 ├──┼──┼──┼──┼──┼──┼──┤
 │  │  │  │  │  │  │  │
 ├──┼──┼──┼──┼──┼──┼──┤
 │  │  │  │  │  │  │  │
 ├──┼──┴──┴──┴──┴──┴──┘
 │  │
 └──┘

E alguns são assimétricos , como no mês anterior, o March of 2018:

      March 2018
         ┌──┬──┬──┬──┐
         │  │  │  │  │
┌──┬──┬──┼──┼──┼──┼──┤
│  │  │  │  │  │  │  │
├──┼──┼──┼──┼──┼──┼──┤
│  │  │  │  │  │  │  │
├──┼──┼──┼──┼──┼──┼──┤
│  │  │  │  │  │  │  │
├──┼──┼──┼──┼──┼──┼──┘
│  │  │  │  │  │  │
└──┴──┴──┴──┴──┴──┘

Tarefa

Tome uma entrada na forma de uma data , por exemplo:

  • 2018.04
  • 2018.03
  • 2010.02
  • 1996.02

Emita a simetria correspondente , por exemplo

  • 2018.04 -> centrally symmetric
  • 2018.03 -> asymmetric
  • 2010.02 -> symmetric
  • 1996.02 -> centrally symmetric

Regras

  • Isso é código de golfe, então o menor número de bytes vence.
  • As brechas padrão obviamente não são permitidas.
  • Suponha que a semana comece com segunda - feira (obrigado a Angs e Arnauld pela sugestão).
  • Considere apenas anos entre 1900 e 2100 ( inclusive ).
  • As regras de formatação de entrada e saída são permissivas , o que significa que você pode usar qualquer formato equivalente nativo ao idioma de sua escolha.
  • Baseie sua solução no calendário gregoriano .
mkierc
fonte
7
Considere-se que datas são estranho , você pode querer especificar exatamente as regras, ou limitar a entrada possível um pequeno intervalo (por exemplo, 1901-2099)
user202729
2
O que evitar ao escrever desafios / Adicionar itens desnecessários inclui "Como calcular as respostas f(x)para todos os itens dax lista". Que tal "receber uma entrada na forma de uma data"?
precisa saber é o seguinte
6
Bem-vindo ao PPCG e bom primeiro desafio! Embora esse desafio seja bom, no futuro, se você quiser algum feedback sobre o desafio antes de postá-lo, poderá publicá-lo na sandbox .
precisa saber é o seguinte
2
A saída deve ser estritamente as seqüências mencionadas, ou quaisquer 3 valores distintos?
Uriel
2
(espere um minuto, calendário gregoriano ou calendário Juliano sugeri [1901-2099], mas você decidir usar [1900-2100] por isso eles são diferentes para alguns insumos?)
user202729

Respostas:

20

JavaScript (ES6), 55 bytes

Guardado 6 bytes graças a @Neil

Recebe entrada na sintaxe de currying (year)(month). Retorna falsepara assimétrico, truepara simétrico central e 0para completamente simétrico.

y=>m=>(n=(g=_=>new Date(y,m--,7).getDay())()+g())&&n==7

Experimente online!

Quão?

Definimos a função g () que retorna o dia da semana de aaaa / mm / 01 , como um número inteiro entre 0 = segunda-feira e 6 = domingo.

g = _ => new Date(y, m--, 7).getDay()

Como getDay () retorna nativamente 0 = domingo a 6 = sábado, mudamos o resultado para o intervalo esperado consultando o sétimo dia.

Então definimos:

n = g() + g()

Como o construtor de Date espera um mês indexado em 0 e porque g () diminui m depois de passá-lo para Date , na verdade, primeiro calculamos o dia da semana do primeiro dia do mês seguinte e, em seguida, adicionamos o atual.

Meses completamente simétricos

Os meses completamente simétricos começam com uma segunda-feira e são seguidos por um mês que também começa com uma segunda-feira. Isso só é possível para fevereiro de um ano sem salto.

- Feb --------------    - Mar --------------
Mo Tu We Th Fr Sa Su    Mo Tu We Th Fr Sa Su
--------------------    --------------------
01 02 03 04 05 06 07    01 02 03 04 05 06 07
08 09 10 11 12 13 14    08 09 10 11 12 13 14
15 16 17 18 19 20 21    15 16 17 18 19 20 21
22 23 24 25 26 27 28    22 23 24 25 26 27 28
                        29 30 31

Isso leva a n = 0 .

Meses centralmente simétricos

Meses centralmente simétricos são aqueles cuja soma do dia da semana do primeiro dia e do mês seguinte é 7 .

- M ----------------    - M+1 --------------
Mo Tu We Th Fr Sa Su    Mo Tu We Th Fr Sa Su
--------------------    --------------------
 0  1 [2] 3  4  5  6     0  1  2  3  4 [5] 6
--------------------    --------------------
      01 02 03 04 05                   01 02
06 07 08 09 10 11 12    03 04 05 06 07 07 09
13 14 15 16 17 18 19    ...
20 21 22 23 24 25 26
27 28 29 30 31

Daí o segundo teste: n == 7 .


Nenhum built-in, 93 bytes

Usa a congruência de Zeller . Mesmo formato de E / S da outra versão.

y=>m=>(n=(g=_=>(Y=y,((m+(m++>2||Y--&&13))*2.6|0)+Y+(Y>>2)-6*~(Y/=100)+(Y>>2))%7)()+g())&&n==7

Experimente online!

Arnauld
fonte
Eu pensei que era true, falsee em filenotfoundvez de 0...
Angs 01/04/19
g=m=>new Date(y,m,7).getDay()economiza 6 bytes.
Neil
7

T-SQL , 213 bytes (regras estritas de E / S)

SET DATEFIRST 1SELECT CASE WHEN a+b<>8THEN'a'WHEN a=1THEN''ELSE'centrally 'END+'symetric'FROM(SELECT DATEPART(DW,f)a,DATEPART(DW,DATEADD(M,1,f)-1)b FROM (SELECT CONVERT(DATETIME,REPLACE(s,'.','')+'01')f FROM t)y)x

A consulta acima considera as rígidas regras de formatação de entrada / saída.

A entrada é obtida da coluna sde uma tabela denominada t:

CREATE TABLE t (s CHAR(7))
INSERT INTO t VALUES ('2018.04'),('2018.03'),('2010.02'),('1996.02')

Ungolfed:

SET DATEFIRST 1
SELECT *, CASE WHEN a+b<>8 THEN 'a' WHEN a=1 AND b=7 THEN '' ELSE 'centrally ' END+'symetric'
FROM (
    SELECT *,DATEPART(WEEKDAY,f) a, 
        DATEPART(WEEKDAY,DATEADD(MONTH,1,f)-1) b 
    FROM (SELECT *,CONVERT(DATETIME,REPLACE(s,'.','')+'01')f FROM t)y
) x

SQLFiddle 1

T-SQL , 128 bytes (regras de E / S permissivas)

SET DATEFIRST 1SELECT CASE WHEN a+b<>8THEN 1WHEN a=1THEN\END FROM(SELECT DATEPART(DW,d)a,DATEPART(DW,DATEADD(M,1,d)-1)b FROM t)x

Se o formato da entrada e da saída puder ser alterado, eu escolheria inserir o primeiro dia do mês, em uma datetimecoluna chamada d:

CREATE TABLE t (d DATETIME)
INSERT INTO t VALUES ('20180401'),('20180301'),('20100201'),('19960201')

A saída seria 1 para assimétrico, 0 para simétrico, NULL para simétrico central.

Se pudermos executá-lo em um servidor (ou com um login) configurado para o idioma BRITISH, poderemos remover SET DATEFIRST 1economizando mais 15 bytes.

SQLFiddle 2

Razvan Socol
fonte
11
Bom trabalho. Não tenho certeza se funcionará em todas as versões, mas no SQL 2012 pude salvar 15 bytes usando em CONVERT(DATETIME,s+'.01')vez de REPLACE. Você também pode deixar o espaço emFROM (SELECT
BradC
11
Funciona, mas depende da DATEFORMATconfiguração. Por exemplo, se usarmos SET LANGUAGE BRITISH, CONVERT(DATETIME,'2018.02.01')seria 2 de janeiro, em vez de 1º de fevereiro.
Razvan Socol
5

Haskell, 170 bytes

import Data.Time.Calendar
import Data.Time.Calendar.WeekDate
a%b=((\(_,_,a)->a).toWeekDate.fromGregorian a b$1)!gregorianMonthLength a b
1!28=2
4!29=1
7!30=1
3!31=1
_!_=0

Retorna 2 para simétrico central, 1 para simétrico e 0 para assimétrico

Angs
fonte
@TuukkaX Desculpe pela confusão - este é o meu primeiro desafio, eu mudei as regras para que eles também permitam formatos de saída permissivos, para que fique mais "em espírito" do código-golfe.
Mkierc #
5

Python 2, 118 104 bytes

Obrigado a Jonathan Allan e Dead Possum pelas melhorias!

from calendar import*
def f(*d):_=monthcalendar(*d);print all(sum(_,[]))+(_[0].count(0)==_[-1].count(0))

Python 3, 122 105 bytes

from calendar import*
def f(*d):_=monthcalendar(*d);print(all(sum(_,[]))+(_[0].count(0)==_[-1].count(0)))

Entrada

  • Primeiro é o ano
  • Segundo é o mês


Saída

  • 0 = sem simetria
  • 1 = simetria central
  • 2 = simetria completa
Valete de espadas
fonte
3
Bem vindo ao site! Você não pode assumir que a entrada está armazenada em uma variável (como You M), portanto, atualmente, é um trecho e é inválido. Se você alterar as variáveis ​​para chamadas, no input()entanto, isso será perfeitamente correto.
caird coinheringaahing
11
@cairdcoinheringaahing Obrigado pela recepção! Entrada do usuário fixa :)
Jack of all Spades
Bem vinda! Ajustes para -9 bytes aqui - tudo importação, entrada descompactado, _[0]+_[-1]->sum(..)
Morto Possum
11
Alguns truques para obtê-lo abaixo de 13 bytes aqui
Jonathan Allan
11
... e outro byte usando truque soma Dead Possum - aqui
Jonathan Allan
4

Vermelho , 199, 168 161 bytes

func[d][t: split d"."y: do t/1 m: do t/2 a: to-date[1 m y]b: a + 31
b/day: 1 b: b - 1 if(1 = s: a/weekday)and(7 = e: b/weekday)[return 1]if 8 - e = s[return 2]0]

Experimente online!

0 - assimétrico

1 - simétrico

2 - simétrica centralmente

Mais legível:

f: func[d][                  ; Takes the input as a string
    t: split d "."           ; splits the string at '.'
    y: do t/1                ; stores the year in y 
    m: do t/2                ; stores the month in m
    a: to-date[1 m y]        ; set date a to the first day of the month
    b: a + 31                ; set date b in the next month  
    b/day: 1                 ; and set the day to 1st
    b: b - 1                 ; find the end day of the month starting on a
    s: a/weekday             ; find the day of the week of a 
    e: b/weekday             ; find the day of the week of b
    if(s = 1) and (e = 7)    ; if the month starts at Monday and ends on Sunday
        [return 1]           ; return 1 fo symmetric
    if 8 - e = s             ; if the month starts and ends on the same day of the week
        [return 2]           ; return 2 for centrally symmetric  
    0                        ; else return 0 for assymetric
]
Galen Ivanov
fonte
2

Mathematica, 137 bytes

a=#~DateValue~"DayName"&;b=a/@{2}~DateRange~{3};Which[{##}=={0,6},1,+##>5,0,1>0,-1]&@@(Position[b,a@#][[1,1]]~Mod~7&)/@{{##},{#,#2+1,0}}&

Função pura. Toma o ano e o mês como entrada e retorno -1por meses assimétricos, 0por meses centralmente simétricos e 1por meses totalmente simétricos. Não sei por que esse idioma não pode converter de um dia da semana para um número por padrão ...

LegionMammal978
fonte
2

Utilitários Bash + GNU, 70

date -f- +%u<<<"$1/1+1month-1day
$1/1"|dc -e??sad8*la-55-rla+8-d*64*+p

A entrada está formatada como YYYY/MM.

A saída é numérica, da seguinte maneira:

  • menor que 0: simétrico central
  • exatamente 0: simétrico
  • maior que 0: assimétrico

Presumo que este formato de saída seja aceitável para esta pergunta.

Experimente online!

Trauma Digital
fonte
1

C, 111 bytes

a;g(y,m){y-=a=m<3;return(y/100*21/4+y%100*5/4+(13*m+16*a+8)/5)%7;}f(y,m){a=g(y,m)+g(y,m+1);return(a>0)+(a==7);}

Invoque f(year, month), 0 para completamente simétrico, 1 para assimétrico, 2 para simétrico central.

tsh
fonte
IIRC, você pode abusar do UB no GCC substituindo returnpor y=(o primeiro parâmetro) e caindo fora da função.
Quentin
1

Perl 6 , 74 bytes

{{{$_==30??2!!$_%7==2}(2*.day-of-week+.days-in-month)}(Date.new("$_-01"))}

Bloco vazio, implicitamente uma função de 1 argumento, uma string semelhante "2012-02". Devoluções:

2     # Fully symmetric
True  # Centrally symmetric
False # Asymmetric

Quando o padrão é simétrico, à medida que .dia da semana aumenta em 1, .days-in-month precisaria mover 2 para continuar a corresponder (o mês começaria um dia depois, mas precisaria terminar um dia antes ), 2 * .day-of-week + .days-in-monthnos fornece uma medida dessa lacuna. No módulo 7, deve ser 1 para obter simetria, mas podemos primeiro verificar o fevereiro sem pulos a um preço baixo, verificando o total antes do módulo (segunda-feira e 28 dias por mês é a combinação mínima possível).

Estou surpreso que isso consiga tantos bytes, mas são necessários 36 bytes apenas para marcar uma data e obter o dia da semana e os dias desse mês.

Phil H
fonte