La symétrie des mois

32

introduction

Certains mois sont complètement symétriques , ce qui signifie qu'ils ont une symétrie centrale ainsi qu'une symétrie de réflexion , comme February of 2010:

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

Certains mois n'ont que la symétrie centrale, comme February of 1996ou mois en cours, le April of 2018:

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

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

Et certains sont asymétriques , comme le mois précédent, le March of 2018:

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

Tâche

Prenez une entrée sous forme de date , par exemple:

  • 2018.04
  • 2018.03
  • 2010.02
  • 1996.02

Afficher la symétrie correspondante , par exemple

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

Règles

  • C'est le golf de code, donc le plus petit nombre d'octets gagne.
  • Les failles standard ne sont évidemment pas autorisées.
  • Supposons que la semaine commence avec lundi (merci à Angs et Arnauld pour la suggestion).
  • Ne considérez que les années entre 1900 et 2100 ( inclus ).
  • Les règles de formatage d'entrée et de sortie sont permissives , ce qui signifie que vous pouvez utiliser n'importe quel format équivalent natif de la langue de votre choix.
  • Basez votre solution sur le calendrier grégorien .
mkierc
la source
7
Considérez que les dates sont bizarres , vous voudrez peut-être spécifier exactement les règles, ou limiter l'entrée possible à une petite plage (disons, 1901-2099)
user202729
2
Les choses à éviter lors de la rédaction de défis / L'ajout de choses inutilement comprend «Faire calculer les réponses f(x)pour chaque élément xd'une liste». Qu'en est-il de "prendre une entrée sous forme de date"?
user202729
6
Bienvenue chez PPCG, et beau premier défi! Bien que ce défi soit bon, à l'avenir, si vous souhaitez obtenir des commentaires sur le défi avant de le publier, vous pouvez le publier dans le bac à sable .
user202729
2
La sortie doit-elle être strictement les chaînes mentionnées ou 3 valeurs distinctes?
Uriel
2
(attendez une minute, calendrier grégorien ou calendrier julien? J'ai suggéré [1901-2099] mais vous décidez d'utiliser [1900-2100] afin qu'ils soient différents pour certaines entrées)
user202729

Réponses:

20

JavaScript (ES6), 55 octets

6 octets enregistrés grâce à @Neil

Prend des entrées dans la syntaxe de currying (year)(month). Renvoie falsepour asymétrique, truepour symétrique central et 0pour complètement symétrique.

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

Essayez-le en ligne!

Comment?

Nous définissons la fonction g () qui retourne le jour de la semaine de aaaa / mm / 01 , comme un entier entre 0 = lundi et 6 = dimanche.

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

Étant donné que getDay () renvoie nativement 0 = dimanche à 6 = samedi, nous décalons le résultat dans la plage attendue en interrogeant le 7ème jour à la place.

Ensuite, nous définissons:

n = g() + g()

Étant donné que le constructeur de Date attend un mois indexé sur 0 et que g () décrémente m après l'avoir passé à Date , nous calculons d'abord le jour de la semaine du premier jour du mois suivant , puis nous ajoutons celui du mois en cours.

Mois complètement symétriques

Les mois complètement symétriques commencent par un lundi et sont suivis d'un mois qui commence également par un lundi. Cela n'est possible que pour février d'une année sans bissextile.

- 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

Cela conduit à n = 0 .

Mois à symétrie centrale

Les mois à symétrie centrale sont des mois pour lesquels la somme du jour de la semaine de leur premier jour et de celle du mois suivant est 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

D'où le deuxième test: n == 7 .


Pas intégré, 93 octets

Utilise la congruence de Zeller . Même format d'E / S que l'autre version.

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

Essayez-le en ligne!

Arnauld
la source
Je pensais que c'était le cas true, falseet filenotfoundau lieu de 0
Angs
g=m=>new Date(y,m,7).getDay()enregistre 6 octets.
Neil
7

T-SQL , 213 octets (règles d'E / S strictes)

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 requête ci-dessus considère les règles strictes de formatage d'entrée / sortie.

L'entrée provient de la colonne sd'une table nommée 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 octets (règles d'E / S permissives)

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 le format de l'entrée et de la sortie peut être modifié, je choisirais de saisir le premier jour du mois, dans une datetimecolonne nommée d:

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

La sortie serait 1 pour asymétrique, 0 pour symétrique, NULL pour centralisée symétrique.

Si nous pouvons l'exécuter sur un serveur (ou avec une connexion) configuré pour la langue BRITANNIQUE, nous pouvons supprimer l' SET DATEFIRST 1enregistrement de 15 octets supplémentaires.

SQLFiddle 2

Razvan Socol
la source
1
Bon travail. Je ne sais pas si cela fonctionnera dans toutes les versions, mais sur SQL 2012, j'ai pu économiser 15 octets en utilisant CONVERT(DATETIME,s+'.01')au lieu de REPLACE. Vous pouvez également déposer l'espaceFROM (SELECT
BradC
1
Cela fonctionne, mais cela dépend du DATEFORMATparamètre. Par exemple, si nous utilisons SET LANGUAGE BRITISH, ce CONVERT(DATETIME,'2018.02.01')serait le 2 janvier au lieu du 1er février.
Razvan Socol
5

Haskell, 170 octets

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

Renvoie 2 pour symétrique central, 1 pour symétrique et 0 pour asymétrique

Angs
la source
@TuukkaX Désolé pour la confusion - c'est mon premier défi, j'ai changé les règles afin qu'elles autorisent également les formats de sortie permissifs afin que cela puisse être plus "dans l'esprit" du code-golf.
mkierc
5

Python 2, 118 104 octets

Merci à Jonathan Allan et Dead Possum pour les améliorations!

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

Python 3, 122 105 octets

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

Contribution

  • L' année est d'abord
  • Le deuxième est le mois


Sortie

  • 0 = pas de symétrie
  • 1 = symétrie centrale
  • 2 = symétrie complète
Jack of all Spades
la source
3
Bienvenue sur le site! Vous ne pouvez pas supposer que l'entrée est stockée dans une variable (comme You M), il s'agit donc actuellement d'un extrait de code et non valide. input()Cependant, si vous changez les variables en appels , ce sera parfaitement bien.
caird coinheringaahing
1
@cairdcoinheringaahing Merci pour l'accueil! Correction de l'entrée utilisateur :)
Jack of all Spades
Bienvenue! Tweaks for -9 bytes here - all import, unpacked input, _[0]+_[-1]->sum(..)
Dead Possum
1
Quelques astuces pour le faire descendre 13 octets ici
Jonathan Allan
1
... et un autre octet utilisant le tour de somme de Dead Possum - ici
Jonathan Allan
4

Rouge , 199, 168 161 octets

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]

Essayez-le en ligne!

0 - asymétrique

1 - symétrique

2 - symétrique central

Plus lisible:

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
la source
2

Mathematica, 137 octets

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

Fonction pure. Prend l'année et le mois comme entrée et retourne -1pour les mois asymétriques, 0pour les mois à symétrie centrale et 1pour les mois entièrement symétriques. Je ne sais pas pourquoi cette langue ne peut pas convertir un jour de la semaine en nombre par défaut ...

LegionMammal978
la source
2

Utilitaires Bash + GNU, 70

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

L'entrée est formatée comme YYYY/MM.

La sortie est numérique, comme suit:

  • moins de 0: symétrique central
  • exactement 0: symétrique
  • supérieur à 0: asymétrique

Je suppose que ce format de sortie est acceptable pour cette question.

Essayez-le en ligne!

Trauma numérique
la source
1

C, 111 octets

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

Appelez f(year, month), 0 pour complètement symétrique, 1 pour asymétrique, 2 pour symétrique central.

tsh
la source
IIRC vous pouvez abuser de UB sur GCC en le remplaçant returnpar y=(le premier paramètre) et en tombant hors de la fonction.
Quentin
1

Perl 6 , 74 octets

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

Bloc nu, implicitement une fonction de 1 argument, une chaîne comme "2012-02". Résultats:

2     # Fully symmetric
True  # Centrally symmetric
False # Asymmetric

Lorsque le modèle est symétrique, comme .day-of-week augmente de 1, .days-in-month devrait se déplacer de 2 afin de toujours correspondre (le mois commencerait un jour plus tard mais devra se terminer un jour plus tôt). ), 2 * .day-of-week + .days-in-monthnous donne donc une mesure de cet écart. Modulo 7, il devrait être 1 pour obtenir la symétrie, mais nous pouvons d'abord vérifier à moindre coût le mois de février sans saut en vérifiant ce total avant modulo (lundi et 28 jours par mois est la combinaison minimale possible).

Je suis surpris que cela prenne autant d'octets, mais 36 octets sont nécessaires pour simplement prendre une date et obtenir le jour de la semaine et les jours de ce mois.

Phil H
la source