Đối xứng của tháng


32

Giới thiệu

Một số tháng hoàn toàn đối xứng , có nghĩa là chúng có đối xứng trung tâm cũng như đối xứng phản xạ , như February of 2010:

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

Vài tháng có chỉ đối xứng trung tâm, giống như February of 1996hoặc tháng hiện tại, các April of 2018:

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

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

Và một số bất đối xứng , giống như tháng trước, March of 2018:

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

Bài tập

Lấy đầu vào dưới dạng một ngày , ví dụ:

  • 2018.04
  • 2018.03
  • 2010.02
  • 1996.02

Xuất đối xứng tương ứng , ví dụ

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

Quy tắc

  • Đây là mã golf, vì vậy số byte nhỏ nhất sẽ thắng.
  • Sơ hở tiêu chuẩn rõ ràng là không được phép.
  • Giả sử rằng tuần bắt đầu bằng thứ Hai (nhờ AngsArnauld đã gợi ý).
  • Chỉ xem xét các năm từ 1900 đến 2100 ( bao gồm ).
  • Các quy tắc định dạng đầu vào và đầu ra được cho phép , có nghĩa là bạn có thể sử dụng bất kỳ định dạng tương đương nào có nguồn gốc từ ngôn ngữ bạn chọn.
  • Dựa vào giải pháp của bạn trên lịch Gregorian .

7
Hãy xem xét rằng ngày là kỳ lạ , bạn có thể muốn chỉ định chính xác các quy tắc hoặc giới hạn đầu vào có thể trong một phạm vi nhỏ (giả sử, 1901-2099)
user202729

2
Những điều cần tránh khi viết thử thách / Thêm nội dung không cần thiết bao gồm "Tạo câu trả lời tính toán f(x)cho mọi thứ xtrong danh sách". Điều gì về "lấy một đầu vào dưới dạng một ngày"?
dùng202729

6
Chào mừng bạn đến với PPCG, và thử thách đầu tiên tốt đẹp! Mặc dù thử thách này là tốt, nhưng trong tương lai nếu bạn muốn có một số phản hồi về thử thách trước khi đăng, bạn có thể đăng nó trong hộp cát .
dùng202729

2
Đầu ra có nên đúng các chuỗi được đề cập, hoặc bất kỳ 3 giá trị riêng biệt nào không?
Uriel

2
(đợi một chút, lịch Gregorian hoặc lịch Julian? Tôi đã đề xuất [1901-2099] nhưng bạn quyết định sử dụng [1900-2100] để chúng khác nhau đối với một số đầu vào)
user202729

Câu trả lời:


20

JavaScript (ES6), 55 byte

Đã lưu 6 byte nhờ @Neil

Đưa đầu vào theo cú pháp currying (year)(month). Trả về falsecho bất đối xứng, truecho đối xứng tập trung và 0hoàn toàn đối xứng.

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

Hãy thử trực tuyến!

Làm sao?

Chúng tôi xác định hàm g () trả về ngày trong tuần của yyyy / mm / 01 , dưới dạng một số nguyên trong khoảng từ 0 = Thứ Hai đến 6 = Chủ Nhật.

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

getDay () thực tế trả về 0 = Chủ nhật thành 6 = Thứ bảy, chúng tôi thay đổi kết quả sang phạm vi dự kiến ​​bằng cách truy vấn cho ngày thứ 7 thay thế.

Sau đó, chúng tôi xác định:

n = g() + g()

Bởi vì hàm tạo của Date mong đợi một tháng có chỉ số 0 và vì g () giảm m sau khi chuyển nó sang Date , nên chúng tôi thực sự tính toán ngày trong tuần của ngày đầu tiên của tháng tiếp theo và sau đó thêm vào ngày hiện tại.

Tháng đối xứng hoàn toàn

Các tháng đối xứng hoàn toàn bắt đầu bằng Thứ Hai và tiếp theo là tháng bắt đầu bằng Thứ Hai. Điều này chỉ có thể cho tháng hai của một năm không nhảy vọt.

- 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

Điều này dẫn đến n = 0 .

Tháng đối xứng trung tâm

Các tháng đối xứng trung tâm là các tháng trong đó tổng số ngày trong tuần của ngày đầu tiên của họ và của tháng tiếp theo là 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

Do đó thử nghiệm thứ hai: n == 7 .


Không tích hợp, 93 byte

Sử dụng sự phù hợp của Zeller . Định dạng I / O tương tự như các phiên bản khác.

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

Hãy thử trực tuyến!


Tôi nghĩ rằng nó là true, falsefilenotfoundthay vì 0...
Angs

g=m=>new Date(y,m,7).getDay()tiết kiệm 6 byte.
Neil

7

T-SQL , 213 byte (quy tắc I / O nghiêm ngặt)

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

Các truy vấn trên xem xét các quy tắc định dạng đầu vào / đầu ra nghiêm ngặt.

Đầu vào được lấy từ cột scủa bảng có tên t:

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

Ung dung:

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 (quy tắc I / O cho phép)

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

Nếu định dạng của đầu vào và đầu ra có thể thay đổi, tôi sẽ chọn nhập ngày đầu tiên của tháng, trong một datetimecột có tên d:

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

Đầu ra sẽ là 1 cho đối xứng, 0 cho đối xứng, NULL cho đối xứng tập trung.

Nếu chúng tôi có thể chạy nó trên máy chủ (hoặc có thông tin đăng nhập) được định cấu hình cho ngôn ngữ BRITISH, chúng tôi có thể xóa SET DATEFIRST 1lưu thêm 15 byte.

SQLFiddle 2


1
Công việc tốt đẹp. Không chắc nó có hoạt động trong tất cả các phiên bản không, nhưng trên SQL 2012 tôi đã có thể lưu 15 byte bằng cách sử dụng CONVERT(DATETIME,s+'.01')thay vì REPLACE. Bạn cũng có thể thả khoảng trống vàoFROM (SELECT
BradC

1
Nó hoạt động, nhưng nó phụ thuộc vào DATEFORMATcài đặt. Ví dụ: nếu chúng ta sử dụng SET LANGUAGE BRITISH, thì đó CONVERT(DATETIME,'2018.02.01')sẽ là ngày 2 tháng 1, thay vì ngày 1 tháng 2.
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

Trả về 2 cho đối xứng tập trung, 1 cho đối xứng và 0 cho bất đối xứng


@TuukkaX Xin lỗi vì sự nhầm lẫn - đây là thử thách đầu tiên của tôi, tôi đã thay đổi các quy tắc để họ cũng cho phép các định dạng đầu ra cho phép để nó có thể "tinh thần" hơn trong môn đánh gôn.
mkierc

5

Python 2, 118 104 byte

Cảm ơn Jonathan Allan và Dead Possum vì những cải tiến!

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

Đầu vào

  • Đầu tiên là năm
  • Thứ hai là tháng


Đầu ra

  • 0 = không đối xứng
  • 1 = đối xứng trung tâm
  • 2 = đối xứng hoàn toàn

3
Chào mừng đến với trang web! Bạn không thể cho rằng đầu vào được lưu trữ trong một biến (chẳng hạn như Yhoặc M), vì vậy đây hiện là đoạn trích và không hợp lệ. input()Tuy nhiên, nếu bạn thay đổi các biến thành các cuộc gọi , điều này sẽ hoàn toàn ổn.
caird coinheringaahing

1
@cairdcoinheringaahing Cảm ơn bạn đã chào đón! Đã sửa lỗi đầu vào của người dùng :)
Jack của tất cả các Spades

Chào mừng bạn Tinh chỉnh cho -9 byte tại đây - tất cả nhập, giải nén đầu vào, _[0]+_[-1]->sum(..)
Dead Possum

1
Một số thủ thuật để giảm 13 byte ở đây
Jonathan Allan

1
... và một byte khác sử dụng thủ thuật tổng hợp của Dead Possum - tại đây
Jonathan Allan

4

Đỏ , 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]

Hãy thử trực tuyến!

0 - không đối xứng

1 - đối xứng

2 - đối xứng trung tâm

Dễ đọc hơn:

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

Toán học, 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}}&

Chức năng thuần túy. Lấy năm và tháng làm đầu vào và trả lại -1cho các tháng không đối xứng, 0cho các tháng đối xứng tập trung và 1cho các tháng đối xứng hoàn toàn. Không chắc chắn tại sao ngôn ngữ này không thể chuyển đổi từ một ngày trong tuần sang một số theo mặc định ...


2

Tiện ích Bash + GNU, 70

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

Đầu vào được định dạng như YYYY/MM.

Đầu ra là số, như sau:

  • nhỏ hơn 0: đối xứng tập trung
  • chính xác 0: đối xứng
  • lớn hơn 0: không đối xứng

Tôi giả sử định dạng đầu ra này là chấp nhận được cho câu hỏi này.

Hãy thử trực tuyến!


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

Gọi f(year, month), 0 cho đối xứng hoàn toàn, 1 cho bất đối xứng, 2 cho đối xứng tập trung.


IIRC bạn có thể lạm dụng UB trên GCC bằng cách thay thế returnbằng y=(tham số đầu tiên) và thoát khỏi chức năng.
Quentin

1

Perl 6 , 74 byte

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

Khối trần, mặc nhiên là hàm của 1 đối số, một chuỗi như "2012-02". Trả về:

2     # Fully symmetric
True  # Centrally symmetric
False # Asymmetric

Khi mô hình đối xứng, vì .day-of-week tăng 1, .day-in-tháng sẽ cần di chuyển 2 để vẫn khớp (tháng sẽ bắt đầu một ngày sau đó nhưng cần kết thúc sớm hơn một ngày ), vì vậy 2 * .day-of-week + .days-in-monthcung cấp cho chúng tôi một thước đo khoảng cách đó. Modulo 7 phải là 1 để có được sự đối xứng, nhưng trước tiên chúng ta có thể kiểm tra giá rẻ cho tháng không nhảy vọt bằng cách kiểm tra tổng số đó trước modulo (Thứ hai và 28 ngày mỗi tháng là sự kết hợp tối thiểu có thể).

Tôi ngạc nhiên rằng việc này cần rất nhiều byte, nhưng cần đầy đủ 36 byte cho việc chỉ cần hẹn hò và lấy ngày trong tuần và các ngày trong tháng đó.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.