วันจันทร์สุดท้าย


27

วันจันทร์ที่ 31 ตุลาคมเป็นวันฮาโลวีน และฉันก็คิด - ฉันสงสัยว่าเดือนอื่น ๆ ที่มีวันสุดท้ายของเดือนก็เป็นวันจันทร์เช่นกัน?

อินพุต

  • เป็นจำนวนเต็มบวกในรูปแบบที่สะดวกใด ๆ10000 > y > 0ที่เป็นตัวแทนของปี
  • อินพุตสามารถเพิ่มด้วยศูนย์ (เช่น0025สำหรับปี25) หากต้องการ

เอาท์พุต

  • รายการของเดือนในปีนั้นซึ่งวันสุดท้ายของเดือนคือวันจันทร์
  • นี่อาจเป็นชื่อเดือน (เช่น, January, March, October), หรือชื่อย่อ ( Jan, Mar, Oct) หรือตัวเลข ( 1, 3, 10), เป็นบรรทัดแยกหรือรายการหรือคั่น, ฯลฯ ตราบใดที่มันไม่มีความชัดเจนต่อผู้อ่าน
  • รูปแบบผลลัพธ์ต้องสอดคล้องกัน:
    • สำหรับอินพุตทุกปี (หมายถึงคุณไม่สามารถส่งออกชื่อเดือนสำหรับอินพุตบางส่วนและหมายเลขเดือนสำหรับอินพุตอื่น ๆ )
    • เช่นเดียวกับที่สอดคล้องต่อการส่งออก (หมายถึงคุณไม่สามารถส่งออก1สำหรับJanuaryในการส่งออกเช่นเดียวกับJulสำหรับJuly)
    • โดยทั่วไปเลือกรูปแบบหนึ่งและติดกับมัน

กฎระเบียบ

  • สมมติปฏิทินเกรกอเรียนสำหรับอินพุต / y = 1เอาต์พุตแม้ลงไป
  • จำนวนปีอธิกสุรทินต้องถูกนับอย่างถูกต้อง (เพื่อเตือนความจำ: ทุก ๆ ปีหารด้วย 4 ยกเว้นปีที่หารด้วย 100 ไม่ได้เว้นแต่หารด้วย 400 - 1700, 1800, 1900 ทั้งหมดไม่ได้เป็นปีอธิกสุรทิน แต่ปี 2000 คือ)
  • คุณสามารถใช้เครื่องมือคำนวณวันที่แบบบิวด์อินหรืออื่น ๆ ที่คุณต้องการ
  • ยอมรับได้ทั้งโปรแกรมหรือฟังก์ชั่น หากฟังก์ชั่นคุณสามารถส่งคืนผลลัพธ์มากกว่าการพิมพ์
  • ช่องโหว่มาตรฐานเป็นสิ่งต้องห้าม
  • นี่คือเพื่อให้ใช้กฎการเล่นกอล์ฟตามปกติทั้งหมดและรหัสที่สั้นที่สุด (เป็นไบต์) ชนะ

ตัวอย่าง

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

ลีดเดอร์บอร์ด



1
ที่เกี่ยวข้อง แต่ไม่ซ้ำกันหรือ?
ElPedro

@ElPedro ที่เกี่ยวข้อง แต่ไม่ซ้ำกัน ตัวแรกไม่อนุญาตให้มีบิวด์อินและขอคอมโบวันที่ / วันที่กำหนด (วันศุกร์ที่ 13) ในขณะที่ตัวที่สองขอวันอาทิตย์สุดท้ายของทุกเดือนของปี จำกัด ระหว่าง 1900 ถึง 3015
AdmBorkBork

ขออภัย @TimmD ความคิดเห็นของคุณเข้าใจผิด
ElPedro

1
@ElPedro ไม่มีปัญหา! ฉันอยากจะมีคำถามและมีความชัดเจนมากกว่าที่จะไม่มีคำถามและมีสิ่งที่ไม่ชัดเจน
AdmBorkBork

คำตอบ:


2

Dyalog APLกับdfns 's แคเวอร์ชัน 15.0: 22; เวอร์ชัน 16.0: 19 ไบต์

)copy dfnsฟังก์ชั่นแคลมาพร้อมกับการเริ่มต้นติดตั้งเพียงแค่ใส่

รุ่น 15.0: ∊⎕{⍵/⍨2=≢⍎⊢⌿cal⍺⍵}¨⍳12

เกณฑ์ (แบน)

⎕{... อินพุตตัวเลขเป็นอาร์กิวเมนต์ซ้ายไปยังฟังก์ชันที่ไม่ระบุตัวตนดังต่อไปนี้รับค่าด้านขวาแต่ละค่าเป็นอาร์กิวเมนต์ขวา

⍵/⍨ อาร์กิวเมนต์ if (ให้รายการที่ว่างเปล่าถ้าไม่)

2= สอง (คือวันอาทิตย์และวันจันทร์) เท่ากับ

นับของ

ตัวเลขใน

⊢⌿ แถวล่างสุดของ

cal ปฏิทินสำหรับ

⍺⍵ ปีอาร์กิวเมนต์ซ้าย, เดือนอาร์กิวเมนต์ขวา, หลังถูก

⍳12 1 ถึง 12

รุ่น 16.0: ⍸2=⎕{≢⍎⊢⌿cal⍺⍵}¨⍳12

ดัชนีที่

2= สองเท่ากับ (คือวันอาทิตย์และวันจันทร์)

⎕{... อินพุตตัวเลขเป็นอาร์กิวเมนต์ซ้ายไปยังฟังก์ชันที่ไม่ระบุตัวตนดังต่อไปนี้รับค่าด้านขวาแต่ละค่าเป็นอาร์กิวเมนต์ขวา

นับของ

ตัวเลขใน

⊢⌿ แถวล่างสุดของ

cal ปฏิทินสำหรับ

⍺⍵ ปีอาร์กิวเมนต์ซ้าย, เดือนอาร์กิวเมนต์ขวา, หลังถูก

⍳12 1 ถึง 12


19

JavaScript (Firefox 30+), 112 109 103 95 ไบต์

ดูสิไม่มีบิวด์อิน!

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

นี่คือเวอร์ชั่น ES6 107- ไบต์:

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

และนี่คือความพยายามครั้งก่อนของฉัน123 113 ไบต์ของ ES6:

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

คำอธิบาย

วันของสัปดาห์ของปีนั้น ๆ จะถูกคำนวณดังนี้:

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

ในคำอื่น ๆ :

  • yเอา
  • เพิ่มจำนวนปีที่ 4 ก่อนหน้าy( y>>2)
  • ลบจำนวน 100 ปีก่อนy( y/100|0)
  • บวกกลับในจำนวน 400 ปีก่อนy; นี้เป็น 1/4 ของเราจึงใช้y/100|0*3/4|0

จากนั้นเราปรับผลลัพธ์โดย 7 ถ้าเราให้0ค่าเฉลี่ยวันอาทิตย์, 1ค่าเฉลี่ยวันจันทร์, ฯลฯ ผลลัพธ์จะตรงกับวันในสัปดาห์ของวันที่ 31 ธันวาคมของปีนั้น 1ดังนั้นสำหรับเดือนธันวาคมเราต้องการตรวจสอบว่าผลที่ได้คือ สิ่งนี้ทำให้เราเป็นคนสุดท้ายในสายอักขระ

วันสุดท้ายของเดือนพฤศจิกายนคือ 31 วันก่อนวันสุดท้ายของเดือนธันวาคม ซึ่งหมายความว่าสำหรับวันสุดท้ายของเดือนพฤศจิกายนเป็นวันจันทร์ที่ 31 ธันวาคมจะต้องเป็น(1 + 31) % 7 = 4= วันพฤหัสบดี

ขั้นตอนนี้ซ้ำจนกว่าเราจะกลับถึงเดือนมีนาคม (a 3) ไม่ว่าจะมีวันอธิกสุรทินหรือไม่ก็ตามวันสุดท้ายของเดือนกุมภาพันธ์คือ 31 วันก่อนวันสุดท้ายของเดือนมีนาคมดังนั้นเราจึงสามารถคำนวณได้เช่น(3 + 31) % 7 = 6กัน ส่วนที่ยุ่งยากคือการหาค่าที่ถูกต้องสำหรับเดือนมกราคม:

  • ถ้าเป็นปีอธิกสุรทินที่วันสุดท้ายของเดือนมกราคมเป็น 29 วันก่อนวันสุดท้ายของ ก.พ. (6 + 29) % 7 = 0มีผลในการ
  • มิฉะนั้นจะเป็น 28 วันก่อนวันสุดท้ายของ ก.พ. (6 + 28) % 7 = 6มีผลในการ

เราสามารถคำนวณได้ว่าเป็นปีอธิกสุรทินที่มีตัวอย่างต่อไปนี้หรือไม่:

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

สิ่งนี้จะให้0ถ้าyไม่ใช่ปีอธิกสุรทินและจำนวนเต็มบวกเป็นอย่างอื่น สิ่งนี้ทำให้เรา

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

สำหรับการคำนวณวันสำหรับเดือนมกราคม อย่างไรก็ตามเราสามารถทำได้ดีกว่าโดยการย้อนกลับเงื่อนไข:

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

เนื่องจากผลลัพธ์ที่ผิดพลาดเป็น 0 อยู่เสมอเราจึงสามารถลดได้

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

ประหยัดหนึ่งไบต์ที่มีค่ามากกว่านี้

เมื่อรวมทั้งหมดเข้าด้วยกันเราวนรอบอักขระแต่ละตัวในสตริงโดยตรวจสอบว่าแต่ละอันเท่ากับวันในสัปดาห์ของวันที่ 31 ธันวาคม เราเก็บดัชนีของดัชนีที่ตรงกับคืนอาเรย์นี้ในที่สุด และนั่นคือวิธีที่คุณทำการคำนวณแบบก้าวกระโดดโดยไม่ต้องใช้โปรแกรมในตัว


Owww ... สมองของฉันคุณคิดเป็นปีอธิกสุรทินหรือไม่
Magic Octopus Urn

2
@carusocomputing นั่นคือสิ่งที่!(y%4)*y%100|!(y%400)มีไว้เพื่อ ทุกปีหารด้วย 4 ยกเว้นปีหารด้วย 100 ไม่เว้นด้วยหารด้วย 400
mbomb007

หวังว่าy+(y>>2)+(z=y/25>>2)+(z>>2)จะยังคงช่วยคุณประหยัด byte
Neil

@ Neil ขอบคุณ แต่ฉันพบวิธีที่ดีกว่า :-)
ETHproductions

นีซ; ฉันบันทึก 6 (y*5/4-(y/100)*3/4)ไบต์ในพอร์ตแบทช์ของฉันโดยใช้
Neil

11

JavaScript (Firefox 30-57), 67 65 64 63 61 ไบต์

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

บันทึก2 4 6 ไบต์ด้วย @ETHproductions บันทึกไบต์อื่นด้วยการแสดงเดือนในลำดับย้อนกลับ


ฉันคิดว่าคุณสามารถบันทึก 2 ไบต์โดย winging มันโดย.keys():y=>[for(_ of(m=0,Array(12)))if(new Date(y+400,++m).getDay()==2)m]
ETHproductions

@ ETHproductions ฉันสามารถบันทึก byte ต่อไปโดยกลับคำสั่ง!
Neil

ลำดับที่กลับเป็นเรื่องปกติ การจัดรูปแบบผลลัพธ์ไม่ใช่ส่วนที่น่าสนใจของความท้าทายนี้
AdmBorkBork

นโยบายของเราเกี่ยวกับความเข้าใจอาเรย์ตอนนี้พวกเขาถูกลบออกจากสเปคแล้วหรือยัง?
MayorMonty

คุณสามารถบันทึกอีก 2 ไบต์โดยข้ามArray(12)ไปพร้อมกัน: y=>[for(_ of(m=0,1e11+""))if(new Date(y+400,++m).getDay()==2)m]
ETHproductions

8

MySQL, 183 134 129 106 ไบต์

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

แทนที่2016ด้วยปีที่ต้องการ วิ่ง.

Rev. 2: ใช้help_topicsตารางในการติดตั้งเริ่มต้นแทนการสร้างตารางชั่วคราว

Rev.3: บุญธรรมaross's -เคล็ดลับ"-1"และสังเกตเห็นฉันยังสามารถละเว้นคำพูดสำหรับ
อย่างไรก็ตาม-1จำเป็นต้องมีใน MySQL: ฉันต้องการวันที่เต็ม

Rev.4: ข้อ จำกัดm BETWEEN 1 AND 12สามารถทำได้ในฐานะm>0 AND m<13(-6) แต่ไม่จำเป็นเลย - ค่าที่ไม่ถูกต้องจะถูกละเว้น คำเตือนจะถูกนับ แต่ไม่อยู่ในรายการ


คุณต้องการตาราง shema mysql จริงๆเหรอ? mariadb.com/kb/en/mariadb/mysqlhelp_topic-table
JörgHülsermann

@ JörgHülsermannฉันไม่เข้าใจประเด็นของคุณ
ติตัส

ควรจะFROM help_topicไม่mysql.ทำงาน ฉันไม่ได้ลอง
JörgHülsermann

@ JörgHülsermannเฉพาะในกรณีที่คุณเติมUSE mysql;ข้อมูลฐานข้อมูลที่ถูกต้องจะต้องเลือกอย่างใด
ติตัส


5

รุ่นที่160 152 ไบต์

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

คำตอบของพอร์ต @ETHproduction ด้วยตัวย่อเดือนสำหรับ197 189 ไบต์:

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

4

J, 48 34 33 ไบต์

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

ที่บันทึกไว้ 15 ไบต์ด้วยความช่วยเหลือจาก @ อดัม

ใช้ปฏิทินในตัวเพื่อสร้างอาร์เรย์ของสตริงที่แทนเดือนจากนั้นแยกวิเคราะห์แต่ละสตริงเพื่อพิจารณาว่าวันจันทร์สุดท้ายเป็นวันสุดท้ายของเดือนหรือไม่ มันส่งออกในแต่ละเดือนเป็นจำนวนเดือนของแต่ละ นั่นคือJan = 0, Feb = 1, ... Dec = 11,

ผลลัพธ์ของcalendarคือ

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

การใช้

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

คำอธิบาย

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

รอปฏิทินแสดงผลงาน ASCII จริงหรือไม่
เลมอนที่ถูกทำลายได้

@DestructibleWatermelon รูปแบบเอาต์พุตของcalendarอาร์เรย์เป็น 12 กล่องโดยแต่ละกล่องจะมีอักขระ 2 มิติ
ไมล์

ฉันไม่รู้ด้วยซ้ำว่าจะทำ "แต่ละคน" ใน J ได้อย่างไร แต่มันสั้นกว่านี้มาก: I.7=;#&.>".&.>,&.>_2{.&.>calendar 2016ถ้าคุณรวม "under-open" ทั้งหมดเข้าด้วยกันคุณควรจะทำให้มันสั้นได้
Adám

@ Adámขอบคุณมันใช้วิธีการที่ดีกว่า แต่ไม่ใช่คำกริยาใน J. ฉันคิดว่ามันจะยังคงช่วย
ไมล์

ความตั้งใจของฉันเป็นเพียงแรงบันดาลใจ ฉันรู้ว่ามันไม่ใช่คำกริยา
Adám

4

Mathematica, 62 57 ไบต์

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

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


4

Perl + cal, 46 ไบต์

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

ตัวอย่าง:

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

2







10


$

1
พูดอย่างเคร่งครัดนี่คือ perl + cal ไม่ใช่แค่ perl :-p ตัวอย่างเช่นเครื่อง Windows ของฉันมี Perl แต่สิ่งนี้จะไม่ทำงาน
philomory

พอใช้อัปเดตสิ่งนี้และความพยายามของฉัน
สตีฟ

4

Java 7186 182 172 ไบต์

ขอบคุณ kevin สำหรับการบันทึก 4 ไบต์
ขอบคุณ @cliffroot สำหรับการบันทึก 10 ไบต์

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

ungolfed

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

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

return a;
     }

รุ่นนี้ให้บริการโดย@cliffroot ( 168 ไบต์ )

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

ตัวอย่างผลลัพธ์

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

1
หลังจากที่ฉันเขียนคำตอบของฉันฉันรู้ว่าการคำนวณทุกอย่างด้วยตัวเองจะสั้นลง .. :) Btw คุณสามารถเล่นกอล์ฟn%4==0ไปที่n%4<1; n%400==0การn%400<1และการint c=...;int[]b=...,a=... int c=...,b[]=...,a[]=...
Kevin Cruijssen

1
bและaสามารถนิยามได้ในintส่วนเช่นนี้:int ... ,b[]=...,a[]=...
Olivier Grégoire

1
int[]f(int n){int x=--n*365+n/4+n/400-n++/100,k=0,b[]={1,(n%4<1&n%100>0)|n%400<1?-1:-2,1,0,1,0,1,1,0,1,0,1},a[]=new int[12];for(int i:b)a[k++]=(x+=i+30)%7==1?1:0;return a;}บันทึกไม่กี่ไบต์
หน้าผา

1
ยังสามารถเปลี่ยนbเป็นb[]={3,(n%4<1&n%100>0)|n%400<1?1:0,3,2,3,2,3,3,2,3,2,3}และi+30เพิ่มi+28เป็น 2 ไบต์ได้อีกด้วย
cliffroot

1
และอีก 3 ไบต์int[]f(int n){int b=13561787|((n%4<1&n%100>0)|n%400<1?1<<20:0),x=--n*365+n/4+n/400-n/100,a[]=new int[12],k=0;while(k<12)a[k++]=(x+=(b>>24-k*2&3)+28)%7==1?1:0;return a;}
หน้าผา

3

Python 2, 100 ไบต์

ฮึ. คณิตศาสตร์กับวันที่ไม่ง่ายอย่างที่ฉันต้องการ

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

ลองออนไลน์

ความยาวเท่ากัน:

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

ฉันไม่ได้ลอง Python ด้วยอันนี้ ความพยายามที่ดี
ElPedro

3

MATL , 21 ไบต์

12:"G@QhO6(YO9XO77=?@

เดือนจะแสดงเป็นตัวเลข

ลองออนไลน์! หรือตรวจสอบกรณีทดสอบทั้งหมด

คำอธิบาย

นี้ใช้ฟังก์ชั่นการแปลงวันที่ในตัว สำหรับปีนั้นจะทำการทดสอบว่าวันสุดท้ายของเดือนใดเป็นวันจันทร์

แทนที่จะระบุวันสุดท้ายของเดือนอย่างชัดเจนk(ซึ่งอาจเป็น 28, 29, 30 หรือ 31) เราระบุ0วันที่ -th ของเดือนk+1ซึ่งเทียบเท่าและไม่ขึ้นอยู่กับเดือนหรือปี

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


3

Excel, 537 ไบต์

เพราะ - คุณรู้จัก - Excel!

ใช้เวลาป้อนปีใน A1 ส่งคืนรายการเลขฐานสิบหกของเดือน 1 = มกราคม, C = ธันวาคม เนื่องจากในแต่ละเดือนเป็นตัวเลขหลักเดียวจึงไม่จำเป็นต้องมีตัวคั่น

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

ตัวอย่าง: A1 มี 2016. B1 มีสูตรข้างต้นและแสดงเป็น2A, หมายถึงกุมภาพันธ์และตุลาคม


3

PHP, 109 180 159ไบต์

for($z=$argv[1];$m++<12;)if(date(N,strtotime(sprintf("%04d-$m-",$z).cal_days_in_month(0,$m,$z)))<2)echo"$m,";
  • แสดงผลปีที่ระบุไม่ใช่ทั้งหมด (... อ่านคำถามเสมอ)
  • ประกาศถูกละทิ้ง (ขอบคุณติตัส)
  • เปลี่ยนwhileไปforเป็นก็ตอนนี้ปีเดียว (อีกครั้งขอบคุณติตัส)

เก่า 2

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

รองรับทุกปีจากจุดถึง 10,000 และกำจัดคำเตือน var ที่ไม่ได้กำหนดที่ฉันไม่รู้บนพีซีหนึ่งเครื่อง ใช่มันยาวกว่าเวอร์ชั่นเก่า แต่ก็แข็งแกร่งกว่า

เก่า 1

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

หากใช้งานบน Windows หรือระบบ 32 บิตจะมีข้อผิดพลาดที่น่ากลัว 2038 แต่ในระบบ 64 บิตของลินุกซ์ก็ไม่เป็นไร

ฉันพยายามใช้date("t"...ซึ่งหมายถึงวันสุดท้ายของเดือนที่ระบุ แต่ผลลัพธ์ไม่ตรงกับที่กล่าวถึงก่อนหน้าในหัวข้อนี้


2
-2: "$ z" ไม่จำเป็นต้องมีเครื่องหมายคำพูด -7: ละเว้นประกาศ (ไม่พิมพ์ด้วยการตั้งค่าเริ่มต้น: ห้ามเริ่ม$z, ไม่มีเครื่องหมายอัญประกาศN) -1: forแทนwhile -43 : รับอินพุตตามที่ร้องขอแทนที่จะวนซ้ำตลอดหลายปีที่ผ่านมา -3: joinแทนimplode-16: เอาท์พุทโดยตรง: for($z=$argv[1];$m++<12;)if(date(N,strtotime(sprintf("%04d-$m-",$z).cal_days_in_month(0,$m,$z)))<2)echo"$m,";+9 ถ้าคุณยืนยันว่าไม่มีคอมม่าต่อท้าย:echo$o=$o?",$m":$m;
ติตัส

อ่าอ่านคำถามผิด! คิดว่าเป็นเวลาหลายปี .. โอ๊ะโอ: B ขอบคุณสำหรับคำแนะนำอื่น ๆ เช่นกันจะได้รับในพวกเขา
CT14.IT

3

PHP, 92 ไบต์

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

ตรวจสอบ 12 ครั้ง 1 เดือนหลังจากวันแรกของปีเป็นวันอังคาร หากเป็นเช่นนั้นก็คือวันก่อนวันสุดท้ายของเดือนคือวันจันทร์


คุณสามารถใช้ echo แทนการพิมพ์และบันทึก 1
Octopus

1
@ Octopus ไม่ได้อยู่ในผู้ประกอบการที่สาม
JörgHülsermann

3

C, 214 ไบต์

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

รวบรวม

gcc -std=c99 -o foo foo.c

Ungolfed

ด้วยเครดิตให้กับผู้เชี่ยวชาญด้านที่เกี่ยวข้อง

Michael KeithและTom Craverสำหรับโปรแกรม C เพื่อค้นหาวันในสัปดาห์ที่กำหนดโปรแกรมที่จะหาวันนับจากวันที่สัปดาห์ที่กำหนด

Collin Biedenkappสำหรับคำถามและคำตอบ: ฉันจะทราบได้อย่างไรว่าวันสุดท้ายของเดือนเป็นอย่างไร

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

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

1
จะเป็นอย่างไรถ้าคุณพลิกifไปอีกทิศทางหนึ่งเพื่อelseกลับมา31และดังนั้นคุณสามารถกำจัด==ห่วงโซ่ขนาดใหญ่ได้?
AdmBorkBork

1
จะดีกว่าถ้า (x == 1) {z ส่วน} อื่นถ้า (x == 3 || x == 5 || x == 8 || x == 10) ส่งคืน 30 คืน 31
RosLuP

1
แล้ว: return x == 1? (z% 4 == 0? (z% 100 == 0? (z% 400 == 0? 29: 28): 29): 28) :( x == 3 | | x == 5 || x == 8 || x == 10? 30: 31)
RosLuP

TimmyD + RosLuP: ขอบคุณสำหรับคะแนน return) บันทึกได้ 100 ไบต์
สตีฟ

1
เป็นไปได้ที่จะลดลงเรื่อย ๆ จนกว่าจะถึงนี้: u (y, m) {return m-1? 30 + ((2773 >> m) & 1): 28+ (y% 4 == 0 && y% 100 || y% 400 == 0);} โดยที่ y คือปีและ m เดือน
RosLuP

3

C, 119 ไบต์

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

นี่ใช้ตารางที่มีออฟเซ็ตของวันธรรมดาของวันสุดท้ายของทุกเดือนสำหรับปีอธิกสุรทินซึ่งเข้ารหัสด้วยคำ 32- บิตที่เซ็นชื่อโดยใช้ฐาน 7 หากไม่ใช่ปีอธิกสุรทินเราบวก 1 เข้ากับออฟเซ็ตของเดือนมกราคม (อย่างที่คุณเห็นy&3||y%25<1&&y&15จะถูกใช้เพื่อตรวจสอบเป็นเวลาหลายปีโดยไม่มีวันกระโดด) จากนั้นเราก็วนซ้ำทุกเดือนและตรวจสอบว่าวันสุดท้ายของวันนั้นเป็นวันจันทร์หรือไม่ ค่อนข้างง่ายจริง ๆ ไม่มีแฮ็คหรือลูกเล่นที่น่าเกลียด นี่มันเป็นสิ่งที่ไม่ดีเล็กน้อย:

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

ฉันอาจทบทวนสิ่งนี้เพื่อเขียนใหม่เป็นฟังก์ชันเพื่อบันทึกอักขระบางตัว printfยังจะขึ้นเป็นพื้นที่เล็ก ๆ น้อย ๆ มากเกินไป ...


printf ("% d,", m) จะพิมพ์บางอย่างเป็น 1 หรือ 2, 3 ดังนั้นจึงมีหนึ่งเสมอ ',' เพิ่มเติม ... ฉันชอบใช้ช่องว่างเท่านั้น
RosLuP

ที่จริงแล้วฉันชอบช่องว่างในผลลัพธ์ด้วย แต่ฉันมักจะเขียนวิธีแก้ไข C ที่มี golfed เพื่อที่พวกเขาไม่ต้องการช่องว่างใด ๆ ดังนั้นฉันจึงสามารถทำช่องว่างทั้งหมดจากเวอร์ชันครึ่งกอล์ฟเมื่อฉันต้องการตรวจสอบจำนวนตัวละครของฉัน .
Fors

3

PHP, 96 95 76 71 69 64 61 ไบต์

หมายเหตุ: หมายเลขปีจะต้องมีเบาะ 4 0070ตัวอักษรเช่น

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

ทำงานแบบนี้:

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

คำอธิบาย

ทำซ้ำตั้งแต่ -1 ถึง -12 สร้างวันที่ใช้ mktime วัน0(วันสุดท้ายของเดือนก่อนหน้า) 2..13และเดือน จัดรูปแบบวันที่เป็นหมายเลขวันและถ้าผลลัพธ์คือ 1 ให้พิมพ์หมายเลขปัจจุบัน ใช้เครื่องหมายลบ-เป็นตัวคั่น

มิลเลนเนียมบั๊กโต้อีกครั้ง!

ทราบว่ามีรุ่นนี้ช่วงถูกตีความว่าเป็น0..100 1970..2069นี่ไม่ใช่ปัญหาสำหรับช่วง0..69เนื่องจากสัปดาห์มีรูปแบบที่ซ้ำทุก ๆ 400 ปี (146097 วันหรือ 20871 สัปดาห์) แต่สำหรับช่วง70..991900 จะถูกเพิ่มไปยังหมายเลขปีซึ่งไม่เท่ากับ 400 ปัญหานั้นเพียงแค่เป็นเวลา 30 ปีในช่วง 10k วิธีที่ง่ายที่สุดคือการเพิ่ม 400 ไปยังหมายเลขปีเพื่อป้องกันการตีความ 2 หลัก ( +4 ไบต์ ):

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

การปรับแต่ง

  • บันทึกเป็นไบต์โดยใช้!~-$iเพื่อเปรียบเทียบ$iกับ1( -1เป็นลบเลขฐานสองคือ0, ลบด้วยเหตุผลคือtrueทุกหมายเลขอื่น ๆ คือfalse ) ดังนั้นวงเล็บไม่จำเป็น
  • บันทึก 19 ไบต์โดยใช้ last day ofYYYY-mสัญกรณ์เพื่อสร้างวันที่
  • บันทึก 5 ไบต์โดยใช้dateและstrtotimeแทนที่จะเป็นdate_create
  • บันทึก 2 ไบต์โดยนับจากจำนวนลบโดยใช้เครื่องหมายลบเป็นตัวคั่นเอาต์พุต (ไม่มีเลขเดือนลบ) และเช่นเดียวกับ delim ใน YYYY-mส่วนของวันที่
  • ที่บันทึกไว้ 5 ไบต์โดยใช้แทนmktime strtotimeเปลี่ยนกลับเป็นใช้วัน0( mktimeรองรับเดือน 13 ด้วยดังนั้น0-13==31-12 )
  • บันทึก 3 ไบต์โดยใช้-Rเพื่อให้$argnพร้อมใช้งาน

mktimeลบความจำเป็นที่จะผัดปีไม่ได้หรือไม่
ติตัส

@Titus, คมชัด ทีนี้ฉันก็หาว่าmktimeมันตอบโต้ได้ง่ายเพราะข้อโต้แย้งนั้นถูกใช้เป็นINTs นั่นหมายความว่าคุณไม่สามารถแผ่นปี ... ดังนั้นทุกอย่างในช่วงที่ถูกตีความว่าเป็น0..100 1970..2070นั่นไม่ใช่ปัญหาสำหรับช่วง0..70เนื่องจาก 400 ปีมีจำนวนสัปดาห์ที่แน่นอน (ดังนั้นปฏิทินจะทำซ้ำรูปแบบทุก ๆ 400 ปี) แต่70..99เพิ่ม 1900 (ไม่ใช่ทวีคูณของ 400!) ดังนั้นเวอร์ชั่นใหม่ มีข้อบกพร่อง
aross

ทางออกเดียวที่ฉันเห็นในตอนนี้คือ$argv[1]+400... เว้นแต่ว่า Julian และ Gregorian จะแตกต่างกันไป
ติตัส

@Titus, ใช่ กฎบอกว่าใช้ Gregorian cal
aross

3

Excel, 428 97 96 ไบต์

ป้อนข้อมูลใน A1 เอาต์พุตเลขฐานสิบหกที่ไม่ได้แยกออกจากกัน (มกราคม = 0, ธันวาคม = B)

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

เพิ่ม 10 ไบต์ ("+2000") เพื่อให้สามารถจัดการกับวันที่ก่อนปี 1990

ที่บันทึกไว้ 11 ไบต์ขอบคุณที่ @ วิศวกร Toast


ความพยายามครั้งแรก (428 bytes) ยืมหนักจาก @ ADAMวิธีการแก้ปัญหาของ

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

สิ่งนี้ใช้งานได้อย่างไรในปีก่อนหน้า 1900 กรณีทดสอบ297 -> Mayกลับมา6พร้อมกับสูตรนี้ มันควรจะเป็น 4 หรือไม่? 1776ให้7Aแทนแค่8เดือนกันยายน
Engineer Toast

ถ้าคุณทำให้มันใช้งานได้คุณอาจใช้Date(A1,3,0)แทนEOMONTH(DATE(A1,2,1),0)
Toast วิศวกร

2

Bash + cal 58 ไบต์

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

1 - งานสำหรับ BSD cal(เช่น OSX) แต่นาฬิกาสำหรับช่องว่างต่อท้ายใน calGNU
Digital Trauma

2

Python 2, 94 ไบต์

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

repl.it

ฟังก์ชั่นที่ไม่มีชื่อจะใช้เวลาเป็นปีจำนวนเต็ม outputs [1-12]รายการหมายเลขเดือนที่

ฉันยังพยายามเอาชนะจำนวนไบต์ด้วยเลขคณิตไม่ประสบความสำเร็จ (110 ไบต์) :

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

ฟังก์ชันที่ไม่มีชื่อซึ่งจะส่งคืนรายการค่าบูลีนที่แสดงว่าเดือน [ม.ค. - ธ.ค. ] สิ้นสุดในวันจันทร์


2

Java 7, 200 249 ไบต์

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

ใน Java GregorianCalendarเป็นการผสมผสานระหว่างปฏิทินเกรโกเรียนและจูเลียน ด้วยเหตุนี้ปี1ทำให้ผลลัพธ์ไม่ถูกต้อง การเปลี่ยนCalendar c=Calendar.getInstance();เป็นการGregorianCalendar c=new GregorianCalendar();c.setGregorianChange(new Date(1L<<63));แก้ไขปัญหานี้โดยบังคับให้ใช้ปฏิทินเกรกอเรียนเท่านั้น ขอบคุณ@JonSkeetบน stackoverflow.com ที่อธิบายสิ่งนี้กับฉัน

Ungolfed & รหัสการทดสอบ:

ลองที่นี่

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

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

เอาท์พุท:

4 12
5 
9 
1 7 
2 10 
1 2 10 

2

C # 6 C #, 171 167 135 ไบต์

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

-32 ไบต์ขอบคุณ Shebang

พิมพ์เดือนเป็นตัวเลข มีการคั่นด้วยช่องว่าง มีพื้นที่ต่อท้าย ตอนนี้คำตอบนี้ใช้ได้กับ C # เวอร์ชันก่อนหน้าด้วย


เก่า 167 ไบต์

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

-4 ไบต์ขอบคุณ TimmyD

เดือนเอาท์พุทเป็นตัวเลขในสตริงส่งคืนคั่นด้วยเครื่องหมายจุลภาค

Ungolfed

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

@ TimmyD ใช่ แต่ต้องการการส่งที่ชัดเจน อัปเดตคำตอบแล้ว
เชื่อมโยง

LINQ คือความสนุก แต่นี้เป็น 126 ไบต์: void q(int y){for(int m=1;m<13;m++){if((int)new DateTime(y,m,DateTime.DaysInMonth(y,m)).DayOfWeek==1){Console.WriteLine(m);}}};) นอกจากนี้ก็จะสั้นลงในการโยนDayOfWeekไปintกว่ามันจะโยนintไปDayOfWeek
Kade

@Shebang ขอบคุณ ฉันไม่ควรเล่นกอล์ฟใน linq แบบบรรทัดเดียว --- มีเพียง Jon Skeet เท่านั้นที่ทำได้ ดูว่าฉันมีเวลาอัปเดตพรุ่งนี้หรือไม่ เหนื่อยแล้ว
ลิงก์ Ng

คุณสามารถแปลงให้เป็นแบบAction<int>ไบต์เพื่อบันทึก
TheLethalCoder

2

Ruby, 54 + 6 = 60 ไบต์

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

6 ไบต์สำหรับ-rdateบนบรรทัดคำสั่งเพื่อรับคลาส Date จากไลบรารีมาตรฐาน

คำอธิบาย: ตรงไปตรงมาขอบคุณDateชั้นดีของ Ruby stdlib ไม่เพียง แต่จะมีวิธีการเช่นmonday?, tuesday?ฯลฯ , ตัวสร้างจะใช้จำนวนลบสำหรับเขตข้อมูลใด ๆ ในปีที่ผ่านมาเพื่อหมายถึง 'นับเขตข้อมูลนี้ย้อนหลังจากจุดสิ้นสุดของช่วงเวลาที่แสดงโดยเขตข้อมูลก่อนหน้า $*เป็นการย่อARGVดังนั้น$*[0]เป็นวิธีที่รวดเร็วในการรับอาร์กิวเมนต์บรรทัดคำสั่งแรก


2

PHP, 84 ไบต์

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

กอล์ฟรหัสแรกของฉัน นี่เป็น PHP ที่สั้นที่สุดจนถึงตอนนี้

แก้ไข: ดูเหมือนจะไม่ทำงานสำหรับปี 1 ฉันจะต้องคิดออกว่าทำไม แต่ตอนนี้ฉันต้องไป


1
ฉันว่า "ยินดีต้อนรับสู่ PPCG!" แต่คุณได้ลงทะเบียนที่นี่มานานกว่าที่ฉันมี! : D กอล์ฟที่ดีก่อน
AdmBorkBork

ข้อผิดพลาดของคุณคือคุณสร้าง 1-13-1 และ 1-14-1 สำหรับปี 1 <13 ก็เพียงพอแล้ว หากคุณแก้ปัญหานี้คุณสามารถลบวงเล็บ unnessary ในขณะนี้และคิดเกี่ยวกับการใช้ผู้ประกอบการที่สาม
JörgHülsermann

สิ่งนี้จะแก้ไขปัญหาของคุณfor(;$m++<12;)strftime("%w",strtotime($argv[1]+($m/12^0)."-".($m%12+1)."-1"))!=2?:print"$m ";
JörgHülsermann

2

R, 106 99 95 83 78 77 74 ไบต์

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

ลำดับของวันสุดท้ายของแต่ละเดือนกำหนดโดยseq(as.Date(paste0(x,-2,-1)),,'m',12)-1:

  • paste0coerces -2 และ -1 ถึงอักขระ ถ้าxเป็น 2016 เช่นpaste0(x,-2,-1)ให้"2016-2-1"ซึ่งจะถูกแปลงไปแล้ววันที่ 1 กุมภาพันธ์ 2016 as.Dateโดย

  • seqนำไปใช้กับ POSIXct หรือวัตถุวันที่seq(from, to , by, length.out): toไม่ได้ให้ที่นี่จะได้byรับตามที่ได้รับการ'm'จับคู่เพื่อ'month'ขอบคุณการจับคู่บางส่วนและlength.outเป็นของหลักสูตร 12

  • ลำดับผลลัพธ์เป็นวันแรกของ 12 เดือนเริ่มต้นด้วยเดือนกุมภาพันธ์ของปีที่มีปัญหา -1ให้เราเป็นวันสุดท้ายของ 12 เดือนเริ่มต้นด้วยเดือนมกราคมของปีที่มีปัญหา

กรณีทดสอบ:

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

รุ่นเก่าที่ 95 ไบต์แสดงผลชื่อเดือนแทนที่จะเป็นเพียงตัวเลข:

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

คำตอบนี้ยอดเยี่ยมมาก ฉันไม่รู้ว่าseqมีวิธีการDate--object และวิธีนี้แก้ปัญหาการas.Dateไม่จัดการหลายปีข้างต้น10000ในคำตอบที่ถูกลบของฉัน
Billywob

@Billywob ใช่seq.Dateและseq.POSIXtเป็นที่น่าประทับใจมาก: พวกเขายังสามารถประมวลผลคำสั่งเช่นหรือseq(time1, time2, by="10 min") seq(date1, date2, by="quarter")มีประโยชน์มากเมื่อพล็อตอนุกรมเวลา
plannapus

2

Japt, 24 ไบต์

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

ทดสอบออนไลน์! ส่งออกอาร์เรย์ของตัวเลขโดยfalseแทนที่เดือนที่ไม่สิ้นสุดในวันจันทร์

มีข้อผิดพลาดในล่ามที่ไม่อนุญาตให้ผมใช้เป็นในร่างกายของฟังก์ชั่นÐ £หลังจากแก้ไขข้อบกพร่องและการเพิ่มคุณสมบัติอื่นแล้วนี่คือ 18 ไบต์ในการกระทำปัจจุบัน:

Do1@Ð400+UX e ¥2©X

1

Java, 143 129 ไบต์

สิ่งนี้ใช้ API เวลาใหม่ของ Java 8

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

เอาท์พุต

โปรดทราบว่าแต่ละบรรทัดมีพื้นที่พิเศษในตอนท้าย

4 12 
5 
9 
1 7 
2 10 
1 2 10 

Ungolfed และการทดสอบ

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

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

โกน

  1. 143 ถึง 129 ไบต์: ใช้DayOfWeek::ordinalเพื่อเปรียบเทียบกับค่าคงที่ตัวเลขแทนค่าคงที่ enum
    ขอบคุณ @ TimmyD สำหรับความคิดทั่วไปหากไม่ใช่วิธีการแก้ปัญหาที่แน่นอน! ;-)

@ TimmyD เป็นเรื่องน่าเศร้า มันมีgetValue()วิธี แต่ที่จะบันทึกไม่กี่ไบต์
Celos

@Celos ordinal()บันทึกอีก 1 ไบต์เปรียบเทียบกับgetValue()แม้ว่าจะไม่แนะนำให้ใช้ก็ตาม
Olivier Grégoire

ใช่ความคิดที่ดี ฉันโพสต์ความคิดเห็นของฉันโดยไม่ต้องรีเฟรชก่อนดังนั้นฉันจึงไม่เห็นคำตอบและแก้ไขของคุณ
Celos

1

GNU awk, 80 ไบต์

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

ตัวอย่าง

$ gawk '{for(;m<13;a=mktime($0" "++m" 1 9 0 0")){if(strftime("%w",a-8e4)~1){print m-1}}}' <<<2016
2
10
$
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.