La simetría de meses

32

Introducción

Algunos meses son completamente simétrica , lo que significa que tienen simetría central , así como simetría de reflexión , como February of 2010:

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

Algunos meses solo tienen simetría central, como February of 1996o mes actual, el April of 2018:

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

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

Y algunos son asimétricos , como el mes anterior, el March of 2018:

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

Tarea

Tome una entrada en forma de fecha , por ejemplo:

  • 2018.04
  • 2018.03
  • 2010.02
  • 1996.02

Salida de la simetría correspondiente , p. Ej.

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

Reglas

  • Este es el código de golf, por lo que gana el menor número de bytes.
  • Las lagunas estándar obviamente no están permitidas.
  • Suponga que la semana comienza con el lunes (gracias a Angs y Arnauld por su sugerencia).
  • Considere solo años entre 1900 y 2100 ( inclusive ).
  • Las reglas de formato de entrada y salida son permisivas , lo que significa que puede usar cualquier formato equivalente que sea nativo del idioma que elija.
  • Base su solución en el calendario gregoriano .
mkierc
fuente
77
Tenga en cuenta que las fechas son extrañas , es posible que desee especificar exactamente las reglas o limitar la entrada posible a un rango pequeño (por ejemplo, 1901-2099)
usuario202729
2
Cosas que debe evitar al escribir desafíos / Agregar cosas innecesariamente incluye "Hacer que las respuestas se calculen f(x)para cada xen una lista". ¿Qué pasa con "tomar una entrada en forma de fecha"?
user202729
66
¡Bienvenido a PPCG, y buen primer desafío! Aunque este desafío es bueno, en el futuro si desea recibir comentarios sobre el desafío antes de publicarlo, puede publicarlo en el sandbox .
user202729
2
¿Debería la salida ser estrictamente las cadenas mencionadas o 3 valores distintos?
Uriel
2
(espere un minuto, ¿calendario gregoriano o calendario juliano? Sugerí [1901-2099] pero usted decide usar [1900-2100] para que sean diferentes para algunas entradas)
user202729

Respuestas:

20

JavaScript (ES6), 55 bytes

Guardado 6 bytes gracias a @Neil

Toma entrada en la sintaxis de curry (year)(month). Devuelve falsepara asimétrico, truepara centralmente simétrico y 0para completamente simétrico.

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

Pruébalo en línea!

¿Cómo?

Definimos la función g () que devuelve el día de la semana de aaaa / mm / 01 , como un entero entre 0 = lunes y 6 = domingo.

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

Porque getDay () devuelve de forma nativa 0 = domingo a 6 = sábado, cambiamos el resultado al rango esperado al consultar el séptimo día.

Luego definimos:

n = g() + g()

Porque el constructor de Date espera un mes indexado en 0 y porque g () disminuye m después de pasarlo a Date , en realidad primero calculamos el día de la semana del primer día del mes siguiente y luego agregamos el del día actual.

Meses completamente simétricos

Los meses completamente simétricos comienzan con un lunes y son seguidos por un mes que también comienza con un lunes. Esto solo es posible para febrero de un año no bisiesto.

- 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

Esto lleva a n = 0 .

Meses centralmente simétricos

Los meses centralmente simétricos son meses para los cuales la suma del día de la semana de su primer día y la del mes siguiente es 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

De ahí la segunda prueba: n == 7 .


No incorporado, 93 bytes

Utiliza la congruencia de Zeller . Mismo formato de E / S que la otra versión.

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

Pruébalo en línea!

Arnauld
fuente
Pensé que era true, falsey en filenotfoundlugar de 0...
Angs
g=m=>new Date(y,m,7).getDay()ahorra 6 bytes.
Neil
7

T-SQL , 213 bytes (reglas estrictas 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

La consulta anterior considera las estrictas reglas de formato de entrada / salida.

La entrada se toma de la columna sde una tabla llamada t:

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

Sin golf:

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 (reglas de E / S permisivas)

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

Si se puede cambiar el formato de la entrada y de la salida, elegiría ingresar el primer día del mes, en una datetimecolumna llamada d:

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

El resultado sería 1 para asimétrico, 0 para simétrico, NULL para centralmente simétrico.

Si podemos ejecutarlo en un servidor (o con un inicio de sesión) configurado para el idioma BRITÁNICO, podemos eliminar el SET DATEFIRST 1ahorro de 15 bytes más.

SQLFiddle 2

Razvan Socol
fuente
1
Buen trabajo. No estoy seguro de si funcionará en todas las versiones, pero en SQL 2012 pude guardar 15 bytes usando en CONVERT(DATETIME,s+'.01')lugar de REPLACE. También puede colocar el espacio enFROM (SELECT
BradC
1
Funciona, pero depende de la DATEFORMATconfiguración. Por ejemplo, si usamos SET LANGUAGE BRITISH, CONVERT(DATETIME,'2018.02.01')sería el 2 de enero, en lugar del 1 de febrero.
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

Devuelve 2 para centralmente simétrico, 1 para simétrico y 0 para asimétrico

Angs
fuente
@TuukkaX Perdón por la confusión: este es mi primer desafío, he cambiado las reglas para que también permitan formatos de salida permisivos para que pueda ser más "en espíritu" del código de golf.
mkierc 01 de
5

Python 2, 118104 bytes

¡Gracias a Jonathan Allan y Dead Possum por las mejoras!

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

Python 3, 122105 bytes

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

Entrada

  • Primero es el año
  • El segundo es el mes


Salida

  • 0 = sin simetría
  • 1 = simetría central
  • 2 = simetría completa
Jack de todas las espadas
fuente
3
Bienvenido al sitio! No puede suponer que la entrada se almacena en una variable (como Yo M), por lo que actualmente es un fragmento e inválido. input()Sin embargo, si cambia las variables a llamadas , esto estará perfectamente bien.
caird coinheringaahing
1
@cairdcoinheringaahing ¡Gracias por la bienvenida! Entrada fija del usuario :)
Jack of all Spades
¡Bienvenido! Ajustes para -9 bytes aquí : todas las importaciones, entradas desempaquetadas, _[0]+_[-1]->sum(..)
Dead Possum
1
Algunos trucos para bajarlo 13 bytes aquí
Jonathan Allan
1
... y otro byte usando el truco de suma de Dead Possum - aquí
Jonathan Allan
4

Rojo , 199, 168161 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]

Pruébalo en línea!

0 - asimétrico

1 - simétrico

2 - centralmente simétrica

Más legible:

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
fuente
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}}&

Pura función. Toma el año y el mes como entrada y retornos -1para meses asimétricos, 0para meses simétricos centralmente y 1para meses completamente simétricos. No estoy seguro de por qué este idioma no puede convertir de un día de la semana a un número de forma predeterminada ...

LegionMammal978
fuente
2

Bash + utilidades GNU, 70

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

La entrada está formateada como YYYY/MM.

La salida es numérica, como sigue:

  • menor que 0: centralmente simétrico
  • exactamente 0: simétrico
  • mayor que 0: asimétrico

Supongo que este formato de salida es aceptable para esta pregunta.

Pruébalo en línea!

Trauma digital
fuente
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 asimétrico, 2 para centralmente simétrico.

tsh
fuente
IIRC puede abusar de UB en GCC reemplazando returncon y=(el primer parámetro) y cayendo de la función.
Quentin
1

Perl 6 , 74 bytes

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

Bloque desnudo, implícitamente una función de 1 argumento, una cadena como "2012-02" . Devoluciones:

2     # Fully symmetric
True  # Centrally symmetric
False # Asymmetric

Cuando el patrón es simétrico, a medida que .day-of-week aumenta en 1, .days-in-month necesitaría moverse en 2 para seguir coincidiendo (el mes comenzaría un día más tarde pero debería terminar un día antes ), asi que 2 * .day-of-week + .days-in-month nos da una medida de esa brecha. Módulo 7, debería ser 1 para obtener simetría, pero primero podemos verificar de forma económica el febrero sin salto comprobando ese total antes del módulo (lunes y 28 días por mes es la combinación mínima posible).

Me sorprende que esto tome tantos bytes, pero se necesitan 36 bytes para hacer una fecha y obtener el día de la semana y los días de ese mes.

Phil H
fuente