การท้าทายการคูณวันที่


19

(แรงบันดาลใจจากRiddler ของสัปดาห์ที่แล้วเมื่อ FiveThirtyEight.com โพสต์ Sandbox )

ได้รับปีระหว่างปี 2001 ถึงปี 2099 ให้คำนวณและส่งกลับจำนวนวันในช่วงปีปฏิทินดังกล่าวโดยที่mm * dd = yy( yyเป็นปีที่2 หลัก )

เช่นปี 2018 มี 5:

  • 18 มกราคม (1 * 18 = 18)
  • 9 กุมภาพันธ์ (2 * 9 = 18)
  • 6 มีนาคม (3 * 6 = 18)
  • 3 มิถุนายน (6 * 3 = 18)
  • 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

@DanielIndie ถูกต้องไม่ควรนับวันที่ "ล้อมรอบ" กล่าวอีกนัยหนึ่ง 12 ธันวาคม 2044 ไม่นับแม้ว่า 12 * 12 = 144
BradC

เนื่องจากเราจำเป็นต้องจัดการอินพุตจำนวน จำกัด เท่านั้นฉันจึงแก้ไขได้ทั้งหมดโปรดย้อนกลับหรือฟอร์แมตใหม่ได้
ปุย

1
@gwaugh เพียงแค่คุณสามารถตัดสินใจได้ว่าจะยอมรับการป้อนข้อมูลที่ถูกต้องหรือไม่
BradC

คำตอบ:


14

Excel, 48 ไบต์

ไชโย! ในที่สุดสิ่งที่ Excel ดีจริงๆ

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

รับอินพุตจาก A1 ในรูปของจำนวนเต็ม 1-99 ที่แสดงถึงปีและส่งออกไปยังทุกที่ที่คุณป้อนสูตรนี้ มันเป็นสูตรอาร์เรย์ดังนั้นใช้ Ctrl-Shift-Enter แทน 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

Python 2 , 44 ไบต์

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

ลองออนไลน์!

ฟังก์ชั่นที่ไม่ระบุชื่อที่กำหนดเป็นวัตถุวิธีการ ผลิตผลิตภัณฑ์ทั้งหมดของ(month, day)คู่(m, d)ตามที่เข้ารหัสโดยk=32*m+dใช้0≤m≤12, 0≤d≤31ล้อมรอบ กำจัด 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;}

ลองออนไลน์!

เครดิต

  • 8 ไบต์บันทึกขอบคุณที่l4m2
  • 4 ไบต์บันทึกขอบคุณที่Asone Tuhidบนของพวกเขาคำตอบทับทิม

ไม่เหมาะกับปีอธิกสุรทิน29*nดังนั้นจึงไม่จำเป็นต้องตรวจสอบ
l4m2

ขอบคุณสำหรับข้อมูลของคุณ ฉันสามารถลบ 27 ไบต์โดยรวมกับการเปลี่ยนแปลงอื่น ๆ
Olivier Grégoire

1
การเปลี่ยน(m==2?29:32)เป็น29+m%2*3ยังคงให้OKผลลัพธ์ทั้งหมด เครดิต@AsoneTuhid 'คำตอบทับทิม
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
"วัฒนธรรม"? คุณหมายถึง "locale" หรือเปล่า ...
user202729

1
@ user202729 เรียกขานใช่ แต่เอกสาร PowerShell อ้างถึงเป็น"วัฒนธรรม"
AdmBorkBork

"วัฒนธรรม" เป็นคำที่ MS ใช้เพื่อพูดคุยเกี่ยวกับสถานที่เช่น System.Globalization.CultureInfoใน. NET
sundar - Reinstate Monica


4

JavaScript (Node.js) , 48 44 43 ไบต์

F=(x,h)=>h>12?0:F(x,-~h)+(x/h<3*h%6+28>x%h)

ลองออนไลน์!

JavaScript (Node.js) , 59 58 ไบต์

x=>[a=0,...'030101001010'].map((k,m)=>x%m|x/m>31-k||a++)|a

ลองออนไลน์!


ผมรู้ว่าวิธีการแก้ปัญหาทางคณิตศาสตร์จะสั้น ๆ แต่ผมสนุกกับรุ่นของฉัน :)
ปุย


3

JavaScript (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

ยูทิลิตี Bash + GNU , 57

  • บันทึก 1 ไบต์ขอบคุณ @SophiaLechner
seq -f1/1/$1+%gday 0 365|date -f- +%m*%d-%y|bc|grep -c ^0

สังเกตว่า seqคำสั่งจะสร้างรายการวันที่ 366 เสมอ - สำหรับปีที่ไม่ได้ก้าวกระโดดจะรวมอยู่ในวันที่ 1 มกราคมของปีถัดไป อย่างไรก็ตามในช่วงวันที่ 2001..2099 MM * DD จะไม่มีวันเป็น YY ในวันที่ 1 มกราคมของปีถัดไปสำหรับปีใด ๆ เหล่านี้ดังนั้นวันพิเศษนี้จะไม่ส่งผลกระทบต่อผลลัพธ์

ลองออนไลน์!


ดีมาก - ฉันไม่เคยรู้มาก่อนเลยว่าdateจะทำตัวแบบทางคณิตศาสตร์ในขณะที่วิเคราะห์คำ seqไม่ต้องการช่องว่างหลังจาก-fนั้นคุณจึงสามารถบันทึกไบต์ที่นั่นได้
Sophia Lechner

3

T-SQL, 123 121 ไบต์

ต่อกฎ IO ของเราใส่จะได้รับการผ่านทางที่มีอยู่ก่อนตารางทีกับสนามจำนวนเต็มYซึ่งมีปี 2 หลัก

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

การขึ้นบรรทัดใหม่มีไว้เพื่อให้อ่านได้เท่านั้น แรงบันดาลใจส่วนใหญ่โดยการแก้ปัญหา Excel โซเฟีย

  • บรรทัดบนสุดสร้าง 12 รายการตารางจำนวนที่จะเข้าร่วมในตารางการป้อนข้อมูลที
  • หากผ่านฉันจะรวมผู้สมัครวันที่เข้าด้วยกัน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_STRINGแทน CTE จะลดขนาดลงเหลือ 120 ไบต์ ใช้CONCAT_WSแทนการCONCATบันทึกอักขระอื่นรับเป็น 119 ไบต์
Razvan Socol

@RazvanSocol ใช่ฉันไม่แน่ใจว่าตัวแบ่งอยู่ที่ไหนระหว่างวันที่ 2 หลักที่ตรงกับ 19xx กับ 20xxx แต่ทั้งคู่ตอบเหมือนกัน ฉันจะลองอีกสองข้อเสนอแนะขอขอบคุณ!
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)

ลองออนไลน์!

-5 ไบต์แรงบันดาลใจจากคำตอบ Ruby ของ Asone Tuhid
-2 ไบต์แทนที่การนับด้วยผลรวม

คำอธิบาย:

สำหรับแต่ละเดือนiตั้งแต่ 1 ถึง 12 ให้คำนวณy/iและตรวจสอบว่าเป็นวันใดวันหนึ่งของเดือนนั้นหรือไม่ เดือนที่มี 31 วันคือ 1, 3, 5, 7, 8, 10, 12 - ดังนั้นพวกเขาจึงต่ำกว่า 8 และมากกว่าและเท่ากับ 8 ดังนั้นอย่างใดอย่างหนึ่งi%2หรือi÷8(ซึ่งคือ 0 สำหรับ i <8 และ 1 สำหรับ i> = 8 ตรงนี้) ควรเป็น 1 แต่ไม่ใช่ทั้งคู่ - ดังนั้นเราจึง XOR พวกเขา หากผลการ xor เป็นจริงเราจะตรวจสอบวัน1:28+3เช่นมิฉะนั้นเราจะตรวจสอบเพียงแค่วัน1:311:28

1:28เพียงพอสำหรับส่วนที่เหลือของเดือน (การปรับปรุงนี้ได้แรงบันดาลใจจากคำตอบ Ruby ของ Asone Tuhid ) เพราะ:

  • สำหรับเดือนกุมภาพันธ์มีความเป็นไปได้เพียงอย่างเดียว2*29 = 58แต่2058ไม่ใช่ปีอธิกสุรทินดังนั้นเราจึงสามารถคิดว่า ก.พ. มี 28 วันเสมอ

  • เดือนอื่น ๆ ที่มี 30 วันคือ 4 เดือนขึ้นไป - ซึ่งi*29(และi*30) จะสูงกว่า 100 ซึ่งสามารถละเว้นได้

ในที่สุดเราก็นับจำนวนครั้งที่y/iอยู่ในรายการวันนี้ (โดยใช้บูลีนsumที่นี่) และคืนค่านั้น


3

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

3 ไบต์บันทึกขอบคุณที่Arnauld


ทดสอบมัน

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 ไบต์

{=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และจะนับเป็นค่าบวกที่ผิดพลาดหากปีหน้าเป็น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)

ฉันไม่ได้เห็นฉันทามติ แต่โดยทั่วไปฉันไม่ได้รวมวงเล็บปีกกาด้านนอกในจำนวนไบต์ของฉันสำหรับ Excel พวกเขารู้สึกเหมือนเป็นวิธีที่ Excel จัดรูปแบบการแสดงผลมากกว่าส่วนหนึ่งของสูตร ความเห็น?
Sophia Lechner

@SophiaLechner ฉันได้รวมพวกเขาไว้แล้วแทนที่จะตัดสินใจว่าจะรวมการกดแป้นพิเศษที่จำเป็นในการป้อนเป็นสูตรอาร์เรย์ได้อย่างไร มีเป็นคำถาม metaเกี่ยวกับที่และคำตอบเดียวที่บอกว่า CTRL + ALT + ENTER คำสั่งจะนับเป็น 1 การกดแป้นพิมพ์ หากคุณใช้เหมือนกับ vim ( ต่อ meta ) การกดแป้นนั้นจะนับเป็น 1 ไบต์ อย่างไรก็ตามฉันมักจะไม่นับ ENTER เมื่อสิ้นสุดการป้อนสูตรเป็น 1 ไบต์ในคำตอบอื่น ๆ
Engineer Toast

2

เรติน่า 0.8.2 , 55 ไบต์

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

ลองออนไลน์! ใช้เวลาปีสองหลัก; เพิ่ม 1 ไบต์เพื่อสนับสนุนปี 4 หลัก คำอธิบาย: ขั้นตอนแรกเพียงแปลงเป็นเอกภาพ ขั้นตอนที่สองเริ่มต้นด้วยการจับคู่ 1 ถึง 12 ตัวอักษรก่อนตำแหน่งการแข่งขันซึ่งเป็นตัวแทนของเดือนและจากนั้นพยายามที่จะมองหาการทำซ้ำจำนวนเต็มของเดือน อย่างไรก็ตาม lookahead มีเงื่อนไขซึ่งเลือกระหว่างการทำซ้ำมากถึง 27 หรือ 30 เพิ่มเติมขึ้นอยู่กับเดือน การนับตำแหน่งการแข่งขันนั้นเป็นผลลัพธ์ที่ต้องการ


2

R , 22 122 ไบต์

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

ลองออนไลน์!

ตัดสินใจที่จะไปด้วยวิธีการค้นหาตาราง ปีที่ป้อนต้องเป็นตัวเลข 2 หลัก


1
บน TIO คุณสามารถกดปุ่ม "ลิงค์" และมันจะจัดรูปแบบคำตอบให้คุณโดยอัตโนมัติ ขอบคุณเดนนิสสำหรับการตั้งค่า!
จูเซปเป้

คุณสามารถลบเริ่มต้น ifตั้งแต่การป้อนข้อมูลสามารถเป็นได้ทั้ง 2 หลักหรือ 4 หลักที่คุณเลือก (เพื่อให้คุณสามารถเลือกที่จะรับข้อมูลเพียง 2 หลัก) แต่ดูเหมือนว่ารหัสที่พิจารณาทุกเดือนจะมี 31 วันดังนั้นสำหรับเช่น., 62 (สำหรับ 2062) ผลตอบแทน 1 ที่มันควรกลับ 0
sundar - Reinstate Monica

2
ฉันเข้าใจผิด. ที่ถูกกล่าวว่าฉันค่อนข้างแน่ใจว่าตารางการค้นหาจะต้องรวมอยู่ในการนับไบต์
ngm

@ngm ฉันไม่แน่ใจว่าหากต้องการตารางการค้นหา แต่ฉันจะเพิ่มลงในจำนวนไบต์เพื่อความปลอดภัย
Robert S.

ฉันยังไม่แน่ใจว่ากฎทั้งหมดเป็นอย่างไร!
ngm

2

C (gcc), 65 60 59 ไบต์

d(a,t,e){for(t=0,e=13;e-->1;)t+=a%e<1&a/e<(e-2?32:29);a=t;}

ท่าเรือ user202729 ของ Java คำตอบ ลองออนไลน์ได้ที่นี่ ขอบคุณJonathan Frechสำหรับการเล่นกอล์ฟ 1 ไบต์


a=0,m=13;for(;for(a=0,m=13;~>
Jonathan Frech

@JathanathanFrech ขอบคุณที่ชี้ให้เห็นว่าฉันได้แก้ไขแล้ว
OOBalance

2

J , 29 ไบต์

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

ลองออนไลน์!

มันทำงานอย่างไร

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

พยายามอย่างหนักที่จะได้รับต่ำกว่า 2 เท่าของสารละลายเจลลี่ :)

ข้อความด้านข้าง

หากมีคนต้องการ hardcode ข้อมูล 99 หลักจริงๆนี่เป็นข้อมูลเล็กน้อย:

แบ่ง 99 หลักออกเป็นชิ้น ๆ 2 หลัก จากนั้นตัวเลขตัวแรกคือ<4และตัวที่สอง<8ซึ่งหมายความว่าห้าบิตสามารถเข้ารหัสตัวเลขสองตัวได้ จากนั้นข้อมูลทั้งหมดสามารถเข้ารหัสใน 250 บิตหรือ 32 ไบต์


2

Python 3 , 158 162 215 241ไบต์

ลบออก 4 ขอบคุณ Stephen สำหรับการเล่นกอล์ฟตามเงื่อนไข

ลบ 53 ขอบคุณ Stephen สำหรับการชี้พื้นที่สีขาว

ลบออก 26 ขอบคุณลิงก์ที่ให้บริการโดย caird

ฉันค่อนข้างใหม่ในเรื่องนี้ ไม่สามารถคิดวิธีการทำสิ่งนี้โดยไม่ต้องมีวันในหนึ่งเดือน

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

ลองออนไลน์!


5
ยินดีต้อนรับสู่เว็บไซต์และโพสต์แรกที่ดี! มีหลายวิธีที่คุณสามารถเล่นกอล์ฟนี้ได้เช่นการลบช่องว่างออกดังนั้นอย่าลืมตรวจสอบเคล็ดลับการเล่นกอล์ฟใน Python
caird coinheringaahing

@cairdcoinheringaahing ขอบคุณสำหรับคำแนะนำลิงค์มีประโยชน์มาก!
akozi

1
158 bytes - ตีกอล์ฟออกไป แต่ส่วนใหญ่คุณมีช่องว่างขนาดใหญ่ในบรรทัดที่สามของคุณไม่ว่าพวกเขาจะไปถึงที่นั่นได้อย่างไร
Stephen

@ สตีเฟ่นขอบคุณ :) ฉันเพิ่มของคุณเป็นสองการแก้ไข หนึ่งสำหรับพื้นที่สีขาวและอื่น ๆ เช่นการเล่นกอล์ฟ
akozi

(28if Y%4else 29)[29,28][Y%4>0]สามารถลงไป [a,...]+2*[a,b,a,b,a]นอกจากนี้ยังมีรายการยาวสามารถลงไป a,b,cสามารถเพิ่มในรายการพารามิเตอร์เพื่อบันทึกบรรทัด สามารถลงไปint(str(Y)[2:]) Y%100สุดท้ายตัวแปรเคาน์เตอร์สามารถส่วนใหญ่จะลงไปlenของ comprehensions รายการนี้ยังช่วยให้ที่จะทำn lambdaนี้จะทำให้118
Black Owl Kai

2

ออกมา (gforth) , 60 59 ไบต์

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

ลองออนไลน์!

รุ่นนี้ใช้ประโยชน์จากความจริงที่ว่าไม่สามารถมีวันที่ตรงกันมากกว่า 1 วันต่อเดือนและปีจะต้องมีการหารด้วยเดือนเพื่อให้ตรงกับ

คำอธิบาย

วนซ้ำทุกเดือนตรวจสอบว่าปีหารด้วยเดือนหรือไม่และถ้าหารคือ <31 (28 สำหรับ ก.พ. ) เดือนหลังจากเดือนมีนาคมไม่ตรงกับวันที่มากกว่า 25 ดังนั้นเราสามารถสรุปได้ว่าทุกเดือน (นอกเหนือจาก ก.พ. ) มี 31 วันสำหรับจุดประสงค์ในการไขปริศนา

รหัสคำอธิบาย

: 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 มีแนวคิดของตัวเลขความยาวสองเท่าซึ่งถูกเก็บไว้ในสแต็กเป็นตัวเลขสองตัวที่มีความยาวเดี่ยวสองตัว (ของรูปแบบ xy โดยที่ค่าของ double = y * 2^(l) + xโดยที่ l คือขนาดในบิตของเดี่ยวใน การใช้งานที่คุณกำลังดำเนินการ)

ในกรณีนี้ฉันเปรียบเทียบผลหารและส่วนที่เหลือเป็น 32 (หรือ 29) 0 หากส่วนที่เหลือมากกว่า 0 (ปีไม่หารด้วยเดือน) คู่แรกจะใหญ่กว่าโดยอัตโนมัติ 32 (หรือ 29) 0 และผลลัพธ์ จะเป็นเท็จ หากส่วนที่เหลือเป็น 0 ก็จะช่วยให้ตรวจสอบความฉลาดทางปกติ <= 32 (หรือ 29) ได้อย่างมีประสิทธิภาพ

Forth (gforth) , 61 ไบต์

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

ลองออนไลน์!

บันทึกจำนวนไบต์ด้วยการตระหนักว่าเฉพาะเดือนกุมภาพันธ์เท่านั้นที่มีจำนวนวันที่ถูกต้องในเดือนนั้น

คำอธิบาย

การเปรียบเทียบ Forth (อย่างน้อย gforth) จะส่งคืน -1 สำหรับจริงและ 0 สำหรับเท็จ

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 ไบต์

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

ลองออนไลน์!


@Shaggy ขอบคุณ! (เหลือจากรุ่นก่อนหน้าที่ฉันวนรอบdays ทั้งหมด)
user202729

ถ้าคุณเปลี่ยน&&ไป&เป็นคำตอบเดียวกับOlivierGrégoireคำตอบของ Java แม้ว่าเขาจะได้ตอบ 19 นาทีก่อนหน้านี้
Kevin Cruijssen

@KevinCruijssen บังเอิญบังเอิญ ถึงแม้ว่าเวอร์ชั่นของฉันจะแย่ไปกว่านี้อีกเล็กน้อย
user202729

1

JavaScript (Node.js) , 108 ไบต์

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>


การค้นหาที่ดุร้ายกำลังดี!
BradC

ยินดีต้อนรับสู่ PPCG!
ปุย


1

Python 3, 132 ไบต์

นี่เป็นโปรแกรมที่ค่อนข้างยาว แต่ฉันคิดว่ามันน่าสนใจ

ค่าทั้งหมดอยู่ระหว่าง 0-7 ดังนั้นฉันเข้ารหัสแต่ละตัวเลขด้วย 3 บิตในสตริงไบนารีที่มีความยาว ฉันพยายามวางสตริงไบนารีแบบดิบลงในโปรแกรมไพ ธ อนของฉัน แต่ฉันไม่สามารถใช้งานได้ดังนั้นฉันจึงตัดสินบน base64 ในไฟล์

ฉันใช้สตริงต่อไปนี้เป็นตารางการค้นหา (สิ้นสุด 7 ที่ใช้สำหรับการขยาย): 01223242434261334151533172234161321260115040331061312042410060032130113060021220420051013051110140127

โปรแกรมใช้สตริงนี้และถอดรหัสเป็นตัวเลขจากนั้นใช้การเลื่อนบิตเพื่อแยกผลลัพธ์

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

66 ไบต์ + ไฟล์ 37 ไบต์ = 103 ไบต์

สิ่งนี้จะอ่านไฟล์ไบนารีที่เรียกว่าeและหลีกเลี่ยงการใช้ base64

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

นี่คือ hexdump ของไฟล์อ่าน (โดยไม่มีการเติมเต็ม):

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 ไบต์

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

เราอาจทราบว่าไม่สำคัญว่าจะมีกี่วันในเดือนเมษายน (และเดือนต่อมา) ตั้งแต่ 100/4 <28 นอกจากนี้ยังไม่จำเป็นต้องตรวจสอบว่าปีนั้นกระโดดหรือไม่ เราเพียงแค่ต้องระบุว่ามี 28 วันในเดือนกุมภาพันธ์ (ไม่ใช่ 29 เพราะการตรวจสอบจะดำเนินการเฉพาะในปี 2058 ซึ่งไม่ได้เป็นการก้าวกระโดด) มิฉะนั้นมันอาจเป็นเพียง 31 สำหรับเดือนใด ๆ

แนวทางอื่น ๆ

Oracle SQL (12c รีลีส 2 และใหม่กว่า), 151 ไบต์

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 รีลีส 2 และใหม่กว่า), 137 ไบต์

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

วิธีแก้ปัญหาทั้งสองอาจสั้นลง 8 ไบต์ถ้าเราแทนที่(select level l from dual connect by level<=12)ด้วยxmltable('1to 12'columns l int path'.')แต่ Oracle ส่งข้อยกเว้นเนื่องจากข้อผิดพลาด (ทดสอบกับรุ่น 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

กรณีเดียวในการแก้ปัญหาทั้งสองเมื่อปีมีความสำคัญคือ 2058 ซึ่งไม่ใช่การก้าวกระโดดดังนั้นตัวอักษร '-1' ถูกใช้เพื่อระบุปีที่ไม่ก้าวกระโดด

Oracle SQL ขนาด 128 ไบต์

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 ไบต์

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

ปรับปรุง

Oracle SQL, 110 ไบต์

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 ไบต์

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 ไบต์

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 ไบต์

( replaceฟังก์ชั่นใช้งานได้)

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 ไบต์

ใช้อินพุตท่อและphp -nR:

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

ลองออนไลน์!

PHP , 76 ไบต์

การใช้อินพุตบรรทัดคำสั่ง 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;

ลองออนไลน์!

แนวทางการทำซ้ำ เนื่องจากปีอธิกสุรทินเพียงอย่างเดียวที่จะดูคือ 2 * 29 = 58 และปี 2058 ไม่ใช่ปีอธิกสุรทินไม่จำเป็นต้องพิจารณาปีอธิกสุรทินในวัน ก.พ. และเนื่องจากการขึ้นฉากไม่ใช่ปัญหา - ตั้งแต่เดือนเมษายนเป็นต้นไปทุกวันที่มากกว่า 25 จะเกิน 100 เราแค่บอกว่าส่วนที่เหลือของเดือนมีเพียง 25 วัน

ข้อมูลที่ป้อนคือ 2 หลักปีผ่านทางบรรทัดคำสั่ง (-10 ไบต์เป็นโปรแกรม, ขอบคุณไปยังข้อเสนอแนะจาก @Titus)

หรือ:

PHP , 101 ไบต์

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

ลองออนไลน์!

ยังซ้ำอยู่ แต่ใช้ฟังก์ชันการประทับเวลาของ PHP ยอมรับปีเป็นตัวเลขสี่หลัก thx เพื่อ @Titus สำหรับข้อเสนอแนะของการใช้แทนstrtotime()mktime()


เวอร์ชันแรกล้มเหลวเป็นเวลา 4 หลักส่วนที่สองล้มเหลวเป็นสองหลัก แต่ความคิดที่ดี ลอง$m<5?$m-2?31:28:25เป็นภาคแรกและ$d=strtotime("$y-1")รอบที่สอง
ติตัส

อืม ... ทำไมคุณใส่yeval ด้วยเครื่องหมายคำพูด?
ติตัส

@Titus เนื่องจาก PHP7 ในตอนนี้ใช้ตัวเลขเป็นหลักนำหน้าด้วยเลขฐานแปดดังนั้น 0 และ 09 จึงไม่ถูกต้อง tio.run/##K8go@G9jXwAkU5Mz8hUMFWxtFQwsrP//BwA การใช้ฟังก์ชั่น date () คุณจะได้รับ 2 หลักปีแบบไม่มีศูนย์
640KB

แย่จัง! แน่นอน.
ติตัส

1
@Titus รุ่นที่สองที่ได้รับการอัปเดตโดยใช้strtotime()แทนmktime()และนำมาใช้อีกครั้งเป็นโปรแกรม -7 ไบต์ นอกจากนี้ฉันดูที่ส่วนใหญ่ของการส่งรวมถึงคนที่ได้รับคะแนนสูงสุดจะยอมรับเฉพาะปีเป็น 2 หรือ 4 หลักดังนั้นฉันจะเอาไปหมายความว่ามันขึ้นอยู่กับผู้ส่ง ขอบคุณอีกครั้งสำหรับคำแนะนำ!
640KB

0

PHP, 74 70 ไบต์

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

ยอมรับปีสองหลักเท่านั้น

ฉันนำข้อพิจารณาของ gwaughมาใช้และตีกอล์ฟพวกมัน วิธีแรกของฉันยาวกว่าของเขา (92 ไบต์):

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 อนุญาตให้ใช้ปี 4 หลัก


ทำงานเป็นท่อที่มี-nRหรือลองพวกเขาออนไลน์


คุณสามารถบันทึก 4 ไบต์โดยการลบ% 100 และรับเพียง 2 หลักซึ่งก็โอเค: codegolf.stackexchange.com/questions/162137/ …
640KB
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.