Die Symmetrie der Monate

32

Einführung

Einige Monate sind vollständig symmetrisch , was bedeutet, dass sie sowohl eine Zentralsymmetrie als auch eine Reflexionssymmetrie aufweisen , wie z February of 2010.

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

Einige Monate haben nur zentrale Symmetrie, wie February of 1996oder aktueller Monat, die April of 2018:

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

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

Und einige sind asymmetrisch , wie im Vormonat, die March of 2018:

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

Aufgabe

Nehmen Sie eine Eingabe in Form eines Datums vor , zB:

  • 2018.04
  • 2018.03
  • 2010.02
  • 1996.02

Geben Sie die entsprechende Symmetrie aus , z

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

Regeln

  • Das ist Codegolf, also gewinnt die kleinste Anzahl von Bytes.
  • Standardlücken sind natürlich nicht erlaubt.
  • Angenommen, die Woche beginnt mit Montag (danke an Angs und Arnauld für den Vorschlag).
  • Berücksichtigen Sie nur Jahre zwischen 1900 und 2100 ( einschließlich ).
  • Die Eingabe- und Ausgabeformatierungsregeln sind zulässig , dh Sie können jedes äquivalente Format verwenden, das für die Sprache Ihrer Wahl typisch ist.
  • Basieren Sie Ihre Lösung auf dem Gregorianischen Kalender .
mkierc
quelle
7
Bedenken Sie, dass Datumsangaben seltsam sind. Möglicherweise möchten Sie die Regeln genau festlegen oder die mögliche Eingabe auf einen kleinen Bereich beschränken (z. B. 1901-2099)
user202729
2
Zu vermeidende Dinge beim Schreiben von Herausforderungen / Hinzufügen von unnötigem Material umfassen "Berechnen von Antworten f(x)für jeden xin einer Liste". Was ist mit "Eingabe in Form eines Datums"?
user202729
6
Willkommen bei PPCG und schöne erste Herausforderung! Obwohl diese Herausforderung gut ist, können Sie sie in Zukunft in der Sandbox veröffentlichen, wenn Sie vor dem Posten ein Feedback zur Herausforderung erhalten möchten .
user202729
2
Sollte die Ausgabe ausschließlich aus den genannten Zeichenfolgen oder 3 verschiedenen Werten bestehen?
Uriel
2
(Moment mal, Gregorianischer Kalender oder Julianischer Kalender? Ich habe [1901-2099] vorgeschlagen, aber Sie entscheiden sich für [1900-2100], damit sie für einige Eingaben unterschiedlich sind.)
user202729

Antworten:

20

JavaScript (ES6), 55 Byte

6 Bytes dank @Neil gespart

Übernimmt Eingaben in der Currying-Syntax (year)(month). Gibt falsefür asymmetrisch, truefür zentral symmetrisch und 0für vollständig symmetrisch zurück.

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

Probieren Sie es online!

Wie?

Wir definieren die Funktion g (), die den Wochentag von jjjj / mm / 01 als Ganzzahl zwischen 0 = Montag und 6 = Sonntag zurückgibt .

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

Da getDay () nativ 0 = Sonntag bis 6 = Samstag zurückgibt , verschieben wir das Ergebnis in den erwarteten Bereich, indem wir stattdessen den 7. Tag abfragen.

Dann definieren wir:

n = g() + g()

Da der Konstruktor von Date einen mit 0 indizierten Monat erwartet und g () nach der Übergabe an Date m dekrementiert , berechnen wir zunächst den Wochentag des ersten Tages des nächsten Monats und addieren dann den des aktuellen Monats.

Vollkommen symmetrische Monate

Völlig symmetrische Monate beginnen mit einem Montag, gefolgt von einem Monat, der ebenfalls mit einem Montag beginnt. Dies ist nur für den Februar eines Nicht-Schaltjahres möglich.

- 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

Dies führt zu n = 0 .

Zentral symmetrische Monate

Zentralsymmetrische Monate sind Monate, für die die Summe aus dem Wochentag des ersten Tages und dem des nächsten Monats 7 beträgt .

- 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

Daher der zweite Test: n == 7 .


Keine eingebauten 93 Bytes

Verwendet Zellers Kongruenz . Gleiches E / A-Format wie die andere 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

Probieren Sie es online!

Arnauld
quelle
Ich dachte , es war true, falseund filenotfoundstatt 0...
Angs
g=m=>new Date(y,m,7).getDay()Spart 6 Bytes.
Neil
7

T-SQL , 213 Byte (strenge E / A-Regeln)

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

Die obige Abfrage berücksichtigt die strengen Formatierungsregeln für die Eingabe / Ausgabe.

Die Eingabe stammt aus der Spalte seiner Tabelle mit dem Namen 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 Byte (zulässige E / A-Regeln)

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

Wenn das Format der Eingabe und der Ausgabe geändert werden kann, würde ich den ersten Tag des Monats in einer datetimeSpalte mit dem Namen eingeben d:

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

Die Ausgabe wäre 1 für asymetrisch, 0 für symetrisch, NULL für zentral symetrisch.

Wenn wir es auf einem Server (oder mit einem Login) ausführen können, der für die BRITISH-Sprache konfiguriert ist, können wir das SET DATEFIRST 1Speichern von 15 weiteren Bytes entfernen .

SQLFiddle 2

Razvan Socol
quelle
1
Gute Arbeit. Ich bin mir nicht sicher, ob es in allen Versionen funktioniert, aber in SQL 2012 konnte ich 15 Bytes einsparen, indem ich CONVERT(DATETIME,s+'.01')anstelle von verwendete REPLACE. Sie können auch das Leerzeichen inFROM (SELECT
BradC
1
Es funktioniert, ist aber abhängig von der DATEFORMATEinstellung. Wenn wir zum Beispiel verwenden SET LANGUAGE BRITISH, CONVERT(DATETIME,'2018.02.01')wäre dies der 2. Januar anstelle des 1. Februar.
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

Gibt 2 für zentral symmetrisch, 1 für symmetrisch und 0 für asymmetrisch zurück

Angs
quelle
@TuukkaX Entschuldigung für die Verwirrung - dies ist meine erste Herausforderung. Ich habe die Regeln so geändert, dass sie auch zulässige Ausgabeformate zulassen, damit es mehr "im Geiste" des Code-Golfs sein kann.
Mkierc
5

Python 2, 118 104 Bytes

Vielen Dank an Jonathan Allan und Dead Possum für die Verbesserungen!

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

Eingang

  • Erstens ist das Jahr
  • Zweitens ist der Monat


Ausgabe

  • 0 = keine Symmetrie
  • 1 = zentrale Symmetrie
  • 2 = vollständige Symmetrie
Jack of all Spades
quelle
3
Willkommen auf der Seite! Sie können nicht davon ausgehen, dass die Eingabe in einer Variablen (wie z. B. Yoder M) gespeichert ist. Daher ist dies derzeit ein Snippet und ungültig. Wenn Sie die Variablen jedoch in Aufrufe ändern input(), ist dies vollkommen in Ordnung.
Caird Coinheringaahing
1
@cairdcoinheringaahing Danke für die Begrüßung! Behobene Benutzereingaben :)
Jack of all Spades
Herzlich willkommen! Tweaks für -9 Bytes hier - alle importieren, entpackte Eingabe, _[0]+_[-1]->sum(..)
Dead Possum
1
Einige Tricks, um es 13 Bytes hier
Jonathan Allan
1
... und ein weiteres Byte mit dem Summentrick von Dead Possum - hier
Jonathan Allan
4

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

Probieren Sie es online!

0 - asymmetrisch

1 - symmetrisch

2 - zentral symmetrisch

Besser lesbar:

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

Funktion pur. Nimmt das Jahr und den Monat als Eingabe und gibt sie -1für asymmetrische Monate, 0für zentral symmetrische Monate und 1für vollständig symmetrische Monate zurück. Nicht sicher, warum diese Sprache nicht standardmäßig von einem Wochentag in eine Zahl konvertieren kann ...

LegionMammal978
quelle
2

Bash + GNU-Dienstprogramme, 70

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

Die Eingabe ist formatiert als YYYY/MM.

Die Ausgabe erfolgt numerisch wie folgt:

  • kleiner als 0: zentral symmetrisch
  • genau 0: symmetrisch
  • größer als 0: asymmetrisch

Ich gehe davon aus, dass dieses Ausgabeformat für diese Frage akzeptabel ist.

Probieren Sie es online!

Digitales Trauma
quelle
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);}

Invoke f(year, month), 0 für vollständig symmetrisch, 1 für asymmetrisch, 2 für zentral symmetrisch.

tsh
quelle
IIRC können Sie UB auf GCC missbrauchen, indem Sie returndurch y=(den ersten Parameter) ersetzen und aus der Funktion herausfallen.
Quentin
1

Perl 6 , 74 Bytes

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

Bare Block, implizit eine Funktion von 1 Argument, ein String wie "2012-02". Kehrt zurück:

2     # Fully symmetric
True  # Centrally symmetric
False # Asymmetric

Wenn das Muster symmetrisch ist und der Wochentag um 1 erhöht wird, müssen die Wochentage um 2 verschoben werden, um die Übereinstimmung zu gewährleisten (der Monat beginnt einen Tag später, muss jedoch einen Tag früher enden) ), so 2 * .day-of-week + .days-in-monthgibt uns ein Maß für diese Lücke. Modulo 7 sollte 1 sein, um Symmetrie zu erhalten, aber wir können zuerst billig nach dem Nichtsprung-Februar suchen, indem wir die Summe vor Modulo prüfen (Montag und 28 Tage pro Monat ist die minimal mögliche Kombination).

Ich bin überrascht, dass dies so viele Bytes benötigt, aber es werden 36 Bytes benötigt, um nur ein Datum zu erstellen und den Wochentag und die Wochentage in diesem Monat zu ermitteln.

Phil H
quelle