日付乗算チャレンジ


19

(FiveThirtyEight.comの先週のRiddlerに触発されました。サンドボックスの投稿。)

2001年から2099年までの年を指定して、その暦年の日数を計算して返しますmm * dd = yy(ここyyで、2桁の年)。

たとえば、2018には5があります。

  • 1月18日(1 * 18 = 18)
  • 2月9日(2 * 9 = 18)
  • 3月6日(3 * 6 = 18)
  • 6月3日(6 * 3 = 18)
  • 9月2日(9 * 2 = 18)

入力は、2桁または4桁の年です。

出力は整数でなければなりません。オプションの後続スペースまたはリターンは問題ありません。

完全な入出力リスト:

Input = Output
 2001 = 1     2021 = 3     2041 = 0     2061 = 0     2081 = 2
 2002 = 2     2022 = 3     2042 = 4     2062 = 0     2082 = 0
 2003 = 2     2023 = 1     2043 = 0     2063 = 3     2083 = 0
 2004 = 3     2024 = 7     2044 = 3     2064 = 2     2084 = 5
 2005 = 2     2025 = 2     2045 = 3     2065 = 1     2085 = 1
 2006 = 4     2026 = 2     2046 = 1     2066 = 3     2086 = 0
 2007 = 2     2027 = 3     2047 = 0     2067 = 0     2087 = 1
 2008 = 4     2028 = 4     2048 = 6     2068 = 1     2088 = 3
 2009 = 3     2029 = 1     2049 = 1     2069 = 1     2089 = 0
 2010 = 4     2030 = 6     2050 = 3     2070 = 3     2090 = 5
 2011 = 2     2031 = 1     2051 = 1     2071 = 0     2091 = 1
 2012 = 6     2032 = 3     2052 = 2     2072 = 6     2092 = 1
 2013 = 1     2033 = 2     2053 = 0     2073 = 0     2093 = 1
 2014 = 3     2034 = 1     2054 = 4     2074 = 0     2094 = 0
 2015 = 3     2035 = 2     2055 = 2     2075 = 2     2095 = 1
 2016 = 4     2036 = 6     2056 = 4     2076 = 1     2096 = 4
 2017 = 1     2037 = 0     2057 = 1     2077 = 2     2097 = 0
 2018 = 5     2038 = 1     2058 = 0     2078 = 2     2098 = 1
 2019 = 1     2039 = 1     2059 = 0     2079 = 0     2099 = 2
 2020 = 5     2040 = 5     2060 = 6     2080 = 4

これはチャレンジであり、各言語の最小バイト数が勝ちです。

事前に計算して答えを検索することは、通常、抜け穴のルールに従って除外されますが、このチャレンジでは明示的に許可しています。98個の99項目のルックアップリストが最短になる可能性は低いものの、いくつかの興味深い代替戦略が可能になります。


それがあなたの言語でそれをより簡単にするなら、答えは世紀に関係なく同じです。1924と2124は、2024と同じ日数を持っている
BradC

mm * ddの結果が100より大きい場合、自動的にフィルタリングされますか?
ダニエルインディー

@DanielIndie正しい、「ラップアラウンド」の日付はカウントされません。つまり、12 * 12 = 144であっても、2044年12月12日はカウントされません
。– BradC

限られた数の入力のみを処理する必要があるため、それらをすべて編集しました。気軽にロールバックまたは再フォーマットしてください。
シャギー

1
@gwaugh有効な入力としてどちらを受け入れるかを決めることができます(したがって、2つの間で変換する余分な文字を費やす必要はありません)。
BradC

回答:


14

Excel、48バイト

やった!最後に、Excelが実際に得意とするもの。

=COUNT(VALUE(ROW(1:12)&"/"&A1/ROW(1:12)&"/"&A1))

年を表す整数1〜99の形式でA1から入力を受け取り、この式を入力した場所に出力します。これは配列式なので、Enterの代わりにCtrl-Shift-Enterを使用して入力します。

これはCOUNT、エラーを無視するという事実を利用しているため、年で区切られていない月(Excelのような何かを解析し2/12.5/25たり、などの無効な日付によって引き起こされたエラー2/29/58)は、黙って無視されます。


1
非常に素晴らしい。言及する価値があるのは、おそらく2桁の年ですA1。4桁の年を入力すると、単に戻ります0
BradC

本当だ!これを説明に編集します。
ソフィア・レヒナー

また、ロケール固有であることにも言及する必要があります。mm / dd / yyの順序を使用するロケールを持つことに依存します。dd / mm / yyの順序のロケールでは、当然、答えは同じバイト数になります。
ソフィア・レヒナー

1
超賢い; 私は、あなたが1年中毎日実行するのではなく、12の日付候補(1か月に1つ)だけをテストする方法が好きです。
BradC

年を飛躍しない1セーブバイトに修正しますか?
l4m2

6

Python 2、44バイト

[k/32%13*(k%32)for k in range(96,509)].count

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

メソッドオブジェクトとして指定された匿名関数。すべての製品生産(month, day)のペアを(m, d)によってコードされるk=32*m+d0≤m≤120≤d≤31折り返し、。範囲から除外することにより、2月29〜31日を排除します。


5

Java(JDK 10)、65バイト

y->{int m=13,c=0;for(;m-->1;)if(y%m<1&y/m<29+m%2*3)c++;return c;}

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

クレジット


うるう年はありません29*nので、チェックする必要はありません
l4m2

ご意見ありがとうございます。他の多くの変更により、合計27バイトを削除できました。
オリビエグレゴワール

1
それでも変更(m==2?29:32)する29+m%2*3と、すべてのOK結果が得られるようです。@AsoneTuhidのRubyの回答感謝します
ケビンCruijssen

4

PowerShell、94バイト

param($a)for($x=Date 1/1/$a;$x-le(Date 12/9/$a);$x=$x.AddDays(1)){$z+=$x.Month*$x.Day-eq$a};$z

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

入力を2桁の年として受け取りfor1/1/yearto からループを構築します12/9/year(12/10以降はカウントされず、これによりバイトが節約されるため)。各繰り返しは、我々はインクリメント$z場合に限っ.Month.Day私たちの入力年に等しいです。ループ外で$zは、パイプラインに残り、出力は暗黙的です。

編集-これは文化に依存します。上記のコードはで機能しen-usます。他の文化では日付形式を変更する必要がある場合があります。


2
"文化"?「ロケール」という意味ですか?...
user202729

1
@ user202729口語的には、そうですが、PowerShellのドキュメントでは「文化」
AdmBorkBork

「文化」は、MSがロケールについて話すために一般的に使用する単語です。.NETのSystem.Globalization.CultureInfo
スンダ-




3

JavaScript(ES6)、91バイト

ハードコーディングが反復計算と比較する方法を知りたいと思いました。それは間違いなく長くなりますが(@Shaggyの答えを参照)、ひどく長くはありません。

編集:ただし、より直接的な式よりもはるかに長くなります(@ l4m2 answerを参照)。

入力を[1..99]の整数として受け取ります

n=>(k=parseInt('8ijkskercdtbnqcejh6954r1eb2kc06oa3936gh2k0d83d984h'[n>>1],36),n&1?k>>3:k&7)

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

どうやって?

奇数年は、偶数年よりもmm * dd = yyになる可能性が大幅に低くなります。より具体的には、奇数年は持って0への3年も持ちながら、試合を0への7試合を。これにより、各年のペアをわずか5ビットでコーディングできます。これは、ベース36で単一の文字として簡単に表すことができます。




3

Bash + GNUユーティリティ、57

  • @SophiaLechnerのおかげで1バイト節約
seq -f1/1/$1+%gday 0 365|date -f- +%m*%d-%y|bc|grep -c ^0

このseqコマンドは常に366個の日付のリストを生成することに注意してください-うるう年以外の場合は、翌年の1月1日が含まれます。ただし、2001..2099の日付範囲では、これらの年のいずれでも、翌年の1月1日のMM * DDがYYになることはないため、この余分な日は結果に影響しません。

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


非常に素晴らしい- date解析中にそのような日付計算を行うことさえ知らなかった。seqの後にスペースは必要ないので、-fそこにバイトを保存できます。
ソフィア・レヒナー

3

T-SQL、123 121バイト

IOルールに従って、入力は2桁の年を含む整数フィールドyを持つ既存のテーブルtを介して取得されます。

WITH c AS(SELECT 1m UNION ALL SELECT m+1FROM c WHERE m<12)
SELECT SUM(ISDATE(CONCAT(m,'/',y/m,'/',y)))FROM c,t WHERE y%m=0

改行は読みやすくするためのものです。主にSophiaのExcelソリューションに触発されました。

  • 一番上の行は、入力テーブルtに結合される12アイテムの番号テーブルcを生成します。
  • それが成功したら、CONCAT()暗黙的なvarcharデータ型変換を行うを使用して日付候補をマッシュアップします。そうでなければ、私はたくさんのやる必要があるだろうCASTCONVERT文を。
  • ISDATE()有効な日付に対して1を返し、無効な日付に対して0を返す完璧な評価関数を見つけました。
  • SUMでラップすれば完了です。
  • 編集:整数除算チェック(y%m=0)をWHERE句に移動して、2バイトを節約しました。@ RazvanSocolに感謝します。

残念ながら、ルックアップテーブルバージョンよりも短くはありません(osdavisonのバージョンの文字列を使用):

T-SQLルックアップ、129バイト

SELECT SUBSTRING('122324243426133415153317223416132126011504033106131204241006003213011306002122042005101305111014012',y,1)FROM t

編集:オリジナルを上に残しますが、いくつかの新しい関数を使用することで数バイト節約できます:

  • STRING_SPLIT MS SQL 2016以降で利用可能です。
  • CONCAT_WS MS SQL 2017以降で利用可能です。
  • 以上のように、置き換えIIFWHERE

MS-SQL 2017、121 118バイト

SELECT SUM(ISDATE(CONCAT_WS('/',value,y/value,y)))
FROM t,STRING_SPLIT('1-2-3-4-5-6-7-8-9-10-11-12','-')
WHERE y%value=0

MS-SQL 2017、余分なチートエディション:109バイト

SELECT SUM(ISDATE(CONCAT_WS('/',number,y/number,y)))
FROM t,spt_values WHERE number>0AND y%number=0AND'P'=TYPE

masterデータベースにアクセスする必要があります。データベースにはspt_valuesTYPE='P'0でフィルタリングされた場合に)0から2048までの数値をカウントするシステムテーブルが含まれています。


他の回答と同様に、日付(m/d/y)を組み立てる順序は、SQLインスタンスのローカリティ設定によって異なります。他の地域では、異なる順序または異なる区切り文字が必要になる場合がありますが、コードの長さに影響はないと思います。
BradC

'2/29/64'を日付に変換すると1964-02-29(2064-02-29ではない)が得られることに気づいたと思いますが、2000年と2100年が除外されていることを考えると、短くするのに良い方法ですコード。
ラズバンソコル

SPLIT_STRINGCTEの代わりに使用すると、120バイトになります。別の文字CONCAT_WSCONCAT保存する代わりにを使用すると、119バイトになります。
ラズバンソコル

@RazvanSocolええ、19xxと20xxに対応する2桁の日付の間の区切りがどこにあるかわかりませんが、どちらも同じ答えを与えます。他の2つの提案を試してみます、ありがとう!
BradC

1
交換してくださいIIFWHERE
ラズバンソコル

3

ジュリア0.649の 44 42バイト

y->sum(y/i1:28+3(i%2i÷8)for i=1:12)

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

Asone TuhidのRubyの回答に触発された-5バイト。
カウントを合計で置き換える-2バイト

説明:

i1から12までの各月について、を計算しy/i、その月の日かどうかを確認します。8以下だ奇数彼らはそうとそうであってもいずれかでのおよび8上- 31日とヶ月は1、3、5、7、8、10、12であるi%2か、i÷8<iについて8と1> iについて0(=ここでは8)は1である必要がありますが、両方ではありません。したがって、それらをXORします。xorの結果がtrueの場合、日付をチェックします。1:28+3つまり1:31、日付のみをチェックします1:28

1:28残りの月は十分です(この改善はAsone TuhidのRubyの回答に触発されました)。

  • for February, the only possibility would have been 2*29 = 58, but 2058 is not a leap year, so we can assume Feb always has 28 days.

  • the other months with 30 days are month 4 and above - for which i*29 (and i*30) would be above 100, which can be ignored.

Finally, we count out the number of times y/i belongs in this list of days (by using boolean sum here), and return that.


3

JavaScript, 91 85 82 81 77 bytes

Takes input as a 2-digit string (or a 1 or 2 digit integer).

Takes advantage of the fact that new Date will rollover to the next month, and continue doing so, if you pass it a day value that exceeds the number of days in the month you pass to it so, on the first iteration, it tries to construct the date yyyy-01-345 which becomes yyyy-12-11, or yyyy-12-10 on leap years. We don't need to check dates after that as 12*11+ results in a 3-digit number.

y=>(g=d=>d&&([,M,D]=new Date(y,0,d).toJSON().split(/\D/),D*M==y)+g(--d))(345)

3 bytes saved thanks to Arnauld.


Test It

f=
y=>(g=d=>d&&([,M,D]=new Date(y,0,d).toJSON().split(/\D/),D*M==y)+g(--d))(345)
o.innerText=[...Array(99)].map((_,x)=>(2001+x++)+` = `+f(x)).join`\n`
pre{column-count:5;width:480px;}
<pre id=o></pre>



2

Excel, 83 bytes

{=SUM(IF(MONTH(DATE(A1,1,0)+ROW(1:366))*DAY(DATE(A1,1,0)+ROW(1:366))=A1-2000,1,0))}

Input is in cell A1 in the format yyyy. This is an array formula and is entered with Ctrl+Shift+Enter to get the curly brackets {}. It is fairly straightforward and without any cleverness.

When in an array formula, DATE(A1,1,0)+ROW(1:366) gives us an array of 366 date values. On non-leap years, this will include Jan 1 of the next year but that is not a problem because 1*1=1 and would only count as a false positive if the next year is 2001 but, since the required year range is 2001 - 2099, it will never arise as an issue.

If you shorted that bit into simply ~, the formula because much easier to follow:

{=SUM(IF(MONTH(~)*DAY(~)=A1-2000,1,0))}

I tried using COUNTIF() instead of SUM(IF()) but Excel wouldn't even let me enter it as an array formula, much less give me a result. I did find a Google Sheets solution using CountIf() but the same method otherwise that turned out to be 91 bytes, mostly because it uses ArrayFormula() instead of simply { }.

=CountIf(ArrayFormula(Month(Date(A1,1,0)+Row(1:366))*Day(Date(A1,1,0)+Row(1:366))),A1-2000)

I haven't seen a consensus, but I've generally not been including the outer curly brackets in my byte counts for Excel. They feel more like a way that Excel is formatting its display than part of the formula. Opinions?
Sophia Lechner

@SophiaLechner I've included them instead of deciding how to include the extra keystrokes required to enter it as an array formula. There's a meta question about that and the only answer says that the CTRL+ALT+ENTER command would count as 1 keystroke. If you use the same as vim (per meta), then that keystroke would count as 1 byte. However, I don't usually count the ENTER at the end of entering a formula as 1 byte in other answers.
Engineer Toast

2

Retina 0.8.2, 55 bytes

..
$*
(?<=^(1{1,12}))(?=(?(?<=^11$)\1{0,27}|\1{0,30})$)

Try it online! Takes a two-digit year; add 1 byte to support 4-digit years. Explanation: The first stage simply converts to unary. The second stage starts by matching 1 to 12 characters before the match position, representing the month, and then attempts to look ahead for a whole number of repetitions of that month. However, the lookahead contains a conditional, which chooses between up to 27 or 30 further repetitions depending on the month. The count of match positions is then the desired result.


2

R, 22 122 bytes

x=scan();substr("122324243426133415153317223416132126011504033106131204241006003213011306002122042005101305111014012",x,x)

Try it online!

Decided to go with a lookup table approach. Input year needs to be 2 digits.


1
Also on TIO you can hit the "link" button and it will auto-format the answer for you. Thanks to Dennis for setting it up!
Giuseppe

You can remove the initial if, since input can be either 2-digit or 4-digit, your choice (so you can choose to accept only 2-digit input). But it looks like the code considers every month to contain 31 days, so for eg., 62 (for 2062) returns 1 where it should return 0.
sundar - Reinstate Monica

2
I misunderstood. That being said, I'm pretty sure the lookup table would have to be included in the byte count.
ngm

@ngm I also was not sure if the lookup table needed to be included, but I will add it to the byte count just to be safe.
Robert S.

I'm still not sure what all the rules are!
ngm


2

J, 29 bytes

1#.(,x*i."+29+3*2~:x=.i.13)=]

Try it online!

How it works

1#.(,x*i."+29+3*2~:x=.i.13)=]    Input: year (2-digit, 1..99)
                   x=.i.13       array of 0..12; assign to x
                2~:              1 1 0 1 .. 1
              3*                 3 3 0 3 .. 3
           29+                   32 32 29 32 .. 32
       i."+                      for each item of above, generate a row 0 .. n
    ,x*                          each row times 0 .. 12 and flatten
                           =]    1 for each item == input, 0 otherwise
1#.                              sum

Tried hard to get under 2 times Jelly solution :)

Side note

If someone really wants to hardcode the 99-digit data, here's a bit of information:

Divide the 99-digit into chunks of 2 digits. Then the first digit is <4 and the second <8, which means five bits can encode two numbers. Then the entire data can be encoded in 250 bits, or 32 bytes.


2

Python 3, 158 162 215 241 bytes

Removed 4 Thanks to Stephen for golfing the conditionals.

Removed 53 thanks Stephen for pointing out the white space

Removed 26 thanks to the link provided by caird

I'm pretty new at this. Couldn't think of how to do this without having the days in a month be described.

r=range
def n(Y):
 a,b,c=31,30,0
 for x in r(12):
  for y in r([a,(28if Y%4else 29),a,b,a,b,a,a,b,a,b,a][x]):
   if(x+1)*(y+1)==int(str(Y)[2:]):c+=1
 return c

Try it online!


5
Welcome to the site, and nice first post! There are a fair few ways you can golf this, such as removing some whitespace, so be sure to check out these tips for golfing in Python
caird coinheringaahing

@cairdcoinheringaahing Thanks for the advice the link was very useful!
akozi

1
158 bytes - golfed some away, but mostly you had a big long line of spaces on your third line, dunno how those got there
Stephen

@Stephen Thanks :) I added yours as two edits. One for the white space and the other as the golfing.
akozi

(28if Y%4else 29) can be shortened to [29,28][Y%4>0]. Also, the long list can be shortened to [a,...]+2*[a,b,a,b,a]. a,b,c can be added in the parameter list to save a line. int(str(Y)[2:]) can be shortened to Y%100. Finally, counter variables can mostly be shortened to lens of list comprehensions, this also allows n to be made a lambda. This makes 118.
Black Owl Kai

2

Forth (gforth), 60 59 bytes

: f 0 13 1 do over i /mod swap 32 i 2 = 3 * + 0 d< - loop ;

Try it online!

This version takes advantage of the fact that there can't be more than 1 matching day per month, and that the year has to be divisible by the month for it to match.

Explanation

Iterates over the months, checks if year is divisible by month, and if the quotient is < 31 (28 for Feb) Months after March can't match for days greater than 25, so we can just assume all months (other than Feb) have 31 days for the purpose of the puzzle.

Code Explanation

: f                   \ start new word definition
  0                   \ set up counter
  13 1 do             \ start a counted loop from 1 to 12
    over i /mod       \ get the quotient and remainder of dividing year by month
    swap              \ default order is remainder-quotient, but we want to swap them
    32 i 2= 3 * +     \ we want to compare to 32 days unless month is Feb
    0 d<=             \ treat the 4 numbers on the stack as 2 double-length numbers
                      \ and compare [1]
    -                 \ subtract result from counter (-1 is true in Forth)
  loop                \ end loop
;                     \ end word definition    

[1] - Forth has the concept of double length numbers, which are stored on the stack as two single-length numbers (of the form x y, where the value of the double = y * 2^(l) + xwhere l is the size in bits of a single in the forth implementation you're working with).

In this case, I compared the quotient and remainder to 32 (or 29) 0. If the remainder was greater than 0 (year not divisble by month), the first double would be automatically bigger than 32 (or 29) 0 and the result would be false. If the remainder is 0, then it resolves to effectively a regular check of quotient <= 32 (or 29)

Forth (gforth), 61 bytes

: f 0 13 1 do i 2 = 3 * 32 + 1 do over i j * = - loop loop ; 

Try it online!

Saved some bytes by realizing that only February matters in terms of having the correct number of days in the month

Explanation

Forth (at least gforth) comparisons return -1 for true and 0 for false

0                     \ place 0 on top of the stack to use as a counter
13 1 do               \ begin the outer loop from 1 to 12
  i 2 = 3 *           \ if i is 2 place -3 on top of the stack, otherwise 0
  32 + 1 do           \ begin the inner loop from 1 to 31 (or 28)
    over              \ copy the year from stack position 2 and place it on top of the stack
    i j * = -         \ multiply month and day compare to year, subtract result from counter 
  loop                \ end the inner loop
loop                  \ end the outer loop

1

Java (JDK 10), 79 72 70 bytes

y->{int a=0,m=13;for(;m-->1;)a+=y%m<1&&y/m<(m==2?29:32)?1:0;return a;}

Try it online!


@Shaggy Thanks! (leftover from previous version where I loop over all days)
user202729

If you change && to & it's the same answer as OlivierGrégoire's Java answer, although he has answered 19 minutes earlier.
Kevin Cruijssen

@KevinCruijssen Random coincidence. Although my version is a bit worse (unnecessary use of ternary).
user202729

1

JavaScript (Node.js), 108 bytes

a=>'0122324243426133415153317223416132126011504033106131204241006003213011306002122042005101305111014012'[a]

f=a=>'0122324243426133415153317223416132126011504033106131204241006003213011306002122042005101305111014012'[a]
o.innerText=[...Array(99)].map((_,x)=>(2001+x++)+` = `+f(x)).join`\n`
pre{column-count:5;width:480px;}
<pre id=o></pre>


Brute-force lookup, nice!
BradC

Welcome to PPCG!
Shaggy


1

Python 3, 132 bytes

This is really quite long of a program but I thought it might be of interest.

All the values are between 0-7 so I encode each number with 3 bits in a long binary string. I tried pasting a raw binary string into my python program but I couldn't get it to work, so I settled on base64 in the file.

I used the following string as a lookup table (ending 7 used for padding): 01223242434261334151533172234161321260115040331061312042410060032130113060021220420051013051110140127

The program takes this string and decodes it as a number, then uses bit shifting to extract the result.

import base64
lambda n:int.from_bytes(base64.b64decode(b'pNRRxYtw01s9Jw4tFYE0QNkYsoRQgYBosEsYBFIRAUgsUkgwFQM='),'big')>>(6306-3*n)&7

66 bytes + 37 byte file = 103 bytes

This reads a binary file called e and avoids using base64.

lambda n:int.from_bytes(open('e','rb').read(),'big')>>(6306-3*n)&7

Here is a hexdump of the read file (without padding):

00000000  a4 d4 51 c5 8b 70 d3 5b  3d 27 0e 2d 15 81 34 40  |..Q..p.[='.-..4@|
00000010  d9 18 b2 84 50 81 80 68  b0 4b 18 04 52 11 01 48  |....P..h.K..R..H|
00000020  2c 52 48 30 0a                                    |,RH0.|


1

Oracle SQL, 115 bytes

select count(decode(sign(decode(l,2,29,32)-y/l),1,1))from t,
xmltable('1to 12'columns l int path'.')where mod(y,l)=0

We may note that it does not really matter how many days in April (and later months), since 100/4 < 28. Also it's not necessary to check whether year is leap or not. We just have to specify that there are 28 days in February (not 29 because that validation will be executed only for 2058 which is not leap) otherwise it may be just 31 for any month.

Other approaches

Oracle SQL (12c Release 2 and later), 151 bytes

select count(to_date(y/l||'-'||l||'-1' default '' on conversion error,'dd-mm-y'))from t,
(select level l from dual connect by level<=12)where mod(y,l)=0

Oracle SQL (12c Release 2 and later), 137 bytes

select sum(validate_conversion(y/l||'-'||l||'-1'as date,'dd-mm-y'))from t,
(select level l from dual connect by level<=12)where mod(y,l)=0

Both solution could have been 8 bytes shorter if we replace (select level l from dual connect by level<=12) with xmltable('1to 12'columns l int path'.') but Oracle throws an exception because of the bug (tested on versions 12.2.0.1.0, 18.3.0.0.0).

SQL> select count(to_date(y/l||'-'||l||'-1' default '' on conversion error,'dd-mm-y'))from t,
  2  xmltable('1to 12'columns l int path'.')where mod(y,l)=0
  3  /
select count(to_date(y/l||'-'||l||'-1' default '' on conversion error,'dd-mm-y'))from t,
*
ERROR at line 1:
ORA-00932: inconsistent datatypes: expected DATE got DATE


SQL> select sum(validate_conversion(y/l||'-'||l||'-1'as date,'dd-mm-y'))from t,
  2  xmltable('1to 12'columns l int path'.')where mod(y,l)=0
  3  /
select sum(validate_conversion(y/l||'-'||l||'-1'as date,'dd-mm-y'))from t,
*
ERROR at line 1:
ORA-43909: invalid input data type

The only case in both solution when year does matter is 2058 which is non-leap so literal '-1' was used to specify non-leap year.

Oracle SQL, 128 bytes

select count(d)from t,(select date'1-1-1'+level-1 d from dual connect by level<365)
where to_char(d(+),'mm')*to_char(d(+),'dd')=y

Oracle SQL, 126 bytes

select substr('122324243426133415153317223416132126011504033106131204241006003213011306002122042005101305111014012',y,1)from t

Update

Oracle SQL, 110 bytes

select-sum(least(sign(y/l-decode(l,2,29,32)),0))from t,
xmltable('1to 12'columns l int path'.')where mod(y,l)=0

Oracle SQL, 108 bytes

select sum(decode(sign(decode(l,2,29,32)-y/l)*mod(y+1,l),1,1))from t,
xmltable('1to 12'columns l int path'.')

Spark SQL, 137 bytes

select count(cast(regexp_replace(concat_ws('-','2001',l,y/l),'.0$','')as date))
from(select explode(array(1,2,3,4,5,6,7,8,9,10,11,12))l),t

Spark 2.3+ SQL, 126 bytes

(replace function becomes available)

select count(cast(replace(concat_ws('-','2001',l,y/l),'.0')as date))
from(select explode(array(1,2,3,4,5,6,7,8,9,10,11,12))l),t

1

PHP, 73 bytes

Using pipe input and php -nR:

for(;++$m<13;$d=1)while($d<25+($m-2?$m>4?:7:4))$c+=$argn==$m*$d++;echo$c;

Try it online!

PHP, 76 bytes

Using command line arg input php dm.php 18:

for(;++$m<13;$d=1)while($d<25+($m-2?$m>4?:7:4))$c+=$argv[1]==$m*$d++;echo$c;

Try it online!

Iterative approach. Since the only leap year to look at is 2 * 29 = 58, and 2058 is not a leap year there's no need to consider leap year in the Feb days. And since wraparound is not a concern -- from April on, any day greater than 25 will exceed 100 we just say the rest of the months only have 25 days.

Input is 2 digit year via command line (-10 bytes as program, thx to suggestion from @Titus).

OR:

PHP, 101 bytes

$y=$argv[1];for($d=strtotime("$y-1");date(Y,$d)==$y;$d+=86400)eval(date("$\x+=j*n=='y';",$d));echo$x;

Try it online!

Still iterative but using PHP's timestamp functions. Accepts year as four digit number. Thx to @Titus for suggestion of using strtotime() instead of mktime().


First version fails for 4-digit years, second fails for two-digit. But nice thinking. Try $m<5?$m-2?31:28:25 for the first and $d=strtotime("$y-1") for the second
Titus

Uhm ... Why did you put the y in the eval in quotes?
Titus

@Titus because PHP7 now treats digits preceeded with 0 as octal, so 08 and 09 are actually not valid. tio.run/##K8go@G9jXwAkU5Mz8hUMFWxtFQwsrP//BwA Using the date() function you can only get a 2 digit, zero-padded year.
640KB

Bummer! of course.
Titus

1
@Titus, updated second version using strtotime() instead of mktime() and re-implemented as program, -7 bytes. Also, I looked at the majority of the submissions, including the top voted ones, will only accept year as either 2 or 4 digits, so I'm going to take that to mean it is up to submitter. Thx again for the suggestions!
640KB

0

PHP, 74 70 bytes

while(++$m<13)for($d=$m<5?$m-2?31:28:25;$d;)$n+=$d--*$m==$argn;echo$n;

accepts two-digit years only.

I adopted gwaugh´s considerations and golfed them; my 1st approach was longer than his (92 bytes):

for($y=$argn%100;++$m<13;)for($d=$m-2?30+($m+$m/8)%2:29-($y%4>0);$d;)$n+=$d--*$m==$y;echo$n;

%100 allows to use 4-digit years.


Run as pipe with -nR or try them online.


You can save 4 bytes by removing the %100 and only taking 2 digit input, which is OK: codegolf.stackexchange.com/questions/162137/…
640KB
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.