วันศุกร์ที่ 13 ของปีที่แล้ว


28

ความท้าทายของคุณคือการเขียนโปรแกรมที่ให้ผลเป็นจำนวนปี "วันศุกร์ที่ 13" ในปีนั้น

กฎและรายละเอียด:

  • คุณสามารถป้อนข้อมูลผ่านSTDINหรือเป็นอาร์กิวเมนต์ที่ส่งผ่านไปยังโปรแกรมของคุณ
  • STDOUTคุณควรส่งออกผลให้
  • คุณอาจจะสมมติว่าการป้อนข้อมูลจะเป็นปีที่ถูกต้องและไม่ได้ทำการปรับปรุงปฏิทินเกรโกเรียนล่วงหน้า (พฤติกรรมที่ไม่ได้กำหนดจะได้รับอนุญาตในกรณีเหล่านี้)
  • อนุญาตให้ใช้ไลบรารีปฏิทิน / วันที่

นี่คือดังนั้นรหัสที่สั้นที่สุด (เป็นไบต์) ชนะ

(ลิงค์ท้าทายที่เกี่ยวข้อง)


7
ช่วงที่จำเป็นสำหรับการป้อนข้อมูลคืออะไร? ถ้ามันไปมากก่อนปี 1800 ควรมีการตั้งสมมติฐานอะไรเกี่ยวกับการเปลี่ยนแปลงจากจูเลียนไปยังปฏิทินเกรโกเรียน
Peter Taylor

@ PeterTaylor ฉันไม่ได้คิดเกี่ยวกับมัน หากวันที่ pre-date เกรกอเรียนคุณสามารถมีพฤติกรรมที่ไม่ได้กำหนด
Cruncher

1
ประเทศแรก ๆ ที่ใช้ปฏิทินเกรกอเรียนทำเช่นนั้นในเดือนตุลาคม ค.ศ. 1582 ตามวัวของเกรกอรี่ ประเทศที่จะนำปฏิทินใหม่มาใช้ล่าช้าไม่เปลี่ยนไปจนถึงศตวรรษที่ 20 เช่นกรีซเปิดตัวในวันที่ 1 มีนาคม 1923
Jeppe Stig Nielsen

@JeppeStigNielsen ฉันไม่รู้เรื่องปฏิทินมากนัก ไม่ว่าพวกเขาจะนำมาใช้หรือไม่ไม่เปลี่ยนแปลงสิ่งที่วันที่เกรกอเรียน ห้องสมุดควรสามารถคำนวณวันที่ได้จากวิธีที่ฉันเข้าใจ
Cruncher

3
ฉันกำลังเป็นที่นิยมฉันเดา ห้องสมุดจำนวนมากที่เขียนโดยโปรแกรมเมอร์ของแองโกล - อเมริกันใช้กันยายน 1752 เป็นช่วงเวลาที่ "ถูกต้อง" ในการเปลี่ยนปฏิทิน นี่คือเมื่อจักรวรรดิอังกฤษเปลี่ยนไป ปฏิทินใหม่ถูกเก็บไว้เมื่อก่อตั้งประเทศสหรัฐอเมริกาแน่นอน (เนื่องจากความอยากรู้อยากเห็นซอฟต์แวร์ SQL บางตัวมีปี 1753 น้อยที่สุดเนื่องจากไม่ต้องการจัดการกับปัญหาเดือนกันยายน ค.ศ. 1752) อย่างไรก็ตามการใช้งานกันยายน 1752 นั้นมีความเป็นไปได้สูง คุณถูกวันเกรกอเรียนเหมือนกันไม่ว่าจะถูกใช้ในอดีตหรือไม่ นั่นคือปฏิทินเกรโกเรียนที่เรียกว่าproleptic
Jeppe Stig Nielsen

คำตอบ:


3

APL (Dyalog APL) ที่มีcal จากdfns , 29 ไบต์

+/{13∊⍎,⍉3↑¯5↑⍉2cal⍵}¨⎕,¨⍳12

ลองออนไลน์!

⍳ 12 จำนวนเต็มหนึ่งถึงสิบสอง

⎕ ,¨ รับข้อมูลเข้าเป็นตัวเลขและเสริมแต่ละหมายเลขสิบสอง

{...  ในแต่ละคู่ใช้ฟังก์ชัน ...

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

2 ↓ ปล่อยสองแถว (คำบรรยายภาพและวัน)

 ไขว้ (เพื่อให้เราสามารถที่อยู่คอลัมน์แทนแถว)

¯5 ↑ ใช้ตัวเลขห้าตัวสุดท้าย (สองหลักสำหรับแต่ละวันศุกร์และวันเสาร์และอีกหนึ่งช่องว่าง)

3 ↑ ใช้สองคนแรก (ตัวเลขสองหลักสำหรับวันศุกร์บวกด้วยช่องว่าง)

 ไขว้ (ดังนั้นเราจึงได้อ่านคำสั่ง)

, คลี่คลาย

 รันเป็นนิพจน์ APL (ให้รายการวันที่ของวันศุกร์)

13 ∊ สิบสามเป็นสมาชิกของรายการนั้นหรือไม่?

+/ รวม 12 Booleans


การใช้อัลกอริทึมของ @ Wrzlprmftเราสามารถทำได้โดยไม่ต้องมีไลบรารีสำหรับ 53 ไบต์:

'21232211321211'⊃⍨14|2 3 ¯1+.×⊢,0≠.=400 100 4∘.|-∘0 1

-∘0 1 ลบศูนย์และหนึ่ง

400 100 4 ∘.| ตารางเศษที่เหลือสำหรับสองปี (ข้าม) หารด้วยตัวเลขเหล่านี้ (ลง)

0 ≠.= "ผลิตภัณฑ์" ภายในด้วย 0 แต่ใช้≠และ = แทน +. ×

⊢ , เพิ่มปีอาร์กิวเมนต์ที่ไม่ได้แก้ไข

2 3 ¯1 +.× ผลิตภัณฑ์ภายในด้วยตัวเลขเหล่านี้

14 | ส่วนที่เหลือเมื่อหารด้วยสิบสี่

'21232211321211' ⌷⍨ จัดทำดัชนีลงในสายอักขระนี้


มันคือ 29 ตัวอักษร แต่มีมากกว่า 1 ไบต์ใช่ไหม
Cruncher

@Cruncher ฉันได้เพิ่มลิงก์คำอธิบายในส่วนหัว หากคุณเปิดลิงก์ TIO คุณจะเห็นว่ามีข้อความระบุว่า "29 ตัวอักษร 29 ตัว (SBCS)" ทางด้านขวาคือชุดอักขระไบต์เดียว
Adám

ฉันเดาว่านี่คือผู้ชนะคนใหม่ในตอนนี้การฝึกแบบมาตรฐานใน SE นี้เพื่อเปลี่ยนคำตอบที่ได้รับการยอมรับมานานแล้วหลังจากคำถามนี้หรือไม่?
Cruncher

@Cruncher ใช่ และมีป้ายที่จะต้องได้รับการยอมรับหลังจาก OP
Adám

12

Mathematica 49 46 45 44 42

ในฐานะที่เป็นฟังก์ชั่นที่บริสุทธิ์ : 42 ตัวอักษร

DayName@{#,m,6}~Table~{m,12}~Count~Friday&

ตัวอย่าง

DayName@{#,m,6}~Table~{m,12}~Count~Friday&[2013]

2


ในฐานะที่เป็นฟังก์ชั่นที่มีชื่อ : 44 ตัวอักษร

f=DayName@{#,m,6}~Table~{m,12}~Count~Friday&

ตัวอย่าง

f[1776]
f[2012]
f[2013]
f[2014]

2
3
2
1


ตัวละครหนึ่งตัวสั้นลง:f=DayName@{#,m,6}~Table~{m,12}~Count~Friday&
Mr.Wizard

@ Mr.Wizard ใช่ มันทำให้ฉันประหลาดใจที่ Mathematica สามารถแยกหลายกรณีของสัญกรณ์มัด
DavidC

เดวิดมันทำให้ฉันประหลาดใจมากที่คุณไม่ได้เห็นการใช้ความทรงจำนี้ของฉัน : ^) (ตัวอย่าง: (1) , (2) )
Mr.Wizard

8

ทับทิม, 49 48 47 46

f=->m{(1..12).count{|i|Time.gm(m,i,6).friday?}}

แก้ไข: โกนตัวละครโดยย้อนกลับไปหนึ่งสัปดาห์ขอบคุณแจนและอีกตัวโดยเปลี่ยนจาก Time.new เป็น Time.gm

แก้ไข: ด้วยค่าใช้จ่ายในการทำให้งงมากขึ้นฉันสามารถไปถึง 46 ด้วย

f=->m{(1..12).count{|i|Time.gm(m,i,8).wday<1}}

5
ประหยัดแบบ Char ถ้าคุณนับจำนวนวันศุกร์ที่ 6
John Dvorak


ทำไม 6 ฉันไม่ได้รับมัน
NARKOZ

3
หากวันที่ 6 เป็นวันศุกร์วันที่ 13 จะเป็นวันศุกร์
TwiNight

หากวันที่ 8 คือวันอาทิตย์แสดงว่าวันที่ 1 เป็นวันที่เช่นกันและคุณสามารถใช้งานTime.gm(m,i).wday<1ได้ นอกจากนี้ฉันไม่รู้ว่าทำไมคุณถึงตั้งชื่อฟังก์ชั่น
Lee W

8

Powershell, 68 63 58 52 50

ขอบคุณ Iszi สำหรับคำแนะนำ

$n=$args;(1..12|?{!+(date $n-$_).DayOfWeek}).Count

ใช้ความจริงที่ว่าถ้าวันที่ 1 ของเดือนเป็นวันอาทิตย์ที่ 13 จะเป็นวันศุกร์

ฉันยังลอง:

(1..12|?{!+(date $args-$_).DayOfWeek}).Count

แต่มันไม่เหมือนกัน$argsในบล็อกสคริปต์


1
ฉันชอบความคิดที่จะใช้วันแรกของเดือน
Cruncher

เคล็ดลับที่ดีที่นั่น แม้ว่า @ ไม่จำเป็น แต่
Iszi

อีกสิ่งหนึ่งแม้ว่าฉันจะมีความผิดในสคริปต์จำนวนมากของฉัน ความท้าทายไม่ได้ระบุว่าอินพุตนั้นมาจากการโต้แย้ง แทนที่$nด้วย$argsในวงและคุณสามารถทำได้โดยไม่ต้อง$n=read-host;ทั้งหมด บันทึก 8. ลบ @ ตามที่กล่าวไว้ข้างต้นและคุณลดเหลือ 54
Iszi

การแก้ไข: ลดลงเหลือ 52!
Iszi

พยายามคิดให้ออกว่าทำไมสคริปต์ตัวที่สองของคุณไม่ทำงานและฉันก็แพ้ สิ่งที่น่าสนใจก็คือว่าผมสามารถเปลี่ยนออก$argsสำหรับ$inputดังนั้นการให้อาหารในปีจากท่อและสคริปต์ที่จะทำงาน แต่มันก็ outputs 3.
Iszi

5

R 76 72 57

sum(format(as.Date(paste(scan(),1:12,1,sep="-")),"%w")<1)

สามารถทำให้ค่านี้ลดลง 4 ได้อย่างง่ายดายโดยแทนที่ของคุณ"%a %d")=="Fri 13"ด้วยการ"%w%d)=="513")ใช้ dow เป็นตัวเลขและลบช่องว่าง
chmullig

ชื่นชมมาก!
flodel

+1 แม้ว่าการทำสิ่งseqเดียวในเดือนนี้จะสั้นกว่าจริง ๆ ! sum(format(as.Date(paste(scan(),1:12,13,sep="-")),"%w%d")=="513")มีเพียง 65 ตัวอักษร!
plannapus

ว้าวฉันจะไม่เดาเลยว่า<จะบีบบังคับอักขระให้เป็นจำนวนเต็ม เคล็ดลับดี!
plannapus

@plannapus มันค่อนข้างบ่อย เนื่องจากรหัสตัวอักษรเป็นตัวเลขทั้งหมด แม้กระทั่งจาวาก็สามารถเปรียบเทียบ int และ char
Cruncher

5

Python2.7 90 86

from datetime import*
s=c=0
exec's+=1;c+=date(%d,s,9).weekday()<1;'%input()*12
print c

วันจันทร์ที่ 9 อาจไม่มีวงแหวนเดียวกัน แต่ให้ผลเช่นกัน

แก้ไข: หนึ่งปีครึ่งที่จะสังเกตเห็นว่าdateสั้นกว่าdatetime:)


ทางออกที่ดีจริงๆ!
leancz

2
คุณสามารถประหยัดถ่านโดยทำfrom datetime import*
user80551

ดี! ฉันจบลงด้วยบางสิ่งที่เหมือนกันอย่างมีประสิทธิภาพ แต่หลีกเลี่ยง exec: f=lambda y:sum([date(y,m,13).weekday()==4 for m in range(1,13)]).... โซลูชันขนาดเดียวกันกับการนำเข้า (86 ไบต์)
iwaseatenbyagrue

5

ไม่ใช้ไลบรารีหรือฟังก์ชั่นวันที่ในตัว:

Golfscript - 51

~..({4/.25/.4/--@}2*2*\3*+-
14%' [3/=RI[)a%:*.'\=5%

' [3/=RI[)a%:*.' อาจจะเป็นเช่นกัน 'feefefgeeffgfe'

Python - 82 79

เป็นหลักอัลกอริทึมเดียวกัน

l=lambda y:y/4-y/100+y/400
i=input()
print"21232211321211"[(2*i+3*l(i)-l(i-1))%14]

ด้วยการใช้เคล็ดลับนี้สามารถลงไปที่:

l=lambda y:y/4-y/100+y/400
i=input()
print 94067430>>(4*i+6*l(i)-2*l(i-1))%28&3

การใช้ประโยชน์จากความจริงที่ว่าปฏิทินฉลาดมีเพียง 14 ปีที่แตกต่างกันซึ่งสามารถแยกแยะได้ในวันสุดท้ายของพวกเขาและไม่ว่าพวกเขาจะกระโจน lคำนวณจำนวนปีอธิกสุรทินจนถึงอาร์กิวเมนต์ (ถ้าปฏิทินเกรโกเรียนขยายไปจนถึงปี 1) (2*i+3*l(i)-l(i-1))%14สั้นสำหรับl(i)-l(i-1)+(i+l(i))%7*2ที่l(i)-l(i-1)จะบอกเราว่าการโต้เถียงเป็นปีอธิกสุรทินและi+l(i)สรุปการเปลี่ยนแปลงของวันสุดท้ายหรือไม่ (หนึ่งในปีปกติสองปีในปีอธิกสุรทิน)


เนื่องจากนี่เป็นกอล์ฟ golfscript แรกของฉันฉันจะขอบคุณคำแนะนำใด ๆ เกี่ยวกับการตีกอล์ฟต่อไป
Wrzlprmft

ฉันกำลังคิดเกี่ยวกับวิธีแก้ปัญหาดังกล่าวโดยใช้ความจริงที่ว่ามีเพียง 14 ปีที่ไม่ซ้ำกันจริง ๆ แต่ไม่แน่ใจว่าภาษาที่ดีที่สุดเพื่อให้สามารถแข่งขันได้ ฉันคิดว่านี่เป็นคำตอบสั้น ๆ ที่ไม่มีห้องสมุด หากปีอธิกสุรทินมีความสม่ำเสมอทุก 4 ปีคุณอาจชนะด้วยสิ่งนี้
Cruncher

4

C 301+ 287

main(int x,char**v){char p[400],*a[]={"abbababbacaacbac","bacabbb","baabbaca","abbb","aabbacaac","abbbbcaac","abbbbaabb"},*b="adcadcadcaebcadcadcafbcadcadcagbcadcadcadc";int c=0,i,y=atoi(v[0]);for(i=0;i<42;i++)strcpy(&p[c],a[b[i]-'a']),c+=strlen(a[b[i]-'a']);printf("%d",p[y%400]-'`');}

ไม่ใช่คำตอบที่สั้นที่สุด แต่ไม่ต้องใช้ห้องสมุด


เฮ้คุณยินดีที่จะให้คำตอบที่ไม่ถูกต้องกับคำอธิบายหรือไม่? ฉันสนใจในสิ่งที่คุณทำอย่างแน่นอน
Cruncher

1
@Cruncher เป็นตารางการค้นหาบนพื้นฐานที่ว่าปฏิทินเกรโกเรียนติดตามรอบ 400 ปี
Peter Taylor

1
อย่างชัดเจนมากขึ้น (และอีกต่อไป), C static char GetNumberOfFriday13s(int year) { const string perpetualCalendar = "1221212213113213122221122131122121221311321312222112213112212122131132131222211221311221212213113213112213113213122221122131122121221311321312222112213112212122131132131222211221311221212213113213122213113213122221122131122121221311321312222112213112212122131132131222211221311221212213113213122221122213122221122131122121221311321312222112213112212122131132131222211221311221212213113213122221122131"; return perpetualCalendar[year % 400];#: จะไม่ทำงานเป็นปีที่ไม่ดี
Jeppe Stig Nielsen

น่ารัก! ในฐานะที่เป็นข้อผิดพลาดเล็ก ๆ ที่ควรจะเป็นv[0] v[1]คุณยังสามารถตีกอล์ฟได้เล็กน้อย พิจารณาใช้strcatจัดเก็บอักขระเพื่อพิมพ์โดยตรงa[]และลบค่าคงที่ตัวเลขแทนค่าคงที่ของอักขระ :)
user1354557

1
ฉันปรับปรุงการบีบอัดด้วย: main(int x,char**v){char p[400],*a[]={"1221212213113213","2131222","21122131","1222","112213113","122223113","122221122"},*b="adcadcadcaebcadcadcafbcadcadcagbcadcadcadc";*p=0;for(;*b;b++)strcat(p,a[*b-97]);putchar(p[atoi(v[1])%400]);}(215 chars)
user1354557

4

C ( 151 145 137 131 130 ตัวอักษร)

ฉันประหลาดใจที่เห็นว่ามีเพียงโซลูชันเดียวเท่านั้นที่ไม่ได้ใช้เครื่องมือปฏิทินในตัว นี่คือวิธีการทางคณิตศาสตร์ (ที่ทำให้งงมาก) ใน C:

f(x){return(x+(x+3)/4-(x+99)/100+!!x)%7;}main(int x,char**v){int y=atoi(v[1])%400,a=f(y+1);putchar('1'+((f(y)&3)==1)+(a>2&&a-5));}

(คอมไพล์ข้างต้นใน GCC โดยไม่มีข้อผิดพลาด)

ทางเลือกอื่น: C (287-> 215 chars)

ฉันชอบวิธีแก้ปัญหาของ Williham Totlandมากกว่าและการใช้การบีบอัดของเขา ฉันแก้ไขข้อบกพร่องเล็ก ๆ สองตัวและปรับแต่งโค้ดเพื่อลดความยาวของมัน:

main(int x,char**v){char p[400],*a[]={"1221212213113","213122221122131","12213113","22213113","22221122","2131"},*b="abababafcbababafdbababafebababab";*p=0;for(;*b;b++)strcat(p,a[*b-97]);putchar(p[atoi(v[1])%400]);}

4

PHP, 82

<?for($i=1,$c=0;$i<13;$i++)$c+=(date("N",mktime(0,0,0,$i,1,$argv[1]))==7);echo $c;

ขึ้นอยู่กับ

"เดือนใดก็ตามที่เริ่มต้นในวันอาทิตย์จะมีวันศุกร์ที่ 13 และอย่างน้อยหนึ่งวันศุกร์ที่ 13 ในทุก ๆ ปีปฏิทิน"

จากhttp://en.wikipedia.org/wiki/Friday_the_13th


4

ทุบตี47 36

seq -f$1-%g-6 12|date -f-|grep -c ^F

@DigitalTrauma ขอขอบคุณสำหรับการบันทึก 10 ตัวอักษรโดยใช้กับการเริ่มต้นที่จะเริ่มต้นseq1

date -f<(printf "%s\n" $1-{1..12}-6)|grep -c ^F

(รุ่นก่อนหน้าใช้echoข้อผิดพลาดในการนำเสนอเนื่องจากบรรทัดว่างเมื่อ<(echo $1-{1..12}-6$'\n')ดังนั้นฟังก์ชั่นนี้ทำงานได้ดีจนถึงวันนี้เป็นวันศุกร์

มาดูกัน:

set -- 2013
seq -f$1-%g-6 1 12|date -f-|grep -c ^F
2

date -f<(printf "%s\n" $1-{1..12}-13)|grep -c ^F
2

คือเป็นสถานที่เกิดเหตุขึ้นอยู่กับ si ถ้ามันจะไม่ได้ทำงานคุณอาจจะต้อง

export LANG=C

หรือ

LANG=C date -f<(printf "%s\n" $1-{1..12}-13)|grep -c ^F

เป็นฟังก์ชั่น; +7 -> 43

f(){ seq -f$1-%g-6 12|date -f-|grep -c ^F;}

f 2013
2

for i in {2010..2017};do echo $i $(f $i) ;done
2010 1
2011 1
2012 3
2013 2
2014 1
2015 3
2016 1
2017 2

โบนัส: +78 -> 121

จากนั้นถ้าฟังก์ชั่นของฉันกลายเป็น:

f(){ o=();for t in $(seq -f$1-%g-6 12|date -f- +%a,%b);do [ "${t:0:1}" = "F" ]&&o+=(${t#*,});done;echo ${#o[@]} ${o[@]};}

หรือ

f(){ o=();
     for t in $(seq -f$1-%g-6 1 12|date -f- +%a,%b);do
         [ "${t:0:1}" = "F" ]&&o+=(${t#*,})
       done
     echo ${#o[@]} ${o[@]}
}

for i in {2010..2017};do echo $i $(f $i) ;done
2010 1 Aug
2011 1 May
2012 3 Jan Apr Jul
2013 2 Sep Dec
2014 1 Jun
2015 3 Feb Mar Nov
2016 1 May
2017 2 Jan Oct

สิ่งนี้ดูเหมือนจะขึ้นอยู่กับสถานที่
Peter Taylor

Cใช่นี้เป็นไปตามค่าเริ่มต้น แต่มีข้อผิดพลาด ...
เอฟ HAURI

ประหยัดถ่านโดยการคลายสตริงการจัดรูปแบบ printf ของคุณและหนีออกจาก \ แทน:%s\\n
Digital Trauma

1
หรือใช้seqเพื่อวาง 8 chars:date -f<(seq -f$1-%g-6 1 12)|grep -c ^F
Digital Trauma

1
ที่จริงแล้วคุณสามารถโกนได้อีก 2 ตัวอักษร หากคุณไม่ใช้หมายเลขลำดับเริ่มต้น seq จะเริ่มต้นที่ 1 ตามค่าเริ่มต้นซึ่งเป็นสิ่งที่คุณต้องการ:seq -f$1-%g-6 12|date -f-|grep -c ^F
Digital Trauma

4

JavaScript, 70

f=function(a){b=0;for(c=12;c--;)b+=!new Date(a,c,1).getDay();return b}

แล้วทำไมถึงเป็น -1
Lukasz 'Severiaan' Grela

1
ดูดี! คุณสามารถบันทึกอีกไม่กี่ไบต์โดยการลบ,b,cจากการประกาศฟังก์ชัน (! มันตกลงที่จะรั่วไหล vars สำหรับการเล่นกอล์ฟ) ยังเป็นbถูกโยนเป็นNumberที่คุณสามารถ+=ผลของการทดสอบแทนของ:&&b++ b+=/^F/.test(new Date(a,c,6))อย่างไรก็ตามคุณสามารถบันทึกไบต์อื่นได้โดยใช้!new Date(a,c,1).getDay()(ผลงานนี้เพราะgetDayคืน 0 สำหรับวันอาทิตย์และถ้าวันที่ 13 เป็นวันศุกร์วันที่ 1 จะเป็นวันอาทิตย์) แทนที่จะเป็นวันtestที่รวมกันคุณควรประหยัด 7 ไบต์!
Dom Hastings

@DomHastings: ขอบคุณสำหรับเคล็ดลับของคุณ !!!
guy777

3

k

64 ตัวอักษร

{+/6={x-7*x div 7}(.:')x,/:(".",'"0"^-2$'$:1+!:12),\:".13"}[0:0]

อ่านจาก stdin


ตกลงเกิดอะไรขึ้นที่นี่? : P
Williham Totland

อ่านในปีสร้างรายการของวันที่ 13 ของทุกเดือนวันทดสอบของสัปดาห์ = วันศุกร์ผลรวมรายการของ booleans
skeevey

3

Common LISP (CLISP), 149

(print 
    (loop for i from 1 to 12 count 
        (= 4 (nth-value 6 
            (decode-universal-time
                (encode-universal-time 0 0 0 13 i
                    (parse-integer (car *args*)) 0))))))

โอ้พระเจ้าผมไม่เคยอ่านกระเพื่อม ..
Cruncher

2

C # 110 101 93 92

int f(int y){int c=0;for(int i=1;i<13;i++)c+=new DateTime(y,i,8).DayOfWeek>0?0:1;return c;}

C # Linq 88

int g(int y){return Enumerable.Range(1,12).Count(m=>new DateTime(y,m,8).DayOfWeek==0);}

ขอบคุณ Jeppe Stig Nielsen สำหรับ linq และข้อเสนอแนะในการตรวจสอบวันอาทิตย์ที่ 8

ขอขอบคุณที่ Danko Durbićสำหรับการแนะนำแทน>==


แทนการใช้เทียบเท่าc+=(int)new DateTime(y,i,13).DayOfWeek==5?1:0; c+=new DateTime(y,i,8).DayOfWeek==0?1:0;เคล็ดลับคือการลบ5แล้วเพราะคุณสามารถกำจัดทิ้งไปintและยังหมายเลขที่มีหนึ่งหลักน้อยกว่าจำนวน8 13วันอาทิตย์ที่แปด!
Jeppe Stig Nielsen

ด้วย int g(int y){return Enumerable.Range(1,12).Count(m=>new DateTime(y,m,8).DayOfWeek==0);}Linq: y=>Enumerable.Range(1,12).Count(m=>new DateTime(y,m,8).DayOfWeek==0)แน่นอนเป็นแลมบ์ดานี้อยู่
Jeppe Stig Nielsen

.DayOfWeek<1คุณสามารถบันทึกตัวละครตัวหนึ่งโดยการเปรียบเทียบ
Danko Durbić

@ DankoDurbićสิ่งนี้สามารถใช้กับc#คำตอบได้ แต่ไม่แน่ใจว่าจะนำไปใช้linqอย่างไร
Kami

ความผิดพลาดของฉัน; เห็นได้ชัดว่าคุณไม่สามารถเปรียบเทียบDayOfWeekกับจำนวนเต็มอื่น ๆ ที่ไม่ใช่-0 error CS0019: Operator '<' cannot be applied to operands of type 'System.DayOfWeek' and 'int'
Danko Durbić

2

PHP, 55 ไบต์

for(;++$i<13;)$c+=!date(w,strtotime($argn.-$i));echo$c;

echo <year> | php -nR '<code>'ทำงานด้วย

โดยพื้นฐานแล้วสิ่งเดียวที่โอเล็กพยายามและดาเมียร์กาซิโปวิชทำก็คือเล่นกอล์ฟได้ดีกว่า:
ทุก ๆ เดือนที่เริ่มต้นด้วยวันอาทิตย์จะมีวันศุกร์ที่ 13
ดังนั้นฉันจึงวนรอบเดือนและนับวันแรกที่เป็นวันอาทิตย์

ทำให้พังถล่ม

for(;++$i<13;)          // loop $i from 1 to 12
    $c+=!                   // 4. if result is not truthy (weekday==0), increment $c
        date(w,             // 3. get weekday (0 stands for Sunday)
            strtotime(      // 2. convert to timestamp (midnight 1st day of the month)
                $argn.-$i   // 1. concatenate year, "-" and month
            )
        )
    ;
echo$c;                 // output



1

Rebol, 63

f: 0 repeat m 12[d: do ajoin["6-"m"-"y]if d/weekday = 5[++ f]]f

ตัวอย่างการใช้งานในคอนโซล Rebol:

>> y: 2012
== 2012

>> f: 0 repeat m 12[d: do ajoin["6-"m"-"y]if d/weekday = 5[++ f]]f
== 3

ทางเลือกในการแก้ปัญหาซึ่งรวบรวมทั้งหมดในวันศุกร์ที่ 13 ในปีนั้นคือ:

>> collect[repeat m 12[d: do ajoin["13-"m"-"y]if d/weekday = 5[keep d]]]
== [13-Jan-2012 13-Apr-2012 13-Jul-2012]

1

Bash and Sed, 39

ncal $1|sed '/F/s/13/\
/g'|grep -c ^\ 2

ncal พิมพ์ปฏิทินสำหรับปีที่กำหนดโดยมีวันในสัปดาห์ทางด้านซ้าย

sedด้วย/gค่าสถานะย่อยออกทั้งหมด 13s ด้วยการขึ้นบรรทัดใหม่

grep -c นับจำนวนบรรทัดที่ขึ้นต้นด้วย "2" (20 เสมอตาม 13)

ขอบคุณ @DigitalTrauma สำหรับการค้นหาข้อผิดพลาดในรุ่นเก่าของฉันและเสนอทางออก!


ใช้งานไม่ได้สำหรับฉัน - มีการพิมพ์บรรทัดวันศุกร์เพียงครั้งเดียวแม้ว่าจะมีมากกว่า 13 รายการ
บาดเจ็บทางดิจิทัล

1
ฉันคิดว่าสิ่งที่ดีที่สุดที่ฉันสามารถทำได้กับสิ่งนี้คือ 38:ncal $1|sed /F/s/13/\\n/g|grep -c ^\ 2
Digital Trauma

1
@DigitalTrauma คุณพูดถูก เมื่อถึงจุดหนึ่งสคริปต์นี้ทำงาน ให้ฉันแก้ไข
ไม่ใช่ว่า Charles

1
@DigitalTrauma ดูเหมือนว่ารุ่นที่ใช้งานได้นานกว่านี้อีกบ้าง ขอบคุณสำหรับการแก้ไข!
ไม่ใช่ชาร์ลส์ที่

ที่น่าสนใจนิพจน์ sed ที่ไม่มีคำพูดที่ฉันเสนอนั้นใช้ได้กับ GNU sed (Linux) แต่ไม่ใช่กับ BSD sed (OSX) ฉันเดาว่าคุณจะได้รับ 1 ถ่านที่พกพาได้ถ้าคุณเลือกรุ่น GNU
บาดเจ็บทางดิจิตอล

1

สกาลา, 76 68 ตัวอักษร

ใน 78 ตัวอักษร:

def f(y:Int)=0 to 11 count(new java.util.GregorianCalendar(y,_,6).get(7)==6)

ไม่มีอะไรออกจากสามัญยกเว้นสำหรับการใช้ตัวเลขที่มีมนต์ขลังสำหรับและDAY_OF_WEEK = 7FRIDAY = 6

รุ่น 68 ตัว:

def f(y:Int)=0 to 11 count(new java.util.Date(y-1900,_,6).getDay==5)

ใช่จาวาเปลี่ยนค่าของวันของสัปดาห์ค่าคงที่ระหว่าง API


It's a shame new java.util.GregorianCalendar has to be so long :(
Cruncher

1

Python 195 / 204

Works only for previous years, because monthdatescalendar returns a calendar for the given year until now. I think there is a lot of optimizing potential left :).

import calendar, sys
c=calendar.Calendar()
f=0
for m in range(1,12):
 for w in c.monthdatescalendar(int(sys.argv[1]),m):
  for d in w:
   if d.weekday() == 4 and d.day == 13:
    f=f+1
print(f)

Another solution, works for every date but it isn't smaller:

import datetime,sys
y=int(sys.argv[1])
n=datetime.date
f=n(y,1,1)
l=n(y,12,31)
i=0
for o in range(f.toordinal(), l.toordinal()):
 d=f.fromordinal(o)
 if d.day == 13 and d.weekday() == 4:
  i=i+1
print(i)

In your first example the range should be (1,13) otherwise you'd miss December Friday 13ths, like in 2013.
leancz

1
You didn't even bother golfing. Remove some of those spaces.
mbomb007



0

Perl + lib POSIX 55

With the idea of not looking for 13th but first, and as sunday is 0 this let save 3 chars! Thanks @ Iszi and Danko Durbić!

$==$_;$_=grep{!strftime"%w",0,0,0,1,$_,$=-1900}(0..11)

Could compute 2010 to 2017 (for sample) in this way:

perl -MPOSIX -pE '$==$_;$_=grep{!strftime"%w",0,0,0,1,$_,$=-1900}(0..11)' <(
    printf "%s\n" {2010..2017})
11321312

(Ok, there is no newline, but that was not asked;)

Old post: 63

$==grep{5==strftime"%w",0,0,0,13,$_,$ARGV[0]-1900}(0..11);say$=

In action:

for i in {2010..2017};do
    echo $i $(
        perl -MPOSIX -E '
            $==grep{5==strftime"%w",0,0,0,13,$_,$ARGV[0]-1900}(0..11);say$=
            ' $i );
  done
2010 1
2011 1
2012 3
2013 2
2014 1
2015 3
2016 1
2017 2

0

In Smalltalk (Squeak/Pharo flavour), implement this method in Integer (86 chars)

countFriday13^(1to:12)count:[:m|(Date year:self month:m day:13)dayOfWeekName='Friday']

Then use it like this: 2014countFriday13.

Of course, we could use a shorter name, but then it would not be Smalltalk


0

C++ - Too many bytes :(

I tried a solution which doesn't make use of any date libraries.

I found a pretty cool (if I may say so myself) solution. Unfortunately I can't get it shorter than this, which really bugs me because it feels like there should be a better way.

The solution hinges on this algorithm which is only 44 bytes in itself. Unfortunately I need another 100 bytes to wrap it nicely...

#include<stdlib.h>
main(int,char**v){int f=0,d,m,y;for(m=1;m<13;++m)d=13,y=atoi(v[1]),(d+=m<3?y--:y-2,23*m/9+d+4+y/4-y/100+y/400)%7-5||++f;return f;}

Output through the return code (in C++, using cout or printf or anything like that requires another #include, which would blow up the solution even more).

Driver / test program:

# Make sure we're not running an old version
rm doomsday.exe

gcc doomsday.cpp -o doomsday.exe

./doomsday.exe 1776
echo 1766: $?

./doomsday.exe 2012
echo 2013: $?

./doomsday.exe 2013
echo 2013: $?

./doomsday.exe 2014
echo 2014: $?

echo `wc doomsday.cpp -c` characters

Output of the driver program:

$ ./test_doomsday 
1766: 2
2013: 3
2013: 2
2014: 1
150 doomsday.cpp characters

I count 88 for the algorithm, not 44. What is the algorithm and what is the warpping? ($m<3?$y--:$y-2)+3 instead of d=13,, d+=m<3?y--:y-2, and d+4 should work as well and saves a lot. +5 instead of +3 and -5 should work too and saves 2 bytes. for(m=0;++m<13;) saves one byte. Moving m=0 to the function head saves another byte; and moving ()%7||++f to the loop head saves another one. Down from 149 to 136 bytes.
Titus

0

Clojure, 207 187 bytes

-20 bytes by getting rid of the import, and some whitespace I missed.

(import '[java.time LocalDate DayOfWeek])#(loop[d(LocalDate/parse(str %"-01-01"))c 0](if(=(.getYear d)%)(recur(.plusDays d 1)(if(and(=(.getDayOfMonth d)13)(= (.getDayOfWeek d) DayOfWeek/FRIDAY))(inc c)c))c))

Starting on Janauary 1st of the given year, it loops over each day. If the day is Friday the 13th, it increments the count. It continues to loop until it reaches the next year.

(import '[java.time LocalDate DayOfWeek])

(defn count-friday-13ths [year]
  (loop [d (LocalDate/parse (str year "-01-01")) ; Starting date
         c 0] ; The count
    (if (= (.getYear d) year) ; If we haven't moved onto the next year...
      (recur (.plusDays d 1) ; Add a day...
             (if (and (= (.getDayOfMonth d) 13) ; And increment the count if it's Friday the 13th
                      (= (.getDayOfWeek d) DayOfWeek/FRIDAY))
               (inc c) c))
      c))) ; Return the count once we've started the next year.

0

PHP, no builtins, 81 bytes

echo 0x5da5aa76d7699a>>(($y=$argn%400)+($y>102?$y>198?$y>299?48:32:16:0))%28*2&3;

Run with echo <year> | php -nR '<code>'.

breakdown

Weekdays repeat every 400 years.
In the results for 1600 to 1999 (for example), there is a 28-length period with just three gaps:

  0:2212122131132131222211221311
 28:2212122131132131222211221311
 56:2212122131132131222211221311
 84:2212122131132131122
103:       131132131222211221311
124:2212122131132131222211221311
152:2212122131132131222211221311
180:2212122131132131222
199:       131132131222211221311
220:2212122131132131222211221311
248:2212122131132131222211221311
276:221212213113213122221122
300:            2131222211221311
316:2212122131132131222211221311
344:2212122131132131222211221311
372:2212122131132131222211221311

After adjusting the year for these gaps, we can get the result with a simple hash:

$y=$argn%400;foreach([300,199,103]as$k)$y<$k?:$y+=16;
echo"2212122131132131222211221311"[$y%28];

Not short (95 bytes) but pretty. And we can golf

  • 4 bytes by using a ternary chain for the offset,
  • 8 bytes by converting the hash map from a base4 string to integer,
  • one more by using the hex representation,
  • and one by merging the expressions.

A port of CompuChip´s C++ answer can be golfed down to 84 bytes: for(;++$m<13;23*$m/9+($m<3?$y--:$y-2)+5+$y/4-$y/100+$y/400)%7?:$f++)$y=$argn;echo$f;
Titus

0

Japt -x, 10 bytes

CÆ5¥ÐUXD e

Try it

CÆ5¥ÐUXD e     :Implicit input of integer U
C              :12
 Æ             :  Map each X in the range [0,C) (months are 0-indexed in JavaScript)
  5¥           :  Check if 5 is equal to
    ÐUXD       :  new Date(U,X,13)
         e     :  0-based index of day of the week
               :Implicitly reduce by addition and output
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.