最後の月曜日


27

10月31日月曜日はハロウィーンです。そして、それは私に考えさせられました-月の他の月は月の最後の日であるのだろうか?

入力

  • 年を表す任意の便利な形式の正の整数10000 > y > 0
  • 必要に応じて、入力にゼロを埋め込むことができます(たとえば、0025yearの25場合)。

出力

  • 月の最終日が月曜日であるその年の月のリスト。
  • これは、読者にとって明確である限り、月名(例January, March, October)、ショートネーム(Jan, Mar, Oct)、数字(1, 3, 10)、個別の行、リスト、区切りなどとして使用できます。
  • 出力形式は一貫している必要があります。
    • すべての年の入力(つまり、一部の入力では月名を、他の入力では月番号を出力できません)
    • 出力ごとだけでなく、一貫として(つまり、あなたは出力できない1ためJanuary同じ出力のJulためにJuly
    • 基本的に、1つの形式を選択し、それに固執します。

ルール

  • グレゴリオ暦の入力/出力、さらにはを想定しy = 1ます。
  • うるう年は適切に説明する必要があります(注意:毎年4で割り切れる年を除き、100で割り切れる年ではなく、400-1700、1800、1900で割り切れる場合を除き、すべてがうるう年ではありませんでしたが、2000はそうでした)。
  • 任意の組み込みツールまたはその他の日付計算ツールを使用できます。
  • 完全なプログラムまたは機能のいずれかが受け入れられます。関数の場合、出力する代わりに出力を返すことができます。
  • 標準的な抜け穴は禁止されています。
  • これはので、通常のゴルフルールがすべて適用され、最短のコード(バイト単位)が勝ちます。

   1 --> Apr, Dec
 297 --> May
1776 --> Sep
2000 --> Jan, Jul
2016 --> Feb, Oct
3385 --> Jan, Feb, Oct

リーダーボード



1
関連しているが重複していないか?
エルペドロ

@ElPedro関連するが重複はしない。最初はビルトインを許可せず、固定の日付/日のコンボ(13日金曜日)を要求しますが、2番目は1900年から3015
。– AdmBorkBork

すみません@TimmD。あなたのコメントに対する私の誤解。
エルペドロ

1
@ElPedro問題ありません!質問をせずに何か不明瞭なことをするよりも、質問をして明確にしたいです。
AdmBorkBork

回答:


2

dfnscal使用したDyalog APL、バージョン15.0:22; バージョン16.0:19 バイト

cal関数にはデフォルトのインストールが付属しており、単にを入力し)copy dfnsます。

バージョン15.0: ∊⎕{⍵/⍨2=≢⍎⊢⌿cal⍺⍵}¨⍳12

参加(フラット化)

⎕{... 次の匿名関数への左引数としての数値入力。右辺の各値を順番に右引数として取得

⍵/⍨ 引数if(そうでなければ空のリストを与える)

2= 2(日曜日と月曜日)は次と等しい

の集計

の数字

⊢⌿ の一番下の行

cal のカレンダー

⍺⍵ 年の左引数、月の右引数、後者は

⍳12 1から12

バージョン16.0: ⍸2=⎕{≢⍎⊢⌿cal⍺⍵}¨⍳12

インデックス

2= 2つの等しい(日曜日と月曜日)

⎕{... 次の匿名関数への左引数としての数値入力。右辺の各値を順番に右引数として取得

の集計

の数字

⊢⌿ の一番下の行

cal のカレンダー

⍺⍵ 年の左引数、月の右引数、後者は

⍳12 1から12


19

JavaScript(Firefox 30 +)、112 109 103 95バイト

ビルマインなし

y=>[for(m of(i=0,y%4|y%400*!(y%100)&&6)+"63153042641")if((i++,y+(y>>2)-(y/100|0)*3/4|0)%7==m)i]

次に、107バイトのES6バージョンを示します。

y=>[...(y%4|y%400*!(y%100)&&6)+"63153042641"].map((m,i)=>(y+(y>>2)-(y/100|0)*3/4|0)%7-m?0:i+1).filter(x=>x)

そして、これが私の以前の試み、123 113バイトのES6です。

y=>[(l=y%4|y%400*!(y%100))?[7]:[1,7],[4,12],[9],[3,6],[8,11],[5],l?[1,2,10]:[2,10]][(y+(y>>2)-(y/100|0)*3/4|0)%7]

説明

特定の年の曜日は次のように計算されます。

y+(y>>2)-(y/100|0)*3/4|0)%7

言い換えると:

  • 取るy
  • 4年前の数字yy>>2)を追加します。
  • 100年前の数を引きますyy/100|0)。
  • 400年前の数を追加してくださいy; これは1/4 y/100|0なので、使用します*3/4|0

次に、結果を7でモジュロします。0日曜日、1月曜日などを意味する場合、結果はその年の12月31日の曜日に対応します。したがって、12月については、結果がであるかどうかを確認し1ます。これにより、文字列の最後の文字が得られます。

11月の最終日は、12月の最終日の31日前です。これは、11月の最終日が月曜日である場合、12月31日は(1 + 31) % 7 = 4木曜日である必要があることを意味します。

この手順は、3月(a 3)に戻るまで繰り返されます。うるう日があるかどうかにかかわらず、2月の最終日は3月の最終日の31日前なので、それも計算できます(これは(3 + 31) % 7 = 6)。トリッキーな部分は、1月の正しい値を見つけることです。

  • うるう年の場合、1月の最終日は2月の最終日より29日前であるため、結果はになり(6 + 29) % 7 = 0ます。
  • それ以外の場合は、2月の最終日の28日前になり(6 + 28) % 7 = 6ます。

次のスニペットでle年かどうかを計算できます。

!(y%400)|y%100*!(y%4)

これは0、if年でyはない場合に、そうでない場合は正の整数を返します。これは私たちを導く

!(y%400)|y%100*!(y%4)?0:6

1月の日を計算します。ただし、条件を逆にすることでより良い結果を得ることができます。

y%4|y%400*!(y%100)?6:0

とにかく偽の結果は常に0なので、次のように減らすことができます。

y%4|y%400*!(y%100)&&6

貴重なバイトをもう1つ保存します。

すべてをまとめて、文字列内の各文字をループ処理し、それぞれが12月31日の曜日に等しいかどうかを確認します。一致するもののインデックスを保持し、最後にこの配列を返します。それが、組み込みなしでうるう年の計算を行う方法です。


Owww ...私の脳、あなたはそれでうるう年を説明しましたか?
魔法のタコUr

2
@carusocomputingそれ!(y%4)*y%100|!(y%400)が目的です。毎年4で割り切れる場合を除き、100で割り切れる年を除き、400で割り切れる場合を除き
mbomb007

うまくいけば、y+(y>>2)+(z=y/25>>2)+(z>>2)まだ1バイト節約できます。
ニール

@ニールありがとう、しかし私はより良い方法を見つけました:
ETHproductions

いいね を使用してバッチポートに6バイトを保存しました(y*5/4-(y/100)*3/4)
ニール

11

JavaScript(Firefox 30-57)、67 65 64 63 61バイト

y=>[for(_ of(m='')+1e11)if(new Date(y+400,++m).getDay()==2)m]

保存された2人の 4 @ETHproductionsに6バイトのおかげ。月を逆順に出力することにより、別のバイトを保存しました。


なしでウィングすることで2バイト節約できると思います.keys()y=>[for(_ of(m=0,Array(12)))if(new Date(y+400,++m).getDay()==2)m]
ETHproductions

@ETHproductions順序を逆にすることで、さらにバイトを節約できます!
ニール

逆順でも問題ありません。出力のフォーマットは、この課題の興味深い部分ではありません。
AdmBorkBork

配列内包表記は、仕様から削除されたので、私たちの方針は何ですか?
MayorMonty

Array(12)完全に スキップすることにより、さらに2バイト節約できますy=>[for(_ of(m=0,1e11+""))if(new Date(y+400,++m).getDay()==2)m]
。– ETHproductions

8

MySQL、183 134 129 106バイト

SET @y=2016;SELECT help_topic_id AS m FROM mysql.help_topic HAVING m BETWEEN 1 AND 12 AND 2=DAYOFWEEK(LAST_DAY(CONCAT(@y,-m,-1)))

2016希望する年に置き換えます。走る

Rev. 2:help_topics一時テーブルを作成する代わりに、デフォルトのインストールでテーブルを使用しました。

Rev.3:arossの-トリックを採用し、の引用符も省略できることに気付きました"-1"
ただし、-1MySQL では必須です。完全な日付が必要です。

Rev.4:制限m BETWEEN 1 AND 12m>0 AND m<13(-6)として実行できますが、まったく必要ありません-無効な値は無視されます。警告はカウントされますが、リストされません。


あなたは本当にテーブルシーマmysqlが必要ですか?mariadb.com/kb/en/mariadb/mysqlhelp_topic-table
イェルクHülsermann

@JörgHülsermannあなたの言いたいことはわかりません。
タイタス

仕事FROM help_topicなしにすべきmysql.ですか?私は試していない
ヨルクヒュルサーマン

@JörgHülsermannを追加する場合のみUSE mysql;何らかの方法で正しいデータベースを選択する必要があります。
タイタス

5

Perl、64バイト

+1を含む -n

STDINに入力を与えます。

perl -M5.010 mon.pl <<< 2016

mon.pl

#!/usr/bin/perl -n
map$b.=$/.gmtime$_.e4,-7e6..3e7;say$b=~/on (\S+ )\S.* $_.* 1 /g

5

バッチ、160 152バイト

@set/ay=%1,m=0,j=6*!(!(y%%4)*(y%%100)+(y%%400)),y=(y*5/4-y/100*3/4)%%7
@for %%d in (%j% 6 3 1 5 3 0 4 2 6 4 1)do @set/am+=1&if %%d==%y% call echo %%m%%

@ETHproductionの回答のポート。197 189バイトの月の略語の場合:

@set/ay=%1,j=6*!(!(y%%4)*(y%%100)+(y%%400)),y=(y*5/4-y/100*3/4)%%7
@for %%m in (Jan.%j% Feb.6 Mar.3 Apr.1 May.5 Jun.3 Jul.0 Aug.4 Sep.2 Oct.6 Nov.4 Dec.1)do @if %%~xm==.%y% call echo %%~nm

4

J、48 34 33バイト

[:I.(2=7|_2#@".@,@{.])&>@calendar

@の助けを借りて15バイトを保存しました Adámのました

組み込みのカレンダーを使用して、月を表す文字列の配列を生成し、各文字列を解析して、最後の月曜日が月の最後の日であるかどうかを判断します。各月をそれぞれの月番号として出力します。あれは、Jan = 0Feb = 1、...、 Dec = 11

の出力 calendar

   _3 ]\ calendar 2016
┌─────────────────────┬─────────────────────┬─────────────────────┐
│         Jan         │         Feb         │         Mar         │
│ Su Mo Tu We Th Fr Sa│ Su Mo Tu We Th Fr Sa│ Su Mo Tu We Th Fr Sa│
│                 1  2│     1  2  3  4  5  6│        1  2  3  4  5│
│  3  4  5  6  7  8  9│  7  8  9 10 11 12 13│  6  7  8  9 10 11 12│
│ 10 11 12 13 14 15 16│ 14 15 16 17 18 19 20│ 13 14 15 16 17 18 19│
│ 17 18 19 20 21 22 23│ 21 22 23 24 25 26 27│ 20 21 22 23 24 25 26│
│ 24 25 26 27 28 29 30│ 28 29               │ 27 28 29 30 31      │
│ 31                  │                     │                     │
├─────────────────────┼─────────────────────┼─────────────────────┤
│         Apr         │         May         │         Jun         │
│ Su Mo Tu We Th Fr Sa│ Su Mo Tu We Th Fr Sa│ Su Mo Tu We Th Fr Sa│
│                 1  2│  1  2  3  4  5  6  7│           1  2  3  4│
│  3  4  5  6  7  8  9│  8  9 10 11 12 13 14│  5  6  7  8  9 10 11│
│ 10 11 12 13 14 15 16│ 15 16 17 18 19 20 21│ 12 13 14 15 16 17 18│
│ 17 18 19 20 21 22 23│ 22 23 24 25 26 27 28│ 19 20 21 22 23 24 25│
│ 24 25 26 27 28 29 30│ 29 30 31            │ 26 27 28 29 30      │
│                     │                     │                     │
├─────────────────────┼─────────────────────┼─────────────────────┤
│         Jul         │         Aug         │         Sep         │
│ Su Mo Tu We Th Fr Sa│ Su Mo Tu We Th Fr Sa│ Su Mo Tu We Th Fr Sa│
│                 1  2│     1  2  3  4  5  6│              1  2  3│
│  3  4  5  6  7  8  9│  7  8  9 10 11 12 13│  4  5  6  7  8  9 10│
│ 10 11 12 13 14 15 16│ 14 15 16 17 18 19 20│ 11 12 13 14 15 16 17│
│ 17 18 19 20 21 22 23│ 21 22 23 24 25 26 27│ 18 19 20 21 22 23 24│
│ 24 25 26 27 28 29 30│ 28 29 30 31         │ 25 26 27 28 29 30   │
│ 31                  │                     │                     │
├─────────────────────┼─────────────────────┼─────────────────────┤
│         Oct         │         Nov         │         Dec         │
│ Su Mo Tu We Th Fr Sa│ Su Mo Tu We Th Fr Sa│ Su Mo Tu We Th Fr Sa│
│                    1│        1  2  3  4  5│              1  2  3│
│  2  3  4  5  6  7  8│  6  7  8  9 10 11 12│  4  5  6  7  8  9 10│
│  9 10 11 12 13 14 15│ 13 14 15 16 17 18 19│ 11 12 13 14 15 16 17│
│ 16 17 18 19 20 21 22│ 20 21 22 23 24 25 26│ 18 19 20 21 22 23 24│
│ 23 24 25 26 27 28 29│ 27 28 29 30         │ 25 26 27 28 29 30 31│
│ 30 31               │                     │                     │
└─────────────────────┴─────────────────────┴─────────────────────┘

使用法

   f =: [:I.(2=7|_2#@".@,@{.])&>@calendar
   f 1
3 11
   f 297
4
   f 1776
8
   f 2000
0 6
   f 2016
1 9
   f 3385
0 1 9

説明

[:I.(2=7|_2#@".@,@{.])&>@calendar  Input: year Y
                         calendar  Get 12 boxes each containing a month
    (                )&>@          Operate on each box
                    ]                Identity, get the box
         _2       {.                 Take the last two strings
                ,@                   Flatten it
             ".@                     Parse it into an array of integers
           #@                        Get the length
       7|                            Take it modulo 7
     2=                              Test if it equals 2 - it will either
                                     have two days or 9 days in the last
                                     two lines if the end is on a Monday
[:I.                               Return the indices containing a true value

待って、カレンダーは実際にアスキーアートを出力しますか?
破壊可能なレモン

@DestructibleWatermelon正確には、出力形式はcalendar12個のボックスの配列で、各ボックスには文字の2d配列が含まれています
マイル

Jで「それぞれ」を行う方法すらわかりませんが、これはすでにI.7=;#&.>".&.>,&.>_2{.&.>calendar 2016かなり短くなっています。
アダム

アダム@おかげで、それがより良い方法を使用していますが、それはJ. Iには動詞ではないのですが、それはまだ助けになると思うけれども
マイル

私の意図は刺激することだけでした。私はそれが動詞ではないことを知っています。
アダム

4

Mathematica、62 57バイト

DayName@DayRange[{#},{#+1},"EndOfMonth"]~Position~Monday&

匿名関数。入力として数値を受け取り、出力として数値の単一要素リストのリストを返します。私は正直に言って、それがどのように機能するのかもうわかりません。


4

Perl + cal、46バイト

say`cal $_ $ARGV[0]`=~/\n.{5}\n/&&$_ for 1..12

例:

$ perl -E 'say`cal $_ $ARGV[0]`=~/\n.{5}\n/&&$_ for 1..12' 2016

2







10


$

1
厳密に言えば、これはperl :-pではなく、perl + calです。たとえば、私のWindowsマシンにはperlがありますが、これはそこで動作しません。
哲学

フェアポイント、これと私のbashの試みを更新しました。
スティーブ

4

Java 7、186 182 172バイト

4バイトを保存してくれたkevinに
感謝10バイトを保存してくれた@cliffrootに感謝

int[]f(int n){int c=n-1,x=c*365+c/4+c/400-c/100,k=0,b[]={3,(n%4<1&n%100>0)|n%400<1?1:0,3,2,3,2,3,3,2,3,2,3},a[]=new int[12];for(int i:b)a[k++]=(x+=i+28)%7==1?1:0;return a;}

食べない

int[] f(int n) {
 int c=n-1,x=c*365+(c/4)+(c/400)-(c/100),k=0,
   b[] = {3,(n % 4 < 1 & n % 100 > 0) | n % 400 < 1 ? 1 : 0
                                     ,3,2,3,2,3,3,2,3,2,3},a = new int[ 12 ];

 if ( (n % 4 < 1 & n % 100 > 1) | n % 400 < 1 )
     b[ 1 ] = -1;
 for (int i : b)
    a[ k++ ] = (x += i + 28) % 7 == 1 ? 1 : 0;

return a;
     }

このバージョンは@cliffrootによって提供されます168バイト

 static int[] f(int n) {
 int b = 13561787 | ( (n%4 < 1 & n%100 > 0) | n%400 < 1 ? 1 << 20 : 0 ),
           x = --n*365 + n/4 + n/400 - n/100,a[]=new int[12],k=0;
    while (k < 12)
    a[k++] = (x += (b >> 24 - k*2&3 ) + 28) % 7 == 1 ? 1 : 0;
  return a;   }
    }

出力サンプル

1 1 0 0 0 0 0 0 0 1 0 0(for input 3385)

1
私が答えを書いた後、自分ですべてを計算すると短くなることを知っていn%4==0ましたn%4<1。します。n%400==0n%400<1int c=...;int[]b=...,a=...int c=...,b[]=...,a[]=...
ケビンCruijssen

1
bそして、aで定義することができますint。このようなパーツint ... ,b[]=...,a[]=...
オリヴィエ・グレゴワール

1
int[]f(int n){int x=--n*365+n/4+n/400-n++/100,k=0,b[]={1,(n%4<1&n%100>0)|n%400<1?-1:-2,1,0,1,0,1,1,0,1,0,1},a[]=new int[12];for(int i:b)a[k++]=(x+=i+30)%7==1?1:0;return a;}数バイトの節約
クリフルート

1
また、変更することができますbb[]={3,(n%4<1&n%100>0)|n%400<1?1:0,3,2,3,2,3,3,2,3,2,3}してi+30i+282バイト以上のために
cliffroot

1
さらに3バイトint[]f(int n){int b=13561787|((n%4<1&n%100>0)|n%400<1?1<<20:0),x=--n*365+n/4+n/400-n/100,a[]=new int[12],k=0;while(k<12)a[k++]=(x+=(b>>24-k*2&3)+28)%7==1?1:0;return a;}
クリフルート

3

Python 2、100バイト

あー 日付のある数学は、私が望むほど単純ではありません。

lambda y:[m+1for m in range(12)if(date(y,12,31)if m>10else(date(y,m+2,1)-timedelta(1))).weekday()<1]

オンラインで試す

同じ長さ:

lambda y:[m-1for m in range(2,14)if(date(y,12,31)if m>12else(date(y,m,1)-timedelta(1))).weekday()<1]

私はこれでPythonを試すことすらしませんでした。素晴らしい努力。
エルペドロ

3

MATL、21バイト

12:"G@QhO6(YO9XO77=?@

月は数字で表示されます。

オンラインでお試しください!または、すべてのテストケースを確認します

説明

これは、日付変換組み込み関数を使用します。指定された年について、月の最終月がどの月かをテストします。

月の最終日k028、29、30 、または31)を明示的に指定する代わりに、-th day of month を指定しますk+1。これは同等で、月や年に依存しません。

12:      % Push [1 2 ... 12] (months)
"        % For each month k
  G      %   Push input
  @Q     %   Push k+1
  h      %   Concatenate
  O6(    %   Postpend four zeros. For example, for input 2016 and month k=1 
         %   (first iteration) this gives [2016 2 0 0 0 0] (year, month, day,
         %   hour, min, sec). The 0-th day of month k+1 is the same as the
         %   last day of month k.
  YO     %   Convert the above 6-element date vector to date number
  9XO    %   Convert date number to date string with output format 9, which 
         %   is weekday as a capital letter
  77=    %   Is it an 'M'?
  ?      %   If so
    @    %     Push current month (will be implicitly displayed)

3

Bash + GNUユーティリティ、56バイト

seq -f1month-1day$1-%g-1 12|date -f- +%B%u|sed -n s/1//p

dateバージョン8.25 が必要なようです。Ideoneの8.23バージョンではカットされません。


3

Excel、537バイト

なぜなら–知っている– Excel!

A1で入力年を取得します。月の16進数リストを返します。1 = 1月、C = 12月。各月は1桁なので、セパレータは必要ありません。

=IF(2=WEEKDAY(EOMONTH(DATE(A1,1,1),0)),1,"")&IF(2=WEEKDAY(EOMONTH(DATE(A1,2,1),0)),2,"")&IF(2=WEEKDAY(EOMONTH(DATE(A1,3,1),0)),3,"")&IF(2=WEEKDAY(EOMONTH(DATE(A1,4,1),0)),4,"")&IF(2=WEEKDAY(EOMONTH(DATE(A1,5,1),0)),5,"")&IF(2=WEEKDAY(EOMONTH(DATE(A1,6,1),0)),6,"")&IF(2=WEEKDAY(EOMONTH(DATE(A1,7,1),0)),7,"")&IF(2=WEEKDAY(EOMONTH(DATE(A1,8,1),0)),8,"")&IF(2=WEEKDAY(EOMONTH(DATE(A1,9,1),0)),9,"")&IF(2=WEEKDAY(EOMONTH(DATE(A1,10,1),0)),"A","")&IF(2=WEEKDAY(EOMONTH(DATE(A1,11,1),0)),"B","")&IF(2=WEEKDAY(EOMONTH(DATE(A1,12,1),0)),"C","")

例:A1には2016が含まれています。B1には上記の数式が含まれており2A、2月と10月を意味するとして表示されます。


3

PHP、109の180 159バイト

for($z=$argv[1];$m++<12;)if(date(N,strtotime(sprintf("%04d-$m-",$z).cal_days_in_month(0,$m,$z)))<2)echo"$m,";
  • すべてではなく、指定された年を出力します(...常に質問を読んでください)
  • 無視された通知(Titusに感謝)
  • 変更whileforそれが今、単一の年だとして(再び、感謝タイタス)

古い2

$z=0;while($z++<9999){$o=[];$m=0;while($m++<12)if(date("N",strtotime(sprintf("%04d-$m-","$z").cal_days_in_month(0,$m,$z)))<2)$o[]=$m;echo count($o)>0?"$z:".implode(",",$o)."
":"";}

ドットから10000までのすべての年をサポートし、1台のPCで私が知らなかった未定義のvar警告も削除しました。はい、古いバージョンよりも長いですが、より堅牢です。

古い1

while($z++<9999){$o=[];$m=0;while($m++<12)if(date("N",strtotime("$z-$m-".cal_days_in_month(0,$m,$z)))<2)$o[]=$m;echo count($o)>0?"$z:".implode(",",$o)."
":"";}

Windowsまたは32ビットシステムで実行する場合、恐ろしい2038バグがありますが、64ビットLinuxシステムでは問題ありません。

date("t"...与えられた月の最後の日付を表すために使用することを試みましたが、結果はこのスレッドで前述したものと一致しませんでした。


2
-2:「$ z」は引用符を必要としません-7:通知を無視します(デフォルト設定では印刷されません:init $z、引用符なしN)-1:-43のfor代わりに:年をループする代わりに要求通りに入力します-3:-16の代わりに:直接出力:末尾のコンマがないことを主張する場合は+9:while joinimplodefor($z=$argv[1];$m++<12;)if(date(N,strtotime(sprintf("%04d-$m-",$z).cal_days_in_month(0,$m,$z)))<2)echo"$m,";echo$o=$o?",$m":$m;
Titus

ああ、質問を間違えた!oops:B他の提案にも感謝します、それらに乗ります
-CT14.IT

3

PHP、92バイト

for($d=new DateTime("$argv[1]-1-1");$i++<12;)$d->modify("1month")->format(w)!=2?:print"$i,";

年の最初の日が火曜日になってから1か月後に12回チェックします。その場合は、月の最終日が月曜日である前日です。


印刷の代わりにエコーを使用して、1
Octopus

1
@Octopusが三項演算子の内側にない
ヨルグヒュルサーマン

3

C、214バイト

main(int a,char *b[]){for(int x,y,d,m=12;m;m--){y=atoi(b[1]);x=m-1;d=x==1?(y%4==0?(y%100==0?(y%400==0?29:28):29):28):(x==3||x==5||x==10?30:31);if((d+=m<3?y--:y-2,23*m/9+d+4+y/4-y/100+y/400)%7==1)printf("%d\n",m);}}

コンパイル

gcc -std=c99 -o foo foo.c

非ゴルフ

関連する達人へのクレジット。

Cプログラムのマイケルキーストムクレイバー与えられた曜日を見つける

Q&AのためのCollin Biedenkapp :その月の最後の日が何であるかを知るにはどうすればよいですか?

/* credit to Collin Biedenkapp */
short _get_max_day(short x, int z) {
    if(x == 0 || x == 2 || x == 4 || x == 6 || x == 7 || x == 9 || x == 11)
        return 31;
    else if(x == 3 || x == 5 || x == 8 || x == 10)
        return 30;
    else {
        if(z % 4 == 0) {
            if(z % 100 == 0) {
                if(z % 400 == 0)
                    return 29;
                return 28;
            }
            return 29;
        }
        return 28;
    }
}

main(int argc,char *argv[]) {
 for(int y,d,m=12;m;m--) {
  y=atoi(argv[1]);
  d=_get_max_day(m-1,y);
  /* credit to Michael Keith and Tom Craver */
  if ((d+=m<3?y--:y-2,23*m/9+d+4+y/4-y/100+y/400)%7 == 1)
    printf("%d\n",m);
 }
}

1
あなたifがあなたのelseリターン31を得るためにあなたの反対方向をひっくり返して、それであなたが大きな==チェーンを排除することができるならば、どうですか?
AdmBorkBork

1
if(x == 1){z part} else if(x == 3 || x == 5 || x == 8 || x == 10)return 30 else return 31
RosLuP

1
どうですか:return x == 1?(z%4 == 0?(z%100 == 0?(z%400 == 0?29:28):29):28):( x == 3 | | x == 5 || x == 8 || x == 10?30:31)
RosLuP

TimmyD + RosLuP:return()ポイントのおかげで、100バイトが保存されました。
スティーブ

1
ようやくこれを減らすことができます:u(y、m){return m-1?30 +((2773 >> m)&1):28+(y%4 == 0 && y%100 || y% 400 == 0);}ここで、yは年、mは月
RosLuP

3

C、119バイト

t=1248700335,m;main(y){for(scanf("%d",&y),t+=y&3||y%25<1&&y&15;m++,(6+y+y/4-y/100+y/400+t)%7||printf("%d,",m),t;t/=7);}

これは、基数7を使用して符号付き32ビットワードでエンコードされたうるう年の毎月最終日の平日のオフセットを含むテーブルを使用します。うるう年でない場合は、1月のオフセットに1を追加します。 (ご覧のy&3||y%25<1&&y&15とおり、うるう日のない年を確認するために使用されます)。次に、単に毎月ループし、その最終日が月曜日かどうかを確認します。実際には非常に単純で、いハッキングやトリックはありません。ここでは、わずかに変更されていません。

t=1248700335,m;
main(y){
  for(
    scanf("%d",&y),t+=y&3||y%25<1&&y&15;
    m++,(6+y+y/4-y/100+y/400+t)%7||printf("%d,",m),t;
    t/=7
  );
}

いくつかの文字を保存する関数として書き直すために、これを再検討するかもしれません。またprintf、少しスペースを取りすぎます...


printf( "%d、"、m)は、何かを1または2、3として印刷するため、常に1つの '、'があります。スペースのみを使用することをお
勧めし

実際、実際には出力内のスペースも好みますが、通常は空白を必要としないようにゴルフ用Cソリューションを作成しているため、キャラクター数を確認したい場合は、ハーフゴルフバージョンからすべての空白を削除できます。
Fors

3

PHP、96 95 76 71 69 64 61バイト

注:年番号は、などのように4文字にパディングする必要があります0070

for(;13+$i-=1;)date(N,mktime(0,0,0,1-$i,0,$argn))-1||print$i;

次のように実行します。

echo 3385 | php -nR 'for(;13+$i-=1;)date(N,mktime(0,0,0,1-$i,0,$argn))-1||print$i;';echo
> -1-2-10

説明

-1から-12まで反復します。mktime、day 0(前月の最終日)、およびmonth を使用して日付を作成します2..13。日付を日番号としてフォーマットし、結果が1の場合、現在の番号を出力します。負符号-は区切り文字として使用されます。

ミレニアムのバグが再び襲来!

このバージョンでは、範囲0..100はと解釈されることに注意してください1970..20690..69週には400年ごとに繰り返されるパターンがあるため(146097日、正確には20871週)、これは範囲では問題ありませんが、範囲では、年数70..99に1900が加算されます(400の倍数ではありません)。 10kの範囲の30年の数値に対するその問題は、最も簡単な方法は、2桁の解釈(+4バイト)を防ぐために年の数値に400を追加することです:

for(;13+$i-=1;)date(N,mktime(0,0,0,1-$i,0,$argn+400))-1||print$i;

微調整

  • 使用してバイトを保存!~-$i比較する$i1-1バイナリ否定され0、論理否定でありtrue;他の全ての数であるfalse)、括弧を必要としないように
  • last day ofYYYY-m表記法を使用して日付を作成することで19バイトを保存しました
  • の代わりにdateとを使用して5バイトを保存しましたstrtotimedate_create
  • 出力の区切り文字として負の符号を使用し(負の月の数値は存在しない)YYYY-m、日付の一部に区切り文字として使用して、負の数からカウントすることで2バイトを保存しました
  • mktime代わりにを使用して5バイトを保存しましたstrtotime。曜日の使用に戻しました0mktime月13もサポートしているため、0-13== 31-12
  • 使用して3つのバイトを保存-Rするために$argn利用可能

mktime年を埋める必要がなくなりますよね?
タイタス

@Titus, sharp. Well I just figured out that mktime is counter-intuitive, because the arguments are taken as INTs. That means you can't pad the year... so everything in range 0..100 is interpreted as 1970..2070. That is no problem for the range 0..70 because 400 years have an exact number of weeks (so calendars repeat the pattern every 400 years), but 70..99 adds 1900 (not a multiple of 400!). Therefore new ver. has a bug.
aross

Only solution I see for that right now is$argv[1]+400 ... unless Julian and Gregorian weekdays differ.
Titus

@Titus, yep. Rules say use Gregorian cal
aross

3

Excel, 428 97 96 bytes

Input in A1. Output un-separated Hexadecimal values (January = 0, December = B)

=IF(2=WEEKDAY(DATE(A1+2000,1,31)),0,"")&CHOOSE(WEEKDAY(DATE(A1+2000,3,0)),4,19,6,"3B",8,25,"7A")

Added 10 bytes ("+2000") to allow handling of pre-1990 dates.

Saved 11 bytes thanks to @Engineer Toast.


First attempt (428 bytes), borrowing heavily from @Adám's solution.

=IF(2=WEEKDAY(DATE(A1,1,31)),1,"")&IF(2=WEEKDAY(EOMONTH(DATE(A1,2,1),0)),2,"")&IF(2=WEEKDAY(DATE(A1,3,31)),3,"")&IF(2=WEEKDAY(DATE(A1,4,30)),4,"")&IF(2=WEEKDAY(DATE(A1,5,31)),5,"")&IF(2=WEEKDAY(DATE(A1,6,30)),6,"")&IF(2=WEEKDAY(DATE(A1,7,31)),7,"")&IF(2=WEEKDAY(DATE(A1,8,31)),8,"")&IF(2=WEEKDAY(DATE(A1,9,30)),9,"")&IF(2=WEEKDAY(DATE(A1,10,31)),"A","")&IF(2=WEEKDAY(DATE(A1,11,30)),"B","")&IF(2=WEEKDAY(DATE(A1,12,31)),"C","")

How does this work on years earlier than 1900? The test case 297 -> May returns 6 with this formula. Shouldn't it be 4? 1776 gives 7A instead of just 8 for September.
Engineer Toast

If you get it to work, though, you can probably use Date(A1,3,0) instead of EOMONTH(DATE(A1,2,1),0)
Engineer Toast

2

Bash+cal, 58 bytes

$ cat t.sh
for A in {1..12};do cal $A $1|grep -qx .....&&echo $A;done
$ bash t.sh 2016
2
10
$

+1 - works for BSD cal (e.g. OSX), but watch for trailing spaces on GNU cal.
Digital Trauma

2

Python 2, 94 bytes

from datetime import*
lambda y:[m for m in range(1,13)if date(y+(m>11),m%12+1,1).weekday()==1]

repl.it

An unnamed function, takes an integer year, outputs a list of the month numbers [1-12].

I also tried to beat the byte count with arithmetic without success (110 bytes). :

lambda y:map(lambda x,v:(23*((x+2)%13or 1)/9+y-2*(0<x<11)+(x>10)+v/4-v/100+v/400)%7==4,range(12),[y-1]+[y]*11)

An unnamed function which returns a list of boolean values representing if the months [Jan-Dec] end in a Monday


2

Java 7, 200 249 bytes

import java.util.*;String c(int y){String r="";GregorianCalendar c=new GregorianCalendar();c.setGregorianChange(new Date(1L<<63));c.set(1,y);c.set(2,0);for(int i=0;i++<12;c.add(2,1)){c.set(5,c.getActualMaximum(5));if(c.get(7)==2)r+=i+" ";}return r;}

In Java, GregorianCalendar is a mix between a Gregorian and Julian calendar. Because of this, year 1 gave incorrect results. Changing Calendar c=Calendar.getInstance(); to GregorianCalendar c=new GregorianCalendar();c.setGregorianChange(new Date(1L<<63)); fixes this by forcing a use of the Gregorian calendar only. Thanks to @JonSkeet on stackoverflow.com for explaining this to me.

Ungolfed & test code:

Try it here.

import java.util.*;
class M{
  static String c(int year){
    String r = "";
    GregorianCalendar calendar = new GregorianCalendar();
    calendar.setGregorianChange(new Date(Long.MIN_VALUE));
    calendar.set(Calendar.YEAR, year);
    calendar.set(Calendar.MONTH, 0);
    for(int i = 0; i++ < 12; calendar.add(Calendar.MONTH, 1)){
      calendar.set(Calendar.DATE, calendar.getActualMaximum(Calendar.DATE));
      if(calendar.get(Calendar.DAY_OF_WEEK) == 2){
        r += i+" ";
      }
    }
    return r;
  }

  public static void main(String[] a){
    System.out.println(c(1));
    System.out.println(c(297));
    System.out.println(c(1776));
    System.out.println(c(2000));
    System.out.println(c(2016));
    System.out.println(c(3385));
  }
}

Output:

4 12
5 
9 
1 7 
2 10 
1 2 10 

2

C#6 C#, 171 167 135 bytes

using System;
void d(int n){for(int i=0;++i<13;)if((int)new DateTime(n,i,DateTime.DaysInMonth(n,i)).DayOfWeek==1)Console.Write(i+" ");}

-32 bytes thanks to Shebang

Print months as numbers; with space delimited; with trailing space. Now this answer also works for earlier versions of C#.


Old, 167 bytes

using System;using System.Linq;
c(int n)=>string.Join(",",Enumerable.Range(1,12).Where(i=>new DateTime(n,i,DateTime.DaysInMonth(n,i)).DayOfWeek==(DayOfWeek)1));

-4 bytes thanks to TimmyD

Output months are numbers in return string, comma delimited

Ungolfed

string c(int n)=>
    string.Join(",",                                        // Join them with commas
        Enumerable.Range(1,12)                              // For 1-12 inclusive
        .Where(                                             // Select only
            i=>new DateTime(n,i,DateTime.DaysInMonth(n,i)   // Get last day of that year-month
            ).DayOfWeek                                     // Get its day of week
            ==(DayOfWeek)1                              // Is Monday
        )
    )
;

@TimmyD Yes but need explicit cast. Answer updated
Link Ng

LINQ is fun but this is 126 bytes: void q(int y){for(int m=1;m<13;m++){if((int)new DateTime(y,m,DateTime.DaysInMonth(y,m)).DayOfWeek==1){Console.WriteLine(m);}}} ;) Also, it would be shorter to cast the DayOfWeek to int than it would be to cast the int to DayOfWeek
Kade

@Shebang Thanks. I really shouldn't golf in one-line linq --- Only Jon Skeet can do that. See if I have time for update tomorrow. Tired now.
Link Ng

You can convert this to be an Action<int> to save some bytes
TheLethalCoder

2

Ruby, 54 + 6 = 60 bytes

λ cat monday.rb
p (1..12).select{|m|Date.new($*[0].to_i,m,-1).monday?}
λ ruby -rdate monday.rb 2016
[2, 10]

6 bytes for -rdate on the command line to get the Date class from the standard library.

Explanation: pretty straightforward thanks to the Ruby stdlib's great Date class. Not only does it have methods like monday?, tuesday?, etc, the constructor will take negative numbers for any field past year to mean 'count this field backwards from the end of the period represented by the previous field'. $* is shorthand for ARGV, so $*[0] is a quick way to get the first command line argument.


2

PHP, 84 bytes

for($m=1;$m++<14;){if(strftime('%w',strtotime($argv[1]."-$m-1"))==2)echo($m-1)." ";}

My first Code Golf. This is the shortest PHP so far on this question.

EDIT: doesn't seem to work for year 1. I'll have to figure out why, but right now I have to go.


1
I'd say "Welcome to PPCG!" but you've been registered here for longer than I have! :D Nice first golf.
AdmBorkBork

Your error is that you create 1-13-1 and 1-14-1 for the year 1 <13 is enough. If you solve this you can remove the unnessary brackets in the moment and think about using the ternary operator
Jörg Hülsermann

This should fixed your problems for(;$m++<12;)strftime("%w",strtotime($argv[1]+($m/12^0)."-".($m%12+1)."-1"))!=2?:print"$m ";
Jörg Hülsermann

2

R, 106 99 95 83 78 77 74 bytes

g=function(x)which(format(seq(as.Date(paste0(x,-2,-1)),,'m',12)-1,"%u")<2)

The sequence of last days of each month is given by seq(as.Date(paste0(x,-2,-1)),,'m',12)-1:

  • paste0 coerces -2 and -1 to characters. If the x was 2016 for instance, paste0(x,-2,-1) gives "2016-2-1" which is then converted to the 1st of February 2016 by as.Date.

  • seq applied to a POSIXct or a Date object is seq(from, to , by, length.out): here to is not given, by is given as 'm' which is matched to 'month' thanks to partial matching, and length.out is of course 12.

  • The resulting sequence is the first day of the 12 months starting with February of the year in question. -1 gives us then the last day of the 12 months starting with January of the year in question.

Test cases:

> g(1)
[1]  4 12
> g(25)
[1] 3 6
> g(297)
[1] 5
> g(2000)
[1] 1 7
> g(2016)
[1]  2 10
> g(3385)
[1]  1  2 10
> g(9999)
[1] 5

Old version at 95 bytes, outputting the month names instead of just their numbers:

g=function(x)format(S<-seq(as.Date(sprintf("%04i-02-01",x)),,'m',12)-1,"%B")[format(S,"%u")==1]

This answer is just brilliant. I had no idea seq had a method for Date -objects and this solves the issue of as.Date not handling years above 10000 in my deleted answer.
Billywob

@Billywob yes seq.Date and seq.POSIXt are quite impressive: they can even process commands such as seq(time1, time2, by="10 min") or seq(date1, date2, by="quarter"). Very useful when plotting a time-series.
plannapus

2

Japt, 24 bytes

Do1 £Ov"Ð400+U"+X e ¥2©X

Test it online! Outputs an array of numbers, with false in place of months that don't end in a Monday.

There was a bug in the interpreter that didn't allow me to use Ð in the function body £. After the bug fix and another feature addition, this is 18 bytes in the current commit:

Do1@Ð400+UX e ¥2©X

1

Java, 143 129 bytes

This uses the new time API of Java 8.

y->{String s="";for(int m=0;++m<13;)if(java.time.YearMonth.of(y,m).atEndOfMonth().getDayOfWeek().ordinal()==0)s+=m+" ";return s;}

Output

Note that each line has an extra space at the end.

4 12 
5 
9 
1 7 
2 10 
1 2 10 

Ungolfed and testing

import java.time.*;
import java.util.function.*;

public class Main {
    public static void main (String[] args) {
        IntFunction<String> func = year -> {
          String result = "";
          for (int month=1; month <= 12; month++) {
            if (YearMonth.of(year, month).atEndOfMonth().getDayOfWeek().ordinal() == 0) {
              result += month + " ";
            }
          }
          return result;
        };
        System.out.println(func.apply(1));
        System.out.println(func.apply(297));
        System.out.println(func.apply(1776));
        System.out.println(func.apply(2000));
        System.out.println(func.apply(2016));
        System.out.println(func.apply(3385));
    }
}

Shaves

  1. 143 to 129 bytes: use DayOfWeek::ordinal to compare with a numerical constant instead of the enum constant.
    Thanks @TimmyD for the general idea if not the exact solution! ;-)

@TimmyD sadly, it's an enum. It does have a getValue() method, though, which would save a few bytes.
Celos

@Celos ordinal() saves 1 more byte compared to getValue(), even though it is suggested to never use it.
Olivier Grégoire

yes, good thinking. I posted my comment without first refreshing, so I didn't see your reply and edit.
Celos

1

GNU awk, 80 bytes

{for(;m<13;a=mktime($0" "++m" 1 9 0 0")){if(strftime("%w",a-8e4)~1){print m-1}}}

Example

$ gawk '{for(;m<13;a=mktime($0" "++m" 1 9 0 0")){if(strftime("%w",a-8e4)~1){print m-1}}}' <<<2016
2
10
$
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.