날짜 곱하기 도전


19

( FiveThirtyEight.com 의 지난주 리 들러 에서 영감을 얻었습니다 . 샌드 박스 게시물 .)

2001 년과 2099, 계산 사이에 해 주어 그 역년 동안 일 수를 반환 할 경우 mm * dd = yy(여기서 yy는 IS 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와 동일한 일수
를가집니다.

mm * dd의 결과가 100보다 크면 자동으로 필터링됩니까?
DanielIndie

@DanielIndie 맞습니다. "랩 어라운드"날짜는 계산하지 않아야합니다. 즉, 12 * 12 = 144인데도 2044 년 12 월 12 일은 계산되지 않습니다.
BradC

제한된 수의 입력 만 처리해야하므로 입력을 모두 편집했습니다. 롤백하거나 다시 포맷하십시오.
Shaggy

1
@gwaugh 유효한 입력으로 받아 들일 것을 결정할 수 있습니다 (따라서 두 문자 사이를 변환하는 추가 문자를 소비하지 않아도 됨).
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

진실! 설명으로 편집하겠습니다.
Sophia Lechner

또한 로케일마다 다릅니다. mm / dd / yy 순서를 사용하는 로케일이 있는지에 따라 다릅니다. dd / mm / yy 순서의 로케일에서 대답은 물론 동일한 바이트 수입니다.
Sophia Lechner

1
슈퍼 영리한; 나는 당신이 연중 매일 달리는 대신에 12 개의 날짜 후보자 (한달에 한 번) 만 테스트하는 방법을 좋아합니다.
BradC

윤년이 아닌 저장 바이트로 연도를 수정 하시겠습니까?
l4m2

6

파이썬 2 , 44 바이트

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

온라인으로 사용해보십시오!

메소드 오브젝트로 제공된 익명 함수 모든 제품 생산 (month, day)(m, d)으로 인코딩로 k=32*m+d0≤m≤12, 0≤d≤31주위에 배치. 범위에서 제외하여 2 월 29-31 일을 제거합니다.


5

자바 (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 바이트를 제거 할 수 있습니다.
Olivier Grégoire

1
여전히 변경하면 모든 결과 (m==2?29:32)29+m%2*3나오는 것 같습니다 OK. @AsoneTuhid 의 Ruby 답변감사드립니다 .
Kevin 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

온라인으로 사용해보십시오!

입력을 두 자리 연도로 취한 다음 for루프를 1/1/year~ 에서 생성 합니다 12/9/year(12/10 이상은 계산되지 않으므로 바이트가 절약됩니다). 반복 할 때마다 입력 연도와 같은 횟수만큼 증가 $z합니다 . 루프 외부에서는 파이프 라인에 남아 있으며 출력은 암시 적입니다..Month.Day$z

편집-문화에 따라 다릅니다. 위 코드는에서 작동합니다 en-us. 다른 문화권의 경우 날짜 형식을 변경해야 할 수도 있습니다.


2
"문화"? "로케일"을 의미 했습니까? ...
user202729

1
@ user202729 한마디로, 그러나 PowerShell 설명서에서는이를 "문화"라고합니다.
AdmBorkBork

"문화"는 예를 들어 MS가 로케일에 관해 이야기하기 위해 일반적으로 사용하는 단어이다. .NET의 System.Globalization.CultureInfo
sundar-복원 모니카




3

자바 스크립트 (ES6), 91 바이트

하드 코딩이 반복 계산과 비교할 때 궁금합니다. 확실히 길지만 ( @Shaggy의 답변 참조 ) 너무 길지는 않습니다.

편집 : 그러나 더 직접적인 공식보다 훨씬 깁니다 ( @ l4m2 답변 참조 ).

[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

배쉬 + 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 날짜 범위에서 MM * DD는 이러한 연도의 다음 해 1 월 1 일에 YY가되지 않으므로이 추가 날짜는 결과에 영향을 미치지 않습니다.

온라인으로 사용해보십시오!


아주 좋았습니다- date파싱하는 동안 데이트 수학을 할 줄 조차 몰랐습니다 . seq뒤에 공백이 필요하지 않으므로 -f바이트를 저장할 수 있습니다.
Sophia Lechner

3

티 -SQL, 123 바이트

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 솔루션에서 크게 영감을 받았습니다 .

  • 맨 위 줄 은 입력 테이블에 조인 된 12 개의 항목 테이블 c 를 생성 합니다. t에 .
  • 그것이 통과하면 나는 날짜 후보를 함께 매시 CONCAT() 암시 적 varchar데이터 유형 변환을 수행합니다. 그렇지 않으면 나는 많은 CAST또는CONVERT 문을.
  • 완벽한 평가 기능 발견 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 이상에서 사용할 수 있습니다.
  • 상술 한 바와 같이, 대체 IIF하여WHERE

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_values을 포함하는 데이터베이스 에 있어야하며 TYPE='P'0에서 2048까지의 숫자를 계산합니다.


다른 답변과 마찬가지로 날짜 ( m/d/y)를 조립하는 순서 는 SQL 인스턴스의 로컬 설정에 따라 다릅니다. 다른 지역에서는 다른 순서 또는 다른 구분 기호가 필요할 수 있지만 코드 길이에 영향을 미치지 않을 것이라고 생각합니다.
BradC

'2/29/64'를 날짜로 변환하면 1964-02-29 (2064-02-29가 아님)를 제공하지만 2000 년과 2100 년이 제외된다는 것을 고려할 때 더 짧은 시간을 얻는 것이 좋은 방법입니다 암호.
Razvan Socol

SPLIT_STRINGCTE 대신 사용하면 120 바이트로 줄어 듭니다. CONCAT_WS대신에 사용 CONCAT하면 다른 문자 가 저장되어 119 바이트가됩니다.
Razvan Socol

@ RazvanSocol 그래, 휴식 시간이 19xx 대 20xx로 매핑되는 두 자리 날짜 사이의 위치는 확실하지 않지만 둘 다 동일한 대답을 제공합니다. 다른 두 가지 제안을 시도해 보겠습니다. 감사합니다!
BradC

1
교체 IIF와 함께 WHERE.
Razvan Socol

3

Julia 0.6 , 49 44 42 바이트

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

온라인으로 사용해보십시오!

Asone Tuhid의 Ruby 답변에서 영감을 얻은 -5 바이트.
count를 sum로 바꾸는 -2 바이트

설명:

매월 i1에서 12까지의 월 을 계산 y/i하고 해당 월의 날짜 중 하나인지 확인하십시오. 31 일의 월은 1, 3, 5, 7, 8, 10, 12입니다. 따라서 8보다 낮고 8보다 더 홀수입니다. 따라서 i%2또는 i÷8(i <8의 경우 0, i> =의 경우 1) 여기서 8)은 1이어야하지만 둘다는 아니어야합니다. 배타적 논리합 결과가 사실이라면, 우리는 날짜가 확인 1:28+31:31, 그렇지 않으면 우리가 날짜를 확인합니다 1:28.

1:28다음 달 동안 충분합니다 (이 개선 사항은 Asone Tuhid의 Ruby 답변에서 영감을 얻음 ).

  • 년 2 유일한 가능성이 있었을 것이다 2*29 = 58, 그러나 2058우리 2 월은 항상 28 일까지 가정 할 수 있도록, 윤년이 아닙니다.

  • 30 일이있는 다른 달은 4 개월 이상입니다.이 기간 i*29(및 i*30)은 100을 초과하므로 무시할 수 있습니다.

마지막으로, 우리 y/i는이 일 목록에 속하는 횟수를 계산하고 ( sum여기서 부울을 사용하여 ) 반환합니다.


3

자바 스크립트, 91 85 82 81 77 바이트

입력을 2 자리 문자열 (또는 1 또는 2 자리 정수)로 취합니다.

new Date다음 달로 롤오버 할 사실을 활용 하고 계속 진행합니다. 전달한 달의 일 수를 초과하는 일 값을 전달하면 첫 번째 반복시에는 날짜 yyyy-01-345가된다 yyyy-12-11, 또는 yyyy-12-10윤년에. 그 후 날짜를 12*11+3 자리 숫자 로 확인할 필요는 없습니다 .

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

Arnauld 덕분에 3 바이트가 절약되었습니다 .


그것을 테스트

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

엑셀, 83 바이트

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

입력은 A1형식으로 셀 에 yyyy있습니다. 이 배열 수식이며으로 입력 Ctrl+ Shift+ Enter중괄호를 얻을 {}. 그것은 매우 간단하고 영리하지 않습니다.

배열 수식에있을 때 DATE(A1,1,0)+ROW(1:366)366 개의 날짜 값 배열을 제공합니다. 윤년이 아닌 경우에는 다음 해의 1 월 1 일이 포함되지만 문제가되지 않으며 1*1=1다음 해인 경우 오탐으로 간주 2001되지만 필요한 연도 범위가 2001 - 2099이므로 절대로 발생하지 않습니다. 발행물.

그 비트를 간단히으로 단축 ~하면 수식이 훨씬 쉽게 따라갈 수 있습니다.

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

COUNTIF()대신에 사용하려고 SUM(IF())했지만 Excel에서 배열 수식으로 입력하지 않아도 결과가 훨씬 적습니다. 내가 했던 찾는 상대 의 Google 스프레드 시트를 사용하여 솔루션 CountIf()이 사용 주로하기 때문에, 91 바이트로 판명 달리하지만 같은 방법을 ArrayFormula()대신 단순히 { }.

=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 배열 수식으로 입력하는 데 필요한 추가 키 입력을 포함시키는 방법을 결정하는 대신 포함 시켰습니다. 거기의 메타 질문 에 대한 유일한 대답은 CTRL + ALT + 명령 1 키 입력으로 간주 할 ENTER 말한다. vim ( meta마다 ) 과 동일하게 사용하면 해당 키 입력은 1 바이트로 계산됩니다. 그러나 다른 답변에서 수식을 입력 한 끝에 ENTER를 1 바이트로 계산하지는 않습니다.
엔지니어 토스트

2

레티 나 0.8.2 , 55 바이트

..
$*
(?<=^(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.