Symetria miesięcy

32

Wprowadzenie

Niektóre miesiące są całkowicie symetryczne , co oznacza, że ​​mają symetrię centralną oraz symetrię odbicia , na przykład February of 2010:

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

Niektóre miesiące mają tylko centralną symetrię, taką jak February of 1996lub bieżący, a April of 2018:

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

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

Niektóre są asymetryczne , jak w poprzednim miesiącu March of 2018:

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

Zadanie

Wprowadź dane w postaci daty , np .:

  • 2018.04
  • 2018.03
  • 2010.02
  • 1996.02

Wyprowadź odpowiednią symetrię , np

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

Zasady

  • To jest kod golfowy, więc wygrywa najmniejsza liczba bajtów.
  • Standardowe luki są oczywiście niedozwolone.
  • Załóżmy, że tydzień zaczyna się od poniedziałku (dzięki Angs i Arnauld za sugestie).
  • Rozważ tylko lata od 1900 do 2100 ( włącznie ).
  • Reguły formatowania danych wejściowych i wyjściowych są dozwolone , co oznacza, że ​​można użyć dowolnego równoważnego formatu rodzimego dla wybranego języka.
  • Oprzyj swoje rozwiązanie na kalendarzu gregoriańskim .
mkierc
źródło
7
Pomyśl, że daty są dziwne , możesz sprecyzować reguły lub ograniczyć ewentualne dane wejściowe do niewielkiego zakresu (powiedzmy, 1901-2099)
202729
2
Do rzeczy, których należy unikać, pisząc wyzwania / dodając niepotrzebnie rzeczy, należy wymienić: „Wyliczanie odpowiedzi f(x)dla każdego xna liście”. Co powiesz na „weź dane w formie daty”?
user202729,
6
Witamy w PPCG i miłe pierwsze wyzwanie! Chociaż to wyzwanie jest dobre, w przyszłości, jeśli chcesz opublikować opinię na temat wyzwania przed opublikowaniem, możesz opublikować je w piaskownicy .
user202729,
2
Czy dane wyjściowe powinny być ściśle wymienionymi ciągami, czy też 3 odrębnymi wartościami?
Uriel
2
(poczekaj minutę, kalendarz gregoriański czy kalendarz juliański? Zasugerowałem [1901-2099], ale decydujesz się użyć [1900-2100], więc są różne dla niektórych danych wejściowych)
użytkownik202729

Odpowiedzi:

20

JavaScript (ES6), 55 bajtów

Zaoszczędź 6 bajtów dzięki @Neil

Pobiera dane wejściowe w składni curry (year)(month). Zwraca wartość falseasymetryczną, truecentralnie symetryczną i 0całkowicie symetryczną.

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

Wypróbuj online!

W jaki sposób?

Definiujemy funkcję g (), która zwraca dzień tygodnia rrrr / mm / 01 , jako liczbę całkowitą od 0 = poniedziałek do 6 = niedziela.

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

Ponieważ metoda getDay () natywnie zwraca wartość 0 = niedziela do 6 = sobota, przesuwamy wynik do oczekiwanego zakresu, wysyłając zapytanie dla 7. dnia.

Następnie definiujemy:

n = g() + g()

Ponieważ konstruktor Date oczekuje miesiąca o indeksie 0 i ponieważ g () zmniejsza m po przekazaniu go do Date , w rzeczywistości najpierw obliczamy dzień tygodnia pierwszego dnia następnego miesiąca, a następnie dodajemy go do bieżącego.

Całkowicie symetryczne miesiące

Całkowicie symetryczne miesiące zaczynają się od poniedziałku, a po nich następuje miesiąc, który również zaczyna się od poniedziałku. Jest to możliwe tylko w lutym roku bez przeskoku.

- 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

Prowadzi to do n = 0 .

Centralnie symetryczne miesiące

Centralnie symetryczne miesiące to miesiące, dla których suma dnia tygodnia pierwszego i następnego miesiąca wynosi 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

Stąd drugi test: n == 7 .


Brak wbudowanych, 93 bajtów

Wykorzystuje zgodność Zellera . Ten sam format we / wy, co w innej wersji.

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

Wypróbuj online!

Arnauld
źródło
Myślałem, że tak true, falsei filenotfoundzamiast 0
Angs
g=m=>new Date(y,m,7).getDay()oszczędza 6 bajtów.
Neil
7

T-SQL , 213 bajtów (ścisłe reguły we / wy)

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

Powyższe zapytanie uwzględnia ścisłe reguły formatowania wejścia / wyjścia.

Dane wejściowe pochodzą z kolumny stabeli o nazwie t:

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

Nie golfowany:

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 bajtów (dopuszczalne reguły We / Wy)

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

Jeśli format danych wejściowych i wyjściowych można zmienić, wybrałbym wprowadzenie pierwszego dnia miesiąca w datetimekolumnie o nazwie d:

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

Wynik będzie wynosił 1 dla asymetrycznego, 0 dla symetrycznego, NULL dla centralnie symetrycznego.

Jeśli możemy uruchomić go na serwerze (lub z loginem) skonfigurowanym dla języka BRYTYJSKIEGO, możemy usunąć SET DATEFIRST 1oszczędność 15 dodatkowych bajtów.

SQLFiddle 2

Razvan Socol
źródło
1
Dobra robota. Nie jestem pewien, czy zadziała we wszystkich wersjach, ale w SQL 2012 udało mi się zapisać 15 bajtów, używając CONVERT(DATETIME,s+'.01')zamiast REPLACE. Możesz również upuścić to miejsce wFROM (SELECT
BradC
1
Działa, ale zależy to od DATEFORMATustawienia. Na przykład, jeśli użyjemy SET LANGUAGE BRITISH, to CONVERT(DATETIME,'2018.02.01')będzie 2 stycznia zamiast 1 lutego.
Razvan Socol
5

Haskell, 170 bajtów

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

Zwraca 2 dla centralnie symetrycznego, 1 dla symetrycznego i 0 dla asymetrycznego

Angs
źródło
@TuukkaX Przepraszam za zamieszanie - to moje pierwsze wyzwanie. Zmieniłem reguły, aby zezwalały również na dopuszczalne formaty wyjściowe, dzięki czemu mogą być bardziej „w duchu” golfowego kodu.
mkierc
5

Python 2, 118 104 bajtów

Dzięki Jonathan Allan i Dead Possum za ulepszenia!

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

Python 3, 122 105 bajtów

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

Wkład

  • Pierwszy to rok
  • Drugi to miesiąc


Wydajność

  • 0 = brak symetrii
  • 1 = centralna symetria
  • 2 = pełna symetria
Jack wszystkich pik
źródło
3
Witamy na stronie! Nie można zakładać, że dane wejściowe są przechowywane w zmiennej (takiej jak Ylub M), więc jest to obecnie fragment kodu i jest on nieprawidłowy. Jeśli zmienisz zmienne na wywołania input(), będzie to jednak w porządku.
caird coinheringaahing
1
@cairdcoinheringaahing Dzięki za powitanie! Naprawiono wprowadzane przez użytkownika :)
Jack wszystkich pik
Witamy! Poprawiono dla -9 bajtów tutaj - cały import, rozpakowane dane wejściowe, _[0]+_[-1]->sum(..)
Dead Possum
1
Kilka sztuczek, aby obniżyć o 13 bajtów tutaj
Jonathan Allan
1
... i kolejny bajt za pomocą sztuczki Dead Possum - tutaj
Jonathan Allan
4

Czerwony , 199, 168 161 bajtów

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]

Wypróbuj online!

0 - asymetryczny

1 - symetryczny

2 - centralnie symetryczny

Bardziej czytelny:

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 Iwanow
źródło
2

Mathematica, 137 bajtów

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

Czysta funkcja. Przyjmuje rok i miesiąc jako dane wejściowe i zwroty -1dla miesięcy asymetrycznych, 0dla miesięcy centralnie symetrycznych i 1dla miesięcy w pełni symetrycznych. Nie jestem pewien, dlaczego ten język nie może domyślnie przekonwertować z dnia tygodnia na liczbę ...

LegionMammal978
źródło
2

Narzędzia Bash + GNU, 70

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

Dane wejściowe są sformatowane jako YYYY/MM.

Dane wyjściowe są numeryczne, jak następuje:

  • mniej niż 0: centralnie symetryczny
  • dokładnie 0: symetryczny
  • większa niż 0: asymetryczna

Zakładam, że ten format wyjściowy jest akceptowalny dla tego pytania.

Wypróbuj online!

Cyfrowa trauma
źródło
1

C, 111 bajtów

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

Wywołaj f(year, month), 0 dla całkowicie symetrycznego, 1 dla asymetrycznego, 2 dla centralnie symetrycznego.

tsh
źródło
IIRC można nadużywać UB na GCC zastępując returnz y=(pierwszy parametr) i wypadnięcie funkcji.
Quentin,
1

Perl 6 , 74 bajtów

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

Goły blok, domyślnie funkcja 1 argumentu, podobny do łańcucha "2012-02". Zwroty:

2     # Fully symmetric
True  # Centrally symmetric
False # Asymmetric

Gdy wzorzec jest symetryczny, ponieważ liczba dni w tygodniu wzrasta o 1, dni w miesiącu musiałyby zostać przesunięte o 2, aby nadal pasowały (miesiąc zaczynałby się dzień później, ale musiałby zakończyć dzień wcześniej ), więc 2 * .day-of-week + .days-in-month daje nam miarę tej luki. Modulo 7 powinno uzyskać 1, aby uzyskać symetrię, ale możemy najpierw tanio sprawdzić, czy luty nie przeskakuje, sprawdzając tę ​​sumę przed modulo (poniedziałek i 28 dni w miesiącu to minimalna możliwa kombinacja).

Dziwię się, że zajmuje to tak wiele bajtów, ale w pełni potrzeba 36 bajtów na samą datę i uzyskanie dnia tygodnia i dni w tym miesiącu.

Phil H.
źródło