月の対称性


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

2
チャレンジを書くとき/不必要なものを追加するときは、「リスト内のf(x)すべての回答を計算する」ことを避けてくださいx。「日付の形式で入力する」のはどうですか?
user202729

6
PPCGへようこそ。最初の挑戦です。このチャレンジは優れていますが、将来、投稿する前にチャレンジに関するフィードバックが必要な場合は、サンドボックスに投稿できます。
user202729

2
出力は、厳密に言及された文字列、または任意の3つの異なる値ですか
ウリエル

2
(ちょっと待って、グレゴリオ暦またはユリウス暦?[1901-2099]を提案しましたが、[1900-2100]を使用することを決めたため、入力によって異なる場合があります)
user202729

回答:


20

JavaScript(ES6)、55バイト

@Neilのおかげで6バイト節約

カリー化構文の入力を受け取ります(year)(month)false非対称、true中心対称、0完全対称の場合に戻ります。

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

オンラインでお試しください!

どうやって?

yyyy / mm / 01の曜日を返す関数g()を、0 =月曜日と6 =日曜日の間の整数として定義します。

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

そのためgetDay()ネイティブに戻っ0に=日曜日6 =土曜日、私たちが代わりに7日目のために照会することによって期待される範囲に結果をシフトします。

次に定義します:

n = g() + g()

コンストラクタなので日が 0 -インデックス付きヶ月を期待しているのでグラム()がデクリメントメートルを した後にそれを渡す、私たちは、実際には最初の最初の日の曜日計算の月をし、現在の1のものを追加します。

完全に対称的な月

完全に対称的な月は月曜日から始まり、月が続く月も続きます。これは、うるう年でない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

したがって、2番目のテスト: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

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

1
動作しますが、DATEFORMAT設定に依存します。たとえば、を使用するとSET LANGUAGE BRITISHCONVERT(DATETIME,'2018.02.01')2月1日ではなく1月2日になります。
ラズバンソコル

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バイト

改善してくれたジョナサン・アランとデッド・ポッサムに感謝します!

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

入力

  • 最初は年です
  • 2番目は月です


出力

  • 0 =対称性なし
  • 1 =中心対称性
  • 2 =完全な対称性

3
サイトへようこそ!あなたはその入力を想定しなくてもよい(例えば、変数に格納されているY又はM)、これは、現在のスニペット、無効です。input()ただし、変数を呼び出しに変更する場合、これはまったく問題ありません。
コイナーリンガーをケアします。

1
@cairdcoinheringaahing歓迎してくれてありがとう!ユーザー入力の修正:)
すべてのスペードのジャック

ようこそ!ここで-9バイトの調整-すべてのインポート、アンパックされた入力、_[0]+_[-1]->sum(..)
Dead Possum


1
...そして、Dead Possumのサムトリックを使用する別のバイト- ここで
ジョナサンアラン

4

199、168 161バイト

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

Invoke f(year, month)、0は完全に対称、1は非対称、2は中心対称。


IIRCではreturny=(最初のパラメーター)に置き換えて関数から抜けることにより、GCCでUBを悪用できます。
クエンティン

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

パターンが対称の場合、.day-of-weekが1増加するため、.days-in-monthは一致するために2移動する必要があります(月は1日後に開始しますが、1日前に終了する必要があります) )、2 * .day-of-week + .days-in-monthそのギャップの尺度を提供します。モジュロ7は対称性を得るために1にする必要がありますが、モジュロの前にその合計をチェックすることで、最初に飛躍のない2月を簡単にチェックできます(月曜日と28日が最小の組み合わせです)。

これには非常に多くのバイトが必要であることに驚いていますが、日付を作成してその月の曜日と曜日を取得するには、完全に36バイトが必要です。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.