Ayların simetrisi


32

Giriş

Birkaç ay olan tamamen simetrik sahip oldukları anlamına merkezi simetri yanı sıra yansıma simetrisi gibi February of 2010:

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

Bazı aylar, şu anda olduğu gibi veya şu anda olduğu gibi, sadece merkezi simetriye sahiptir :February of 1996April of 2018

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

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

Ve bazıları asimetrik , önceki ay gibi March of 2018:

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

Görev

Tarih biçiminde bir girdi alın , örneğin:

  • 2018.04
  • 2018.03
  • 2010.02
  • 1996.02

Karşılık gelen simetriyi çıktılar , örn.

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

kurallar

  • Bu kod golf, yani en küçük bayt sayısı kazanır.
  • Standart boşluklara kesinlikle izin verilmiyor.
  • Haftanın Pazartesi ile başladığını varsayalım ( öneri için Angs ve Arnauld sayesinde ).
  • Sadece 1900 ile 2100 arasındaki ( dahil ) yılları dikkate alınız .
  • Giriş ve çıkış formatlama kurallarına izin verilir , yani seçtiğiniz dile özgü olan herhangi bir formatı kullanabilirsiniz.
  • Çözümünüzü Gregoryen takvimine dayandırın .

7
Tarihlerin tuhaf olduğunu düşünün , kuralları tam olarak belirtmek ya da olası girişi küçük bir aralıkla sınırlamak isteyebilirsiniz (örneğin, 1901-2099)
user202729

2
Zorluklar yazarken kaçınılması gerekenler / Gereksiz yere malzeme ekleme , " Listedeki f(x)her xbiri için cevap hesaplama yapma" içerir . Peki ya "tarih biçiminde bir girdi al"?
user202729

6
PPCG'ye hoş geldiniz ve güzel bir ilk meydan okuma! Her ne kadar bu zorluk iyi olsa da, gelecekte yayınlanmadan önce meydan okuma hakkında biraz geribildirim almak isterseniz, bunu sanal alana gönderebilirsiniz .
user202729

2
Çıktı kesinlikle belirtilen dizgilerden mi, yoksa 3 farklı değerden mi oluşmalı?
Uriel

2
(bir dakika bekleyin, Gregoryen takvimi veya Julian takvimi? [1901-2099] 'ı önerdim, ancak [1900-2100]' ü kullanmaya karar verdiniz, bu nedenle bazı girdiler için farklılar)
user202729

Yanıtlar:


20

JavaScript (ES6), 55 bayt

@Neil sayesinde 6 bayt kaydedildi

Körleme sözdiziminde girdi alır (year)(month). İade falseasimetrik için,true merkezi olarak simetrik ve 0tamamen simetrik için.

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

Çevrimiçi deneyin!

Nasıl?

Yyyy / mm / 01 haftasını döndüren g () fonksiyonunu 0 = Pazartesi ve 6 = Pazar arasında bir tamsayı olarak tanımlarız .

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

Çünkü getDay () yerel olarak 0 = Pazar - 6 = cumartesi, bunun yerine 7 gün sorgulayarak beklenen aralığa sonucu kayması.

O zaman tanımlarız:

n = g() + g()

Yapıcısı Çünkü tarihi bir 0-endeksli ay beklediğini ve çünkü gr () azaltır m sonra geçirmeden tarihi , aslında ilk ilk gününün hafta içi hesaplamak sonraki ayın ardından şimdiki birinin olduğunu ekleyin.

Tamamen simetrik aylar

Tamamen simetrik aylar Pazartesi ile başlar ve bunu Pazartesi ile başlayan bir ay izler. Bu, artık olmayan bir yılın Şubat ayında mümkündür.

- 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

Bu n = 0 olur .

Merkez simetrik aylar

Merkezi bir simetrik ay ilk günün hafta içi toplamı için aylar ve bir sonraki ayın olmasıdır 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

Dolayısıyla ikinci test: n == 7 .


Dahili, 93 bayt yok

Zeller'in uyumunu kullanır . Diğer sürümle aynı G / Ç formatı.

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

Çevrimiçi deneyin!


Düşündüm ki o true, falseve filenotfoundyerine 0...
ANG'ler

g=m=>new Date(y,m,7).getDay()6 bayt kaydeder.
Neil

7

T-SQL , 213 bayt (katı G / Ç kuralları)

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

Yukarıdaki sorgu katı girdi / çıktı formatlama kurallarını dikkate almaktadır.

Girdi, sadlı bir tablonun sütunundan alınır 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 bayt (izin verilen G / Ç kuralları)

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

Girdi ve çıktının formatı değiştirilebilirse, ayın ilk gününü, şu datetimeadında bir sütuna girmeyi tercih ederim d:

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

Çıkış asimetrik için 1, simetrik için 0, merkezi simetrik için NULL olacaktır.

BRITISH dili için yapılandırılmış bir sunucuda (veya bir oturum açarak) çalıştırabilirsek, SET DATEFIRST 115 bayttan fazla tasarruf sağlayabiliriz .

SQLFiddle 2


1
İyi iş. Tüm sürümlerde çalışıp çalışmayacağından emin değilim, ancak SQL 2012'de kullanmak CONVERT(DATETIME,s+'.01')yerine 15 bayt tasarruf ettim REPLACE. Ayrıca boşluğu da bırakabilirsinizFROM (SELECT
BradC

1
Çalışır, ancak DATEFORMATayara bağlıdır . Örneğin, kullanırsak SET LANGUAGE BRITISH, CONVERT(DATETIME,'2018.02.01')1 Şubat yerine 2 Ocak olur.
Razvan Socol

5

Haskell, 170 bayt

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

Merkezi simetrik için 2, simetrik için 1 ve asimetrik için 0 döndürür


@TuukkaX Karışıklık için üzgünüm - bu benim ilk zorluğum, kuralları değiştirdim, bu yüzden izinli çıktı biçimlerine de izin verdiler.
mkierc

5

Python 2, 118 104 bayt

Jonathan Allan ve Dead Possum'a iyileştirmeler için teşekkürler!

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

Python 3, 122 105 bayt

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

Giriş

  • İlk yıl
  • İkinci ay


Çıktı

  • 0 = simetri yok
  • 1 = merkezi simetri
  • 2 = tam simetri

3
Siteye Hoşgeldiniz! Girişin bir değişkende ( Yveya gibi M) saklandığını kabul edemezsiniz , bu nedenle bu şu anda snippet ve geçersizdir. Değişkenleri çağrılar olarak değiştirirseniz input(), bu tamamen iyi olacaktır.
caird coinheringaahing

1
@cairdcoinheringaahing Hoşgeldiniz! Sabit kullanıcı girişi :)
Tüm Maçaların Jack'i

Hoşgeldiniz! Burada -9 bayt için Tweaks - tüm ithalat, ambalajsız giriş, _[0]+_[-1]->sum(..)
Dead Possum


1
... ve Dead Possum'un toplama hilesini kullanan başka bir bayt - burada
Jonathan Allan

4

Kırmızı , 199, 168 161 bayt

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]

Çevrimiçi deneyin!

0 - asimetrik

1 - simetrik

2 - merkezi simetrik

Daha okunabilir:

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 bayt

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

Saf işlevi. Yılı ve ayı girdi olarak alır ve -1asimetrik aylar, 0merkezi simetrik aylar ve 1tamamen simetrik aylar için geri döner . Bu dilin neden varsayılan olarak bir hafta içi günden sayıya dönemediğinden emin değilim ...


2

Bash + GNU yardımcı programları, 70

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

Giriş olarak biçimlendirilmiş YYYY/MM .

Çıktı aşağıdaki gibi sayısaldır:

  • 0'dan küçük: merkezi simetrik
  • tam 0: simetrik
  • 0'dan büyük: asimetrik

Bu çıktı formatının bu soru için kabul edilebilir olduğunu varsayıyorum.

Çevrimiçi deneyin!


1

C, 111 bayt

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

Çağırır f(year, month)tamamen simetrik için, 0, merkezi simetrik için asimetrik, 2 1.


IIRC (ilk parametre) returnile değiştirerek y=ve işlevden düşerek UCC'yi GCC'de kötüye kullanabilirsiniz .
Quentin

1

Perl 6 , 74 bayt

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

Çıplak blok, dolaylı olarak 1 argümanının bir işlevi, benzeri bir dize "2012-02". İade:

2     # Fully symmetric
True  # Centrally symmetric
False # Asymmetric

Patern simetrik olduğunda, haftanın gününün 1 kadar artması nedeniyle, ayın içindeki günlerin hala eşleşmesi için 2 oranında hareket etmesi gerekir (ay bir gün sonra başlayacak ancak bir gün önce bitmesi gerekecek ), yani 2 * .day-of-week + .days-in-month bize bu boşluğun bir ölçüsünü veriyor. Modulo 7, simetriye sahip olmak için 1 olmalıdır, ancak ilk önce modulodan önce toplamı kontrol ederek sıçramayacak Şubat ayını ucuza kontrol edebiliriz (ayda Pazartesi ve 28 gün minimum olası kombinasyondur).

Bunun çok fazla bayt almasına şaşırdım, ancak yalnızca randevu almak ve haftanın gününü ve o aydaki günleri almak için tam olarak 36 bayta ihtiyaç var.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.