月的对称性


32

介绍

有些月份是完全对称的,这意味着它们具有中心对称性反射对称性,例如February of 2010

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

某些月份只有中央对称,例如February of 1996或当前月份April of 2018

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

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

还有一些是不对称的,例如上个月的March of 2018

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

任务

日期形式输入,例如:

  • 2018.04
  • 2018.03
  • 2010.02
  • 1996.02

输出相应的对称性,例如

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

规则

  • 这是代码高尔夫,因此最少的字节数获胜。
  • 显然不允许出现标准漏洞。
  • 假设一周从星期一开始(感谢AngsArnauld的建议)。
  • 仅考虑1900到2100()之间的年份。
  • 输入和输出格式设置规则是允许的,这意味着您可以使用所选语言固有的任何等效格式。
  • 将解决方案基于公历

7
考虑到日期很奇怪,您可能想要确切地指定规则,或将可能的输入限制在较小的范围内(例如1901-2099)
user202729 '18

2
编写挑战/添加不必要的内容时应避免的事情包括“使列表中的f(x)每个答案都得到计算x”。关于“以日期形式输入”呢?
user202729'4

6
欢迎来到PPCG,也是第一个挑战!尽管这个挑战很好,但是将来如果您想在发布之前对挑战提出一些反馈,可以将其发布在沙箱中
user202729'4

2
输出应该严格是所提到的字符串,还是任何3个不同的值?
Uriel '18

2
(请稍等,公历还是儒略历?我建议使用[1901-2099],但您决定使用[1900-2100],因此对于某些输入它们会有所不同)
user202729 '18

Answers:


20

JavaScript(ES6),55个字节

@Neil节省了6个字节

以currying语法接受输入(year)(month)。返回false不对称,true中心对称和0完全对称。

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

在线尝试!

怎么样?

我们定义函数g(),该函数返回yyyy / mm / 01的工作日,为介于 0 =星期一和6 =星期日。

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

因为getDay()本地返回0 =周日到6 =周六,因此我们通过查询第7天来将结果移至预期范围。

然后我们定义:

n = g() + g()

因为Date的构造函数期望索引为0的月份,并且g()将m 传递给以下变量递减m日期,我们其实首先计算的第一天工作日接下来的一个月,然后补充说,当前一个。

完全对称的月份

完全对称的月份从星期一开始,然后是一个月份,星期一也从星期一开始。这仅适用于非le年的2月。

- 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

这将导致 n = 0

中央对称月份

中央对称月份是指第一天和下个月的工作日之和为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

因此,第二个测试:n == 7


无内置93字节

使用Zeller的全等。与其他版本相同的I / O格式。

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

在线尝试!


我以为是truefalsefilenotfound不是0……
Angs '18

g=m=>new Date(y,m,7).getDay()节省6个字节。
尼尔

7

T-SQL 213字节(严格的I / O规则)

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

上面的查询考虑了严格的输入/输出格式化规则。

输入来自s名为的表的列t

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

取消高尔夫:

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个字节(允许的I / O规则)

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

如果输入和输出的格式可以更改,我将选择输入月份的第一天,该datetime列名为d

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

对于不对称,输出将为1,对于等距,输出将为0,对于中央对称,输出将为NULL。

如果我们可以在配置为BRITISH语言的服务器上(或使用登录名)运行它,则可以删除SET DATEFIRST 1节省的15个字节。

SQLFiddle 2


1
辛苦了 不知道它是否可以在所有版本中使用,但是在SQL 2012上,我可以使用CONVERT(DATETIME,s+'.01')代替来保存15个字节REPLACE。您也可以在FROM (SELECT
BradC '18

1
它可以工作,但是取决于DATEFORMAT设置。例如,如果使用SET LANGUAGE BRITISHCONVERT(DATETIME,'2018.02.01')则将是1月2日,而不是2月1日。
Razvan Socol '18

5

Haskell,170个字节

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

返回2表示中心对称,1表示对称,0表示非对称


@TuukkaX对不起,很困惑-这是我的第一个挑战,我已经更改了规则,因此它们也允许使用允许的输出格式,因此可以使代码高尔夫球更“符合我的意愿”。
mkierc

5

Python 2 118个 104字节

感谢Jonathan Allan和Dead Possum所做的改进!

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

Python 3中,122个 105字节

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

输入值

  • 首先是年份
  • 二个月


输出量

  • 0 =无对称
  • 1 =中心对称
  • 2 =完全对称

3
欢迎光临本站!您可能不会假定输入存储在变量中(例如YM),因此当前是一个摘要,无效。input()但是,如果将变量更改为call,则完全可以。
caird coinheringaahing'Apr 1'18

1
@cairdcoinheringaahing谢谢您的欢迎!固定用户输入:)
所有锹的杰克

欢迎!在此处调整-9个字节-所有导入,未打包的输入_[0]+_[-1]->sum(..)
Dead Possum

1
一些技巧,以它弄下来的13个字节在这里
乔纳森·艾伦

1
...以及使用Dead Possum的总和的另一个字节- 在这里
Jonathan Allan

4

红色199,168161字节

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]

在线尝试!

0-不对称

1-对称

2-中央对称

更具可读性:

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个字节

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

纯功能。将年和月作为输入,并返回-1不对称月份,0中央对称月份和1完全对称月份的返回值。不确定为什么默认情况下无法将此语言从工作日转换为数字...


2

Bash + GNU实用程序,70

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

输入格式为 YYYY/MM

输出为数字,如下所示:

  • 小于0:中心对称
  • 正好0:对称
  • 大于0:不对称

我认为此问题可接受这种输出格式。

在线尝试!


1

C,111字节

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

调用f(year, month),0表示完全对称,1表示不对称,2表示中心对称。


IIRC你可以通过更换GCC滥用UB returny=(第一个参数)和下降的功能了。
Quentin '18

1

Perl 6,74个字节

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

裸块,隐式为1参数的函数,类似的字符串"2012-02"。返回值:

2     # Fully symmetric
True  # Centrally symmetric
False # Asymmetric

如果模式是对称的,则当星期几增加1时,月中的天数需要移动2才能匹配(该月将在一天后开始,但需要在一天前结束) ),因此可以2 * .day-of-week + .days-in-month让我们对这一差距进行衡量。模7应当为1,以获得对称性,但我们首先可以通过在模之前检查总数(星期一和每月28天是最小的可能组合),廉价地检查2月的非-游。

我很惊讶这占用了这么多字节,但是只需要一个完整的36个字节就可以创建一个日期并获取该月中的星期几和几天。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.