La simmetria dei mesi


32

introduzione

Alcuni mesi sono completamente simmetrica , nel senso che hanno simmetria centrale così come simmetria di riflessione , come February of 2010:

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

Alcuni mesi hanno solo una simmetria centrale, come February of 1996o il mese corrente, il April of 2018:

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

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

E alcuni sono asimmetrici , come il mese precedente, i March of 2018:

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

Compito

Prendi un input sotto forma di una data , ad esempio:

  • 2018.04
  • 2018.03
  • 2010.02
  • 1996.02

Emettere la simmetria corrispondente , ad es

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

Regole

  • Questo è il codice golf, quindi vince il minor numero di byte.
  • Ovviamente non sono ammesse scappatoie standard.
  • Supponiamo che la settimana inizi con lunedì (grazie ad Angs e Arnauld per il suggerimento).
  • Considera solo anni tra il 1900 e il 2100 ( incluso ).
  • Le regole di formattazione di input e output sono permissive , il che significa che puoi usare qualsiasi formato equivalente che è nativo per la lingua che preferisci.
  • Basa la tua soluzione sul calendario gregoriano .

7
Considera che le date sono strane , potresti voler specificare esattamente le regole o limitare il possibile input a un piccolo intervallo (diciamo, 1901-2099)
user202729

2
Le cose da evitare quando si scrivono sfide / L'aggiunta di elementi inutili include "Rendere le risposte calcolate f(x)per ogni xin un elenco". Che dire di "prendere un input sotto forma di una data"?
user202729

6
Benvenuto in PPCG e bella prima sfida! Anche se questa sfida è buona, in futuro se desideri un feedback sulla sfida prima di pubblicarla, puoi pubblicarla nella sandbox .
user202729

2
L'output dovrebbe essere rigorosamente le stringhe menzionate o 3 valori distinti?
Uriel

2
(aspetta un minuto, calendario gregoriano o calendario giuliano? Ho suggerito [1901-2099] ma decidi di usare [1900-2100] in modo che siano diversi per alcuni input)
user202729

Risposte:


20

JavaScript (ES6), 55 byte

6 byte salvati grazie a @Neil

Accetta input nella sintassi del curry (year)(month). Restituisce falseper asimmetrico, trueper centrale simmetrica e 0per completamente simmetrica.

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

Provalo online!

Come?

Definiamo la funzione g () che restituisce il giorno della settimana di aaaa / mm / 01 , come un numero intero compreso tra 0 = lunedì e 6 = domenica.

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

Poiché getDay () restituisce nativamente 0 = domenica a 6 = sabato, spostiamo invece il risultato sull'intervallo previsto eseguendo una query per il settimo giorno.

Quindi definiamo:

n = g() + g()

Poiché il costruttore di Date prevede un mese con indice 0 e poiché g () diminuisce m dopo averlo passato a Data , in realtà calcoliamo prima il giorno della settimana del primo giorno del mese successivo e quindi aggiungiamo quello di quello corrente.

Mesi completamente simmetrici

I mesi completamente simmetrici iniziano con un lunedì e sono seguiti da un mese che inizia anche con un lunedì. Questo è possibile solo per febbraio di un anno non bisestile.

- 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

Questo porta a n = 0 .

Mesi centralmente simmetrici

I mesi centralmente simmetrici sono mesi per i quali la somma del giorno della settimana del loro primo giorno e quella del mese successivo è 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 qui il secondo test: n == 7 .


Nessun built-in, 93 byte

Usa la congruenza di Zeller . Stesso formato I / O dell'altra versione.

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

Provalo online!


Ho pensato che fosse true, falsee filenotfoundinvece di 0...
Angs

g=m=>new Date(y,m,7).getDay()salva 6 byte.
Neil

7

T-SQL , 213 byte (regole I / O rigide)

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 query precedente considera le rigide regole di formattazione input / output.

L'input è tratto dalla colonna sdi una tabella denominata 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 (regole I / O permissive)

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 il formato dell'input e dell'output può essere modificato, sceglierei di inserire il primo giorno del mese, in una datetimecolonna denominata d:

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

L'output sarebbe 1 per asimmetrico, 0 per simmetrico, NULL per simmetrico centrale.

Se possiamo eseguirlo su un server (o con un login) configurato per il linguaggio BRITISH, possiamo rimuovere SET DATEFIRST 1salvando altri 15 byte.

SQLFiddle 2


1
Bel lavoro. Non sono sicuro che funzionerà in tutte le versioni, ma su SQL 2012 sono stato in grado di salvare 15 byte utilizzando CONVERT(DATETIME,s+'.01')invece di REPLACE. Puoi anche rilasciare lo spazio inFROM (SELECT
BradC

1
Funziona, ma dipende DATEFORMATdall'impostazione. Ad esempio, se usiamo SET LANGUAGE BRITISH, CONVERT(DATETIME,'2018.02.01')sarebbe il 2 gennaio, anziché il 1 febbraio.
Razvan Socol,

5

Haskell, 170 byte

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

Restituisce 2 per simmetrico centrale, 1 per simmetrico e 0 per asimmetrico


@TuukkaX Ci scusiamo per la confusione: questa è la mia prima sfida, ho cambiato le regole in modo che consentano anche formati di output permissivi in ​​modo che possa essere più "nello spirito" del code-golf.
mkierc,

5

Python 2, 118 104 byte

Grazie a Jonathan Allan e Dead Possum per i miglioramenti!

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

Python 3, 122 105 byte

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

Ingresso

  • Il primo è l' anno
  • Il secondo è il mese


Produzione

  • 0 = nessuna simmetria
  • 1 = simmetria centrale
  • 2 = simmetria completa

3
Benvenuti nel sito! Non puoi presumere che l'input sia archiviato in una variabile (come Yo M), quindi questo è attualmente uno snippet e non è valido. Se si cambiano le variabili in chiamate input(), tuttavia, questo andrà perfettamente bene.
caird coinheringaahing

1
@cairdcoinheringaahing Grazie per il benvenuto! Risolto l'input dell'utente :)
Jack of all Spades

Benvenuto! Modifiche per -9 byte qui - tutte le importazioni, input non compresso, _[0]+_[-1]->sum(..)
Dead Possum

1
Alcuni trucchi per farlo scendere 13 byte qui
Jonathan Allan

1
... e un altro byte usando il trucco somma di Dead Possum - qui
Jonathan Allan

4

Rosso , 199, 168 161 byte

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]

Provalo online!

0 - asimmetrico

1 - simmetrico

2 - centralmente simmetrico

Più leggibile:

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
]

2

Mathematica, 137 byte

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

Funzione pura. Prende l'anno e il mese come input e ritorna -1per mesi asimmetrici, 0per mesi centralmente simmetrici e 1per mesi completamente simmetrici. Non so perché questa lingua non può convertire da un giorno della settimana in un numero per impostazione predefinita ...


2

Utilità Bash + GNU, 70

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

L'input è formattato come YYYY/MM.

L'output è numerico, come segue:

  • inferiore a 0: centralmente simmetrico
  • esattamente 0: simmetrico
  • maggiore di 0: asimmetrico

Presumo che questo formato di output sia accettabile per questa domanda.

Provalo online!


1

C, 111 byte

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

Richiama f(year, month), 0 per completamente simmetrico, 1 per asimmetrico, 2 per centralmente simmetrico.


IIRC puoi abusare di UB su GCC sostituendolo returncon y=(il primo parametro) e uscendo dalla funzione.
Quentin,

1

Perl 6 , 74 byte

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

Blocco nudo, implicitamente una funzione di 1 argomento, una stringa come "2012-02". Ritorna:

2     # Fully symmetric
True  # Centrally symmetric
False # Asymmetric

Quando il modello è simmetrico, poiché .day della settimana aumenta di 1, .days-in-mese dovrebbe spostarsi di 2 per poter ancora abbinare (il mese dovrebbe iniziare un giorno dopo ma deve terminare un giorno prima ), così 2 * .day-of-week + .days-in-month ci fornisce una misura di tale divario. Modulo 7 dovrebbe essere 1 per ottenere la simmetria, ma possiamo prima verificare a buon mercato il febbraio senza salti controllando il totale prima del modulo (lunedì e 28 giorni al mese è la combinazione minima possibile).

Sono sorpreso dal fatto che questo richieda così tanti byte, ma sono necessari completamente 36 byte solo per fissare una data e ottenere il giorno della settimana e i giorni in quel mese.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.