Thử thách nhân ngày


19

(Lấy cảm hứng từ Riddler tuần trước trên FiveThentyEight.com. Bài đăng trên hộp cát .)

Cho một năm từ 2001 đến 2099, hãy tính và trả về số ngày trong năm dương lịch đó mm * dd = yy(trong đó yylà năm có 2 chữ số ).

Năm 2018, ví dụ, có 5:

  • Ngày 18 tháng 1 (1 * 18 = 18)
  • Ngày 9 tháng 2 (2 * 9 = 18)
  • Ngày 6 tháng 3 (3 * 6 = 18)
  • Ngày 3 tháng 6 (6 * 3 = 18)
  • Ngày 2 tháng 9 (9 * 2 = 18)

Đầu vào có thể là một năm số 2 hoặc 4 chữ số.

Đầu ra phải là một số nguyên. Tùy chọn không gian dấu hoặc trả lại là tốt.

Hoàn thành danh sách đầu vào / đầu ra:

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

Đây là một thử thách , số byte thấp nhất trong mỗi ngôn ngữ sẽ thắng.

Tính toán trước và chỉ đơn giản là tìm kiếm các câu trả lời thường được loại trừ theo quy tắc kẽ hở của chúng tôi , nhưng tôi rõ ràng cho phép nó cho thử thách này. Nó cho phép một số chiến lược thay thế thú vị, mặc dù không có khả năng danh sách tra cứu 98 mục của nó sẽ ngắn nhất.


Nếu nó làm cho ngôn ngữ của bạn dễ dàng hơn, câu trả lời sẽ giống nhau bất kể thế kỷ nào; 1924 và 2124 có cùng số ngày như năm 2024.
BradC

nếu kết quả của mm * dd lớn hơn 100 thì nó được lọc tự động?
DanielIndie

@DanielIndie Đúng, không nên tính ngày "trọn gói". Nói cách khác, ngày 12 tháng 12 năm 2044 không được tính, mặc dù 12 * 12 = 144.
BradC

Vì chúng tôi chỉ cần xử lý một số lượng đầu vào hạn chế, tôi đã chỉnh sửa tất cả chúng. Hãy thoải mái quay lại hoặc định dạng lại.
Shaggy

1
@gwaugh Chỉ cần bạn có thể quyết định chấp nhận làm đầu vào hợp lệ (vì vậy bạn không phải tốn thêm ký tự chuyển đổi giữa hai).
BradC

Câu trả lời:


14

Excel, 48 byte

Hoan hô! Cuối cùng, một cái gì đó Excel thực sự tốt.

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

Lấy đầu vào từ A1 dưới dạng số nguyên 1-99 đại diện cho năm và xuất ra bất cứ nơi nào bạn nhập công thức này. Đây là một công thức mảng, vì vậy hãy sử dụng Ctrl-Shift-Enter thay vì Enter để nhập nó.

Điều này lợi dụng thực tế là COUNTbỏ qua các lỗi, do đó, bất kỳ lỗi nào được gây ra bởi tháng không chia năm (dẫn đến Excel phân tích một cái gì đó như 2/12.5/25hoặc theo ngày không hợp lệ, như 2/29/58, chỉ âm thầm bỏ qua.


1
Rất đẹp. Có lẽ đáng nói đến nó đòi hỏi một năm có 2 chữ số A1. Bước vào một năm có 4 chữ số chỉ đơn giản là trả về 0.
BradC

Thật! Tôi sẽ chỉnh sửa nó thành mô tả.
Sophia Lechner

Ngoài ra tôi nên đề cập rằng đó là địa phương cụ thể; nó phụ thuộc vào việc có một miền sử dụng thứ tự mm / dd / yy. Trong một ngôn ngữ có thứ tự dd / mm / yy, câu trả lời sẽ là cùng một số byte, tất nhiên.
Sophia Lechner

1
Siêu thông minh; Tôi thích cách bạn chỉ kiểm tra 12 ứng cử viên (một tháng một lần), thay vì chạy qua mỗi ngày trong năm.
BradC

Sửa năm để một byte không nhảy một bước?
l4m2

6

Python 2 , 44 byte

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

Hãy thử trực tuyến!

Một hàm ẩn danh được đưa ra như một đối tượng phương thức. Sản xuất tất cả các sản phẩm của (month, day)cặp (m, d)như mã hóa bằng k=32*m+dvới 0≤m≤12, 0≤d≤31, quấn xung quanh. Loại bỏ 29-31 tháng 2 bằng cách loại trừ chúng khỏi phạm vi.


5

Java (JDK 10) , 65 byte

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

Hãy thử trực tuyến!

Tín dụng


Không có năm nhuận phù hợp 29*n, vì vậy không cần kiểm tra
l4m2

Cảm ơn vì đầu vào của bạn. Tôi có thể loại bỏ tổng cộng 27 byte với một loạt các thay đổi khác.
Olivier Grégoire

1
Thay đổi (m==2?29:32)để 29+m%2*3vẫn dường như cho tất cả các OKkết quả. Tín dụng cho câu trả lời Ruby của @AsoneTuhid .
Kevin Cruijssen

4

PowerShell , 94 byte

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

Hãy thử trực tuyến!

Lấy đầu vào là một năm có hai chữ số, sau đó xây dựng một forvòng lặp từ 1/1/yearđến 12/9/year(vì 12/10 trở đi sẽ không bao giờ được tính và điều này sẽ tiết kiệm một byte). Mỗi lần lặp lại, chúng tôi tăng $zsố .Monthlần .Daybằng với năm đầu vào của chúng tôi. Bên ngoài vòng lặp, $zđược để lại trên đường ống và đầu ra là ẩn.

Chỉnh sửa - đây là phụ thuộc vào văn hóa. Các mã trên làm việc cho en-us. Định dạng ngày có thể cần thay đổi cho các nền văn hóa khác.


2
"văn hóa"? Ý bạn là "miền địa phương"? ...
dùng202729

1
@ user202729 Thông thường, có, nhưng tài liệu PowerShell gọi nó là "văn hóa".
admBorkBork

"Văn hóa" là từ mà MS thường sử dụng để nói về miền địa phương, vd. System.Globalization.CARMInfo trong .NET.
- Phục hồi Monica




3

JavaScript (ES6), 91 byte

Tôi tò mò muốn biết làm thế nào mã hóa cứng sẽ so sánh với một tính toán lặp. Đó chắc chắn là còn (xem @ câu trả lời Shaggy của ), nhưng không phải hết sức lâu hơn.

Chỉnh sửa : Tuy nhiên, nó dài hơn nhiều so với công thức trực tiếp hơn (xem câu trả lời @ l4m2 ).

Lấy đầu vào là một số nguyên trong [1..99] .

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

Hãy thử trực tuyến!

Làm sao?

Năm lẻ có cơ hội có mm * dd = yy ít hơn đáng kể so với năm chẵn. Cụ thể hơn, năm lẻ có 0 đến 3 trận, trong khi năm chẵn có 0 đến 7 trận. Điều này cho phép chúng ta mã hóa từng cặp năm chỉ với 5 bit, có thể được biểu diễn một cách thuận tiện dưới dạng một ký tự trong cơ sở 36.




3

Tiện ích Bash + GNU , 57

  • Lưu 1 byte nhờ @SophiaLechner
seq -f1/1/$1+%gday 0 365|date -f- +%m*%d-%y|bc|grep -c ^0

Lưu ý rằng seqlệnh luôn tạo ra một danh sách gồm 365 ngày - cho các năm không nhảy vọt vào ngày 1 tháng 1 năm sau sẽ được đưa vào. Tuy nhiên, trong phạm vi ngày 2001..2099, MM * DD sẽ không bao giờ là YY vào ngày 1 tháng 1 năm sau cho bất kỳ năm nào trong số này, vì vậy ngày thêm này sẽ không ảnh hưởng đến kết quả.

Hãy thử trực tuyến!


Rất hay - tôi thậm chí còn không biết datesẽ làm toán ngày như thế trong khi phân tích cú pháp. seqkhông cần một khoảng trắng sau -f, vì vậy bạn có thể lưu một byte ở đó.
Sophia Lechner

3

T-SQL, 123 121 byte

Theo quy tắc IO của chúng tôi , đầu vào được lấy thông qua bảng t có sẵn với trường số nguyên y , chứa năm có 2 chữ số.

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

Ngắt dòng chỉ dành cho khả năng đọc. Lấy cảm hứng phần lớn từ giải pháp Excel của Sophia .

  • Dòng trên cùng tạo bảng số 12 mục c được nối với bảng đầu vào t .
  • Nếu điều đó trôi qua, tôi kết hợp một ứng cử viên ngày bằng cách sử dụng CONCAT(), điều này ẩn chứa các varcharchuyển đổi kiểu dữ liệu. Nếu không tôi sẽ phải làm một loạt các CASThoặcCONVERT báo cáo.
  • Tìm thấy chức năng đánh giá hoàn hảo ISDATE() , trả về 1 cho ngày hợp lệ và 0 cho ngày không hợp lệ.
  • Gói nó trong một SUM và tôi đã hoàn thành.
  • EDIT : Đã chuyển kiểm tra phân chia số nguyên ( y%m=0) vào WHEREmệnh đề để lưu 2 byte, cảm ơn @RazvanSocol.

Thật không may, nó không ngắn hơn nhiều so với phiên bản bảng tra cứu (sử dụng chuỗi từ phiên bản của osdavison ):

Tra cứu T-SQL, 129 byte

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

EDIT : Để lại bản gốc của tôi ở trên, nhưng chúng ta có thể lưu một vài byte bằng cách sử dụng một vài hàm mới:

  • STRING_SPLIT có sẵn trong MS SQL 2016 trở lên.
  • CONCAT_WS có sẵn trong MS SQL 2017 trở lên.
  • Như trên, thay thế IIFbằngWHERE

MS-SQL 2017, 121 118 byte

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, phiên bản gian lận thêm: 109 byte

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

Yêu cầu bạn phải ở trong mastercơ sở dữ liệu chứa bảng hệ thống spt_values(khi được lọc bởi TYPE='P'), cung cấp cho bạn số đếm từ 0 đến 2048.


Tương tự như các câu trả lời khác, thứ tự tôi lắp ráp ngày ( m/d/y) phụ thuộc vào cài đặt cục bộ của phiên bản SQL. Các địa phương khác có thể yêu cầu một thứ tự khác hoặc một dấu phân cách khác, nhưng tôi không nghĩ sẽ ảnh hưởng đến độ dài mã.
BradC

Tôi đoán bạn đã nhận ra rằng việc chuyển đổi '29/2/64' thành một ngày mang lại 1964-02-29 (không phải 2064-02-29), nhưng xem xét rằng những năm 2000 và 2100 bị loại trừ, đó là một cách hay để rút ngắn mã.
Razvan Socol

Sử dụng SPLIT_STRINGthay vì CTE mang đến 120 byte. Sử dụng CONCAT_WSthay vì CONCATlưu một ký tự khác, đưa nó tới 119 byte.
Razvan Socol

@RazvanSocol Vâng, tôi không chắc chắn thời gian nghỉ giữa các ngày có 2 chữ số ánh xạ đến 19xx so với 20xx, nhưng cả hai đều cho cùng một câu trả lời. Tôi sẽ thử hai gợi ý khác, cảm ơn!
BradC

1
Thay thế IIFbằng WHERE.
Razvan Socol

3

Julia 0,6 , 49 44 42 byte

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

Hãy thử trực tuyến!

-5 byte lấy cảm hứng từ câu trả lời Ruby của Asone Tuhid.
-2 byte thay thế số đếm bằng tổng

Giải trình:

Đối với mỗi tháng itừ 1 đến 12, hãy tính toán y/ivà kiểm tra xem đó có phải là một trong những ngày của tháng đó không. Các tháng có 31 ngày là 1, 3, 5, 7, 8, 10, 12 - vì vậy, chúng là số lẻ dưới 8 và thậm chí ở mức trên 8. Vì vậy, i%2hoặc i÷8là 0 đối với i <8 và 1 đối với i> = 8 ở đây) nên là 1, nhưng không phải cả hai - vì vậy chúng tôi XOR chúng. Nếu kết quả xor là đúng, chúng tôi sẽ kiểm tra ngày 1:28+3tức là 1:31, nếu không, chúng tôi chỉ kiểm tra ngày1:28 .

1:28là đủ cho các tháng còn lại (cải tiến này lấy cảm hứng từ câu trả lời Ruby của Asone Tuhid ) bởi vì:

  • cho tháng hai, khả năng duy nhất sẽ có 2*29 = 58, nhưng 2058không phải là một năm nhuận, vì vậy chúng ta có thể giả sử tháng hai luôn có 28 ngày.

  • các tháng khác với 30 ngày là tháng 4 trở lên - trong đó i*29(vài*30 ) sẽ trên 100, có thể bỏ qua.

Cuối cùng, chúng tôi đếm số lần y/ithuộc về danh sách ngày này (bằng cách sử dụng boolean sumtại đây) và trả lại số đó.


3

JavaScript, 91 85 82 81 77 byte

Lấy đầu vào dưới dạng chuỗi 2 chữ số (hoặc số nguyên 1 hoặc 2 chữ số).

Tận dụng lợi thế của thực tế là new Datesẽ tái đầu tư vào tháng tiếp theo và tiếp tục làm như vậy, nếu bạn vượt qua nó một giá trị ngày vượt quá số ngày trong tháng bạn chuyển qua nó, trong lần lặp đầu tiên, nó sẽ cố gắng xây dựng ngày yyyy-01-345trở thành yyyy-12-11, hoặc yyyy-12-10vào năm nhuận. Chúng tôi không cần kiểm tra ngày sau đó vì 12*11+kết quả là số có 3 chữ số.

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

3 byte được lưu nhờ Arnauld .


Kiểm tra nó

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 byte

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

Đầu vào là trong ô A1ở định dạng yyyy. Đây là một công thức mảng và được nhập bằng Ctrl+ Shift+ Enterđể có dấu ngoặc nhọn{} . Nó khá đơn giản và không có sự thông minh.

Khi trong một công thức mảng, DATE(A1,1,0)+ROW(1:366)cung cấp cho chúng ta một mảng gồm 365 giá trị ngày. Vào những năm không có bước nhảy vọt, điều này sẽ bao gồm ngày 1 tháng 1 năm sau nhưng đó không phải là vấn đề vì 1*1=1và sẽ chỉ được tính là dương tính giả nếu năm sau là 2001nhưng vì phạm vi năm bắt buộc là2001 - 2099 , nó sẽ không bao giờ phát sinh như một vấn đề.

Nếu bạn rút ngắn bit đó thành đơn giản ~, công thức vì dễ thực hiện hơn nhiều:

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

Tôi đã thử sử dụng COUNTIF()thay vì SUM(IF())nhưng Excel thậm chí sẽ không cho tôi nhập nó dưới dạng công thức mảng, ít mang lại cho tôi kết quả. Tôi đã tìm thấy một giải pháp Google Sheets bằng cách sử dụngCountIf() nhưng cùng một phương pháp, hóa ra là 91 byte, chủ yếu là vì nó sử dụng ArrayFormula()thay vì đơn giản { }.

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

Tôi chưa thấy sự đồng thuận, nhưng tôi thường không bao gồm các dấu ngoặc nhọn bên ngoài trong số byte của tôi cho Excel. Họ cảm thấy giống như một cách mà Excel đang định dạng hiển thị của nó hơn là một phần của công thức. Ý kiến?
Sophia Lechner

@SophiaLechner Tôi đã bao gồm chúng thay vì quyết định cách bao gồm các tổ hợp phím bổ sung cần thiết để nhập nó dưới dạng một công thức mảng. Có một câu hỏi meta về điều đó và câu trả lời duy nhất nói rằng lệnh CTRL + ALT + ENTER sẽ được tính là 1 tổ hợp phím. Nếu bạn sử dụng giống như vim ( trên mỗi meta ), thì tổ hợp phím đó sẽ được tính là 1 byte. Tuy nhiên, tôi thường không đếm ENTER khi kết thúc nhập công thức là 1 byte trong các câu trả lời khác.
Kỹ sư Toast

2

Võng mạc 0.8.2 , 55 byte

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

Hãy thử trực tuyến! Mất một năm hai chữ số; thêm 1 byte để hỗ trợ năm có 4 chữ số. Giải thích: Giai đoạn đầu tiên đơn giản là chuyển đổi sang unary. Giai đoạn thứ hai bắt đầu bằng cách khớp 1 đến 12 ký tự trước vị trí khớp, đại diện cho tháng và sau đó cố gắng nhìn về phía trước cho toàn bộ số lần lặp lại của tháng đó. Tuy nhiên, giao diện có chứa một điều kiện, lựa chọn từ tối đa 27 hoặc 30 lần lặp lại tùy theo tháng. Số lượng vị trí phù hợp sau đó là kết quả mong muốn.


2

R , 22 122 byte

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

Hãy thử trực tuyến!

Quyết định đi với một cách tiếp cận bảng tra cứu. Năm đầu vào cần có 2 chữ số.


1
Ngoài ra trên TIO, bạn có thể nhấn nút "liên kết" và nó sẽ tự động định dạng câu trả lời cho bạn. Cảm ơn Dennis đã thiết lập nó!
Giuseppe

Bạn có thể xóa chữ cái đầu tiên if, vì đầu vào có thể 2 chữ số hoặc 4 chữ số, tùy bạn chọn (vì vậy bạn có thể chọn chỉ chấp nhận đầu vào 2 chữ số). Nhưng có vẻ như mã này coi mỗi tháng có chứa 31 ngày, vì vậy, ví dụ: 62 (cho năm 2062) trả về 1 trong đó nó sẽ trả về 0.
sundar - Phục hồi Monica

2
Tôi đã hiểu nhầm. Điều đó đang được nói, tôi khá chắc chắn rằng bảng tra cứu sẽ phải được bao gồm trong số byte.
ngm

@ngm Tôi cũng không chắc có cần đưa vào bảng tra cứu hay không, nhưng tôi sẽ thêm nó vào số byte để đảm bảo an toàn.
Robert S.

Tôi vẫn không chắc chắn tất cả các quy tắc là gì!
ngm


2

J , 29 byte

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

Hãy thử trực tuyến!

Làm thế nào nó hoạt động

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

Đã cố gắng để có được dưới 2 lần giải pháp Jelly :)

Lưu ý bên

Nếu ai đó thực sự muốn mã hóa dữ liệu 99 chữ số, đây là một chút thông tin:

Chia 99 chữ số thành các khối gồm 2 chữ số. Sau đó, chữ số đầu tiên là <4và thứ hai <8, có nghĩa là năm bit có thể mã hóa hai số. Sau đó, toàn bộ dữ liệu có thể được mã hóa thành 250 bit hoặc 32 byte.


2

Python 3 , 158 162 215 241 byte

Đã xóa 4 Cảm ơn Stephen đã chơi golf các điều kiện.

Đã xóa 53 cảm ơn Stephen vì đã chỉ ra khoảng trắng

Đã xóa 26 nhờ liên kết được cung cấp bởi caird

Tôi khá mới ở đây. Không thể nghĩ làm thế nào để làm điều này mà không có ngày trong một tháng được mô tả.

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

Hãy thử trực tuyến!


5
Chào mừng đến với trang web, và bài viết đầu tiên tốt đẹp! Có một số cách công bằng mà bạn có thể chơi golf này, chẳng hạn như xóa một số khoảng trắng, vì vậy hãy chắc chắn kiểm tra các mẹo chơi golf này trong Python
caird coinheringaahing

@cairdcoinheringaahing Cảm ơn lời khuyên của liên kết rất hữu ích!
akozi

1
158 byte - chơi gôn ở một số nơi, nhưng chủ yếu là bạn có một hàng dài các khoảng trống trên dòng thứ ba của mình, không biết làm thế nào những người đến đó
Stephen

@Stephen Cảm ơn :) Tôi đã thêm của bạn dưới dạng hai chỉnh sửa. Một cho không gian màu trắng và một cho sân golf.
akozi

(28if Y%4else 29)có thể rút ngắn thành [29,28][Y%4>0]. Ngoài ra, danh sách dài có thể được rút ngắn [a,...]+2*[a,b,a,b,a]. a,b,ccó thể được thêm vào danh sách tham số để lưu một dòng. int(str(Y)[2:])có thể rút ngắn thành Y%100. Cuối cùng, các biến truy cập chủ yếu có thể được rút ngắn thành lens để hiểu danh sách, điều này cũng cho phép nđược thực hiện a lambda. Điều này làm cho 118 .
Black Owl Kai

2

Forth (gforth) , 60 59 byte

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

Hãy thử trực tuyến!

Phiên bản này lợi dụng thực tế là không thể có nhiều hơn 1 ngày phù hợp mỗi tháng và năm đó phải chia hết cho tháng để phù hợp.

Giải trình

Lặp đi lặp lại qua các tháng, kiểm tra xem năm có chia hết cho tháng không và nếu thương số là <31 (28 cho tháng 2) Các tháng sau tháng 3 không khớp với các ngày lớn hơn 25, vì vậy chúng tôi chỉ có thể giả sử tất cả các tháng (trừ tháng 2) Có 31 ngày cho mục đích của câu đố.

Giải thích mã

: 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 có khái niệm về số có độ dài gấp đôi, được lưu trữ trên ngăn xếp dưới dạng hai số có độ dài đơn (có dạng xy, trong đó giá trị của double = y * 2^(l) + xtrong đó l là kích thước tính theo bit của một đơn trong sắp thực hiện bạn đang làm việc với).

Trong trường hợp này, tôi đã so sánh thương số và phần còn lại với 32 (hoặc 29) 0. Nếu phần còn lại lớn hơn 0 (năm không chia hết theo tháng), lần đầu tiên sẽ tự động lớn hơn 32 (hoặc 29) 0 và kết quả sẽ là sai Nếu phần còn lại là 0, thì nó sẽ giải quyết hiệu quả việc kiểm tra thường xuyên thương số <= 32 (hoặc 29)

Forth (gforth) , 61 byte

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

Hãy thử trực tuyến!

Đã lưu một số byte bằng cách nhận ra rằng chỉ có vấn đề tháng hai về việc có số ngày chính xác trong tháng

Giải trình

So sánh Forth (ít nhất là gforth) trả về -1 cho true và 0 cho 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 byte

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

Hãy thử trực tuyến!


@Shaggy Cảm ơn! (còn lại từ phiên bản trước nơi tôi lặp qua tất cả các days)
user202729

Nếu bạn đổi &&thành &câu trả lời giống như câu trả lời Java của OlivierGrégoire, mặc dù anh ta đã trả lời 19 phút trước đó.
Kevin Cruijssen

@KevinCruijssen Sự trùng hợp ngẫu nhiên. Mặc dù phiên bản của tôi tệ hơn một chút (sử dụng ternary không cần thiết).
dùng202729

1

JavaScript (Node.js) , 108 byte

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>


Tra cứu lực lượng, tốt đẹp!
BradC

Chào mừng đến với PPCG!
Xù xì


1

Python 3, 132 byte

Đây thực sự là một chương trình khá dài nhưng tôi nghĩ nó có thể được quan tâm.

Tất cả các giá trị nằm trong khoảng 0-7 vì vậy tôi mã hóa mỗi số bằng 3 bit trong một chuỗi nhị phân dài. Tôi đã thử dán một chuỗi nhị phân thô vào chương trình python của mình nhưng tôi không thể làm cho nó hoạt động được, vì vậy tôi đã giải quyết trên cơ sở64 trong tệp.

Tôi đã sử dụng chuỗi sau đây làm bảng tra cứu (kết thúc 7 được sử dụng để đệm): 01223242434261334151533172234161321260115040331061312042410060032130113060021220420051013051110140127

Chương trình lấy chuỗi này và giải mã nó thành một số, sau đó sử dụng dịch chuyển bit để trích xuất kết quả.

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

66 byte + tệp 37 byte = 103 byte

Điều này đọc một tệp nhị phân được gọi evà tránh sử dụng base64.

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

Đây là một hexdump của tệp đọc (không có phần đệm):

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 byte

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

Chúng tôi có thể lưu ý rằng việc tháng 4 (và các tháng sau đó) không thực sự quan trọng, kể từ 100/4 <28. Ngoài ra, không cần thiết phải kiểm tra xem năm đó có nhảy vọt hay không. Chúng tôi chỉ phải xác định rằng có 28 ngày vào tháng 2 (không phải 29 vì việc xác thực sẽ chỉ được thực hiện cho năm 2058 không phải là bước nhảy vọt) nếu không nó có thể chỉ là 31 cho bất kỳ tháng nào.

Các cách tiếp cận khác

Oracle SQL (12c Phiên bản 2 trở lên), 151 byte

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 Phiên bản 2 trở lên), 137 byte

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

Cả hai giải pháp có thể ngắn hơn 8 byte nếu chúng ta thay thế (select level l from dual connect by level<=12)bằngxmltable('1to 12'columns l int path'.') nhưng Oracle ném một ngoại lệ vì lỗi (thử nghiệm trên phiên bản 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

Trường hợp duy nhất trong cả hai giải pháp khi năm không thành vấn đề là năm 2058, đây không phải là bước nhảy vọt nên chữ "-1" được sử dụng để chỉ định năm không nhảy.

Oracle SQL, 128 byte

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 byte

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

Cập nhật

Oracle SQL, 110 byte

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 byte

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 byte

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 byte

( replacechức năng trở nên khả dụng)

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 byte

Sử dụng đầu vào đường ống và php -nR:

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

Hãy thử trực tuyến!

PHP , 76 byte

Sử dụng đầu vào dòng lệnh arg 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;

Hãy thử trực tuyến!

Cách tiếp cận lặp đi lặp lại. Vì năm nhuận duy nhất để xem xét là 2 * 29 = 58 và năm 2058 không phải là năm nhuận nên không cần xem xét năm nhuận trong những ngày tháng Hai. Và vì việc đóng gói không phải là vấn đề đáng lo ngại - từ tháng Tư trở đi, bất kỳ ngày nào lớn hơn 25 sẽ vượt quá 100, chúng tôi chỉ nói rằng các tháng còn lại chỉ có 25 ngày.

Đầu vào là 2 chữ số năm thông qua dòng lệnh (-10 byte dưới dạng chương trình, thx để đề xuất từ ​​@Titus).

HOẶC LÀ:

PHP , 101 byte

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

Hãy thử trực tuyến!

Vẫn lặp đi lặp lại nhưng sử dụng các hàm dấu thời gian của PHP. Chấp nhận năm là số có bốn chữ số. Thx đến @Titus để đề xuất sử dụng strtotime()thay vì mktime().


Phiên bản đầu tiên thất bại trong 4 năm chữ số, lần thứ hai thất bại cho hai chữ số. Nhưng suy nghĩ tốt. Hãy thử $m<5?$m-2?31:28:25lần đầu tiên và $d=strtotime("$y-1")lần thứ hai
Titus

Uhm ... Tại sao bạn lại đặt yeval trong ngoặc kép?
Tít

@Titus vì PHP7 hiện xử lý các chữ số có trước 0 là bát phân, vì vậy 08 và 09 thực sự không hợp lệ. tio.run/##K8go@G9jXwAkU5Mz8hUMFWxtFQwsrP//BwA Sử dụng hàm date () bạn chỉ có thể nhận được 2 chữ số, năm không đệm.
640KB

Bummer! tất nhiên.
Tít

1
@Titus, đã cập nhật phiên bản thứ hai bằng cách sử dụng strtotime()thay vì mktime()và triển khai lại dưới dạng chương trình, -7 byte. Ngoài ra, tôi đã xem xét phần lớn các bài nộp, bao gồm cả những bài được bình chọn hàng đầu, sẽ chỉ chấp nhận năm là 2 hoặc 4 chữ số, vì vậy tôi sẽ coi đó là tùy thuộc vào người nộp. Thx một lần nữa cho các đề xuất!
640KB

0

PHP, 74 70 byte

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

chỉ chấp nhận hai chữ số.

Tôi chấp nhận sự cân nhắc của gwaugh và đánh gôn chúng; Cách tiếp cận thứ 1 của tôi dài hơn anh ấy (92 byte):

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 cho phép sử dụng năm có 4 chữ số.


Chạy như ống với -nRhoặc thử chúng trực tuyến .


Bạn có thể lưu 4 byte bằng cách xóa% 100 và chỉ lấy 2 chữ số đầu vào, không sao cả: codegolf.stackexchange.com/questions/162137/ phỏng
640KB
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.