Simetri bulan

32

pengantar

Beberapa bulan benar - benar simetris , artinya mereka memiliki simetri sentral serta simetri refleksi , seperti February of 2010:

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

Beberapa bulan hanya memiliki simetri pusat, seperti February of 1996atau bulan saat ini, yang April of 2018:

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

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

Dan beberapa asimetris , seperti bulan sebelumnya, yaitu March of 2018:

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

Tugas

Ambil input dalam bentuk tanggal , misalnya:

  • 2018.04
  • 2018.03
  • 2010.02
  • 1996.02

Keluarkan simetri yang sesuai , mis

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

Aturan

  • Ini adalah kode golf, sehingga jumlah byte terkecil menang.
  • Celah standar tidak diperbolehkan.
  • Asumsikan minggu dimulai dengan hari Senin (terima kasih kepada Angs dan Arnauld untuk sarannya).
  • Pertimbangkan hanya tahun antara 1900 dan 2100 ( inklusif ).
  • Aturan pemformatan input dan output permisif , artinya Anda dapat menggunakan format apa pun yang setara dengan bahasa pilihan Anda.
  • Dasarkan solusi Anda pada kalender Gregorian .
mkierc
sumber
7
Pertimbangkan bahwa tanggal itu aneh , Anda mungkin ingin menentukan aturan dengan tepat, atau membatasi input yang mungkin untuk rentang kecil (katakanlah, 1901-2099)
user202729
2
Hal-hal yang harus dihindari ketika menulis tantangan / Menambahkan hal - hal yang tidak perlu termasuk "Membuat jawaban dihitung f(x)untuk setiap orang xdalam daftar." Bagaimana dengan "mengambil input dalam bentuk tanggal"?
user202729
6
Selamat datang di PPCG, dan tantangan pertama yang menyenangkan! Meskipun tantangan ini baik, di masa depan jika Anda ingin umpan balik tentang tantangan sebelum memposting, Anda dapat mempostingnya di kotak pasir .
user202729
2
Haruskah output benar-benar string yang disebutkan, atau 3 nilai berbeda?
Uriel
2
(tunggu sebentar, kalender Gregorian atau kalender Julian? Saya sarankan [1901-2099] tetapi Anda memutuskan untuk menggunakan [1900-2100] sehingga mereka berbeda untuk beberapa input)
user202729

Jawaban:

20

JavaScript (ES6), 55 byte

Disimpan 6 byte berkat @Neil

Mengambil input dalam sintaks currying (year)(month). Pengembalian falseuntuk asimetris, trueuntuk simetris terpusat dan 0untuk sepenuhnya simetris.

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

Cobalah online!

Bagaimana?

Kami mendefinisikan fungsi g () yang mengembalikan hari kerja yyyy / mm / 01 , sebagai bilangan bulat antara 0 = Senin dan 6 = Minggu.

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

Karena getDay () mengembalikan secara asli 0 = Minggu hingga 6 = Sabtu, kami menggeser hasilnya ke kisaran yang diharapkan dengan meminta kueri untuk hari ke-7.

Lalu kami mendefinisikan:

n = g() + g()

Karena konstruktor Tanggal memperkirakan bulan yang diindeks 0 dan karena g () menurunkan m setelah meneruskannya ke Tanggal , kami sebenarnya menghitung hari kerja pada hari pertama bulan berikutnya dan kemudian menambahkan bahwa hari ini.

Sepenuhnya bulan simetris

Bulan yang sepenuhnya simetris dimulai dengan hari Senin dan diikuti oleh bulan yang juga dimulai dengan hari Senin. Ini hanya mungkin untuk Februari tahun non-kabisat.

- 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

Ini mengarah ke n = 0 .

Bulan simetris terpusat

Bulan simetris terpusat adalah bulan di mana jumlah hari kerja pada hari pertama mereka dan bulan berikutnya adalah 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

Karenanya tes kedua: n == 7 .


Tidak ada bawaan, 93 byte

Menggunakan kongruensi Zeller . Format I / O yang sama dengan versi lainnya.

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

Cobalah online!

Arnauld
sumber
Saya pikir itu true, falsedan filenotfoundbukannya 0...
Angs
g=m=>new Date(y,m,7).getDay()menghemat 6 byte.
Neil
7

T-SQL , 213 byte (aturan I / O yang ketat)

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

Kueri di atas mempertimbangkan aturan pemformatan input / output yang ketat.

Input diambil dari kolom stabel bernama t:

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

Tidak Disatukan:

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 (aturan I / O permisif)

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

Jika format input dan output dapat diubah, saya akan memilih untuk memasukkan hari pertama bulan itu, dalam datetimekolom bernama d:

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

Outputnya adalah 1 untuk asimetrik, 0 untuk simetri, NULL untuk simetri terpusat.

Jika kami dapat menjalankannya di server (atau dengan login) yang dikonfigurasi untuk bahasa BRITISH, kami dapat menghapus SET DATEFIRST 1penyimpanan 15 byte lebih banyak.

SQLFiddle 2

Razvan Socol
sumber
1
Kerja bagus. Tidak yakin apakah itu akan berfungsi di semua versi, tetapi pada SQL 2012 saya bisa menghemat 15 byte dengan menggunakan CONVERT(DATETIME,s+'.01')bukan REPLACE. Anda juga dapat meletakkan ruang diFROM (SELECT
BradC
1
Ini bekerja, tetapi tergantung pada DATEFORMATpengaturan. Misalnya, jika kita menggunakan SET LANGUAGE BRITISH, maka CONVERT(DATETIME,'2018.02.01')akan menjadi 2 Januari, bukan 1 Februari.
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

Mengembalikan 2 untuk simetris terpusat, 1 untuk simetris dan 0 untuk asimetris

Angs
sumber
@ TuukkaX Maaf atas kebingungan - ini adalah tantangan pertama saya, saya telah mengubah aturan sehingga mereka juga mengizinkan format output permisif sehingga bisa lebih "dalam semangat" dari kode-golf.
mkierc
5

Python 2, 118 104 byte

Terima kasih kepada Jonathan Allan dan Dead Possum untuk perbaikannya!

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

Memasukkan

  • Pertama adalah tahun
  • Kedua adalah bulan


Keluaran

  • 0 = tidak ada simetri
  • 1 = simetri sentral
  • 2 = simetri lengkap
Jack semua Sekop
sumber
3
Selamat datang di situs ini! Anda tidak boleh berasumsi bahwa input disimpan dalam variabel (seperti Yatau M), jadi ini saat ini potongan dan tidak valid. Namun, jika Anda mengubah variabel ke panggilan input(), ini akan baik-baik saja.
caird coinheringaahing
1
@cairdcoinheringaahing Terima kasih atas sambutannya! Memperbaiki input pengguna :)
Dongkrak semua
Selamat datang! Tweaks untuk -9 byte di sini - semua impor, masukan yang belum dibongkar, _[0]+_[-1]->sum(..)
Dead Possum
1
Beberapa trik untuk mendapatkannya 13 byte di sini
Jonathan Allan
1
... dan byte lain menggunakan trik jumlah Dead Possum - di sini
Jonathan Allan
4

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

Cobalah online!

0 - asimetris

1 - simetris

2 - simetris terpusat

Lebih mudah dibaca:

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

Fungsi murni. Mengambil tahun dan bulan sebagai input dan pengembalian -1untuk bulan asimetris, 0untuk bulan simetris terpusat, dan 1untuk bulan simetris sepenuhnya. Tidak yakin mengapa bahasa ini tidak dapat mengonversi dari hari kerja ke angka secara default ...

LegionMammal978
sumber
2

Utilitas Bash + GNU, 70

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

Input diformat sebagai YYYY/MM.

Outputnya numerik, sebagai berikut:

  • kurang dari 0: simetris terpusat
  • tepat 0: simetris
  • lebih besar dari 0: asimetris

Saya menganggap format output ini dapat diterima untuk pertanyaan ini.

Cobalah online!

Trauma Digital
sumber
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);}

Meminta f(year, month), 0 untuk sepenuhnya simetris, 1 untuk asimetris, 2 untuk simetris terpusat.

tsh
sumber
IIRC Anda dapat menyalahgunakan UB pada GCC dengan mengganti returndengan y=(parameter pertama) dan keluar dari fungsinya.
Quentin
1

Perl 6 , 74 byte

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

Blok kosong, secara implisit fungsi dari 1 argumen, string seperti "2012-02". Pengembalian:

2     # Fully symmetric
True  # Centrally symmetric
False # Asymmetric

Ketika polanya simetris, karena. Hari-minggu meningkat sebesar 1,. Hari-dalam-bulan akan perlu bergerak sebesar 2 agar tetap cocok (bulan akan mulai sehari kemudian tetapi harus berakhir sehari sebelumnya) ), jadi 2 * .day-of-week + .days-in-monthberi kami ukuran celah itu. Modulo 7 seharusnya 1 untuk mendapatkan simetri, tetapi pertama-tama kita dapat dengan murah memeriksa Februari non-lompatan dengan memeriksa total sebelum modulo (Senin dan 28 hari per bulan adalah kombinasi minimum yang mungkin).

Saya terkejut bahwa ini membutuhkan banyak byte, tetapi sepenuhnya 36 byte diperlukan untuk hanya membuat tanggal dan mendapatkan hari dalam seminggu dan hari dalam bulan itu.

Phil H
sumber