Có bao nhiêu thứ sáu ngày 13 trong một năm?


28

Thử thách của bạn là viết một chương trình, trong một năm, sẽ đưa ra số lượng "Thứ Sáu ngày 13" trong đó.

Quy tắc & chi tiết:

  • Bạn có thể đưa đầu vào qua STDINhoặc làm đối số được truyền cho chương trình của bạn.
  • Bạn nên xuất kết quả cho STDOUT.
  • Bạn có thể cho rằng đầu vào sẽ là một năm hợp lệ và không đăng ký trước lịch Gregorian (hành vi không xác định được cho phép trong những trường hợp này).
  • Thư viện lịch / ngày được cho phép.

Đây là một , vì vậy mã ngắn nhất (tính bằng byte) sẽ thắng.

(Liên kết thử thách liên quan)


7
Phạm vi yêu cầu của đầu vào là gì? Nếu nó đi nhiều trước năm 1800, những giả định nào nên được thực hiện về việc chuyển đổi từ lịch Julian sang lịch Gregorian?
Peter Taylor

@PeterTaylor Tôi chưa nghĩ về nó. Nếu một ngày trước ngày gregorian thì bạn có thể có hành vi không xác định.
Cruncher

1
Các quốc gia đầu tiên áp dụng lịch Gregorian đã làm như vậy vào tháng 10 năm 1582, theo sau sự thúc đẩy của chính Gregory. Các quốc gia áp dụng lịch mới muộn không thay đổi cho đến thế kỷ 20, ví dụ Hy Lạp đã giới thiệu nó vào ngày 1 tháng 3 năm 1923.
Jeppe Stig Nielsen

@JeppeStigNielsen Tôi không biết nhiều về lịch và như vậy. Cho dù họ có nhận nuôi chúng hay không cũng không thay đổi ngày tháng của gregorian. Thư viện sẽ có thể tính toán ngày từ một cách trở lại tôi đoán?
Cruncher

3
Tôi đoán là không chính thức ở đây, tôi đoán. Nhiều thư viện được viết bởi các lập trình viên người Mỹ gốc Anh sử dụng tháng 9 năm 1752 là thời gian "thay đổi" chính xác của lịch. Đây là khi Đế quốc Anh thay đổi. Lịch mới được giữ khi Hoa Kỳ được thành lập, tất nhiên. (Vì tò mò, một số phần mềm SQL có năm 1753 là năm tối thiểu vì họ không muốn đối phó với vấn đề tháng 9 năm 1752.) Tuy nhiên, sử dụng tháng 9 năm 1752 là rất khó hiểu. Bạn nói đúng ngày Gregorian là như nhau cho dù chúng được sử dụng trong lịch sử hay không. Đó là cái gọi là lịch Gregorian proleptic .
Jeppe Stig Nielsen

Câu trả lời:


3

APL (Dyalog APL) với cal từ dfns , 29 byte

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

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

⍳ 12 các số nguyên từ một đến mười hai

⎕ ,¨ lấy đầu vào số và thêm vào mỗi mười hai số

{...  trên mỗi cặp, áp dụng các chức năng ...

cal⍵ lấy lịch cho tháng đó

2 ↓ thả hai hàng (chú thích và ngày)

 hoán vị (để chúng ta có thể giải quyết các cột thay vì các hàng)

¯5 ↑ lấy năm số cuối (hai chữ số cho mỗi thứ Sáu và thứ Bảy cộng với một khoảng trắng)

3 ↑ lấy hai số đầu tiên (hai chữ số cho thứ Sáu cộng với một khoảng trắng)

 hoán vị (để chúng ta có được thứ tự đọc)

, rốn

 thực hiện dưới dạng biểu thức APL (đưa ra danh sách các ngày thứ Sáu)

13 ∊ mười ba là thành viên của danh sách đó?

+/ tổng cộng 12 Booleans


Sử dụng thuật toán của @ Wrzlprmft , chúng tôi có thể làm điều đó mà không cần thư viện cho 53 byte:

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

-∘0 1 trừ 0 và 1

400 100 4 ∘.| bảng phân chia còn lại trong hai năm (qua) chia cho các số này (xuống)

0 ≠.= "sản phẩm" bên trong có 0, nhưng sử dụng và = thay vì +. ×

⊢ , chuẩn bị năm đối số không thay đổi

2 3 ¯1 +.× sản phẩm bên trong với những con số này

14 | phần còn lại khi chia cho mười bốn

'21232211321211' ⌷⍨ lập chỉ mục vào chuỗi này


Đó là 29 ký tự, nhưng đây là hơn 1 ký tự phải không?
Cruncher

@Cruncher Tôi đã thêm một liên kết giải thích trong tiêu đề. Nếu bạn mở liên kết TIO, bạn sẽ thấy thông báo "29 ký tự, 29 byte (SBCS)" ở bên phải, tức là Bộ ký tự byte đơn.
Adám

Chà, tôi đoán đây là người chiến thắng mới, liệu thực hành tiêu chuẩn ở SE này có thay đổi câu trả lời được chấp nhận lâu sau câu hỏi này không?
Cruncher

@Cruncher Có. Và thậm chí còn có huy hiệu để có được chấp nhận lâu sau OP.
Adám

12

Toán học 49 46 45 44 42

Là một hàm thuần túy : 42 ký tự

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

Thí dụ

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

2


Như một chức năng được đặt tên : 44 ký tự

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

Ví dụ

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

2
3
2
1


Một ký tự ngắn hơn:f=DayName@{#,m,6}~Table~{m,12}~Count~Friday&
Mr.Wizard

@ Mr.Wizard Có. Điều làm tôi ngạc nhiên là Mathicala có thể phân tích nhiều trường hợp ký hiệu infix.
DavidC

David làm tôi ngạc nhiên rằng bạn đã không thấy (hơn) việc sử dụng ký hiệu dính liền này của tôi. : ^) (Ví dụ: (1) , (2) )
Mr.Wizard

8

Ruby, 49 48 47 46

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

Chỉnh sửa: Cạo một nhân vật bằng cách quay lại một tuần, nhờ Jan và một nhân vật khác bằng cách chuyển từ Time.new sang Time.gm

Chỉnh sửa: Với chi phí làm xáo trộn nó thêm một chút, tôi có thể lên 46 với

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

5
tiết kiệm một lần nếu bạn đếm số thứ sáu ngày 6
John Dvorak

2
@JanDvorak thông minh!
lịch sử

tại sao 6? Tôi đã không nhận được nó.
NARKOZ

3
Nếu thứ 6 là thứ sáu, thì ngày 13 cũng là thứ sáu
TwiNight

Nếu ngày 8 là Chủ nhật, thì ngày 1 cũng vậy, và vì vậy bạn có thể sử dụng Time.gm(m,i).wday<1. Ngoài ra, tôi không biết tại sao bạn đặt tên hàm.
Lee W

8

Powershell, 68 63 58 52 50

Cảm ơn Iszi cho tiền boa.

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

Sử dụng thực tế là nếu ngày đầu tiên trong tháng là Chủ nhật, ngày 13 sẽ là Thứ Sáu.

Tôi cũng đã thử:

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

nhưng nó không giống nhau $argstrong khối kịch bản.


1
Tôi thích ý tưởng sử dụng ngày đầu tiên của tháng.
Cruncher

Thủ thuật hay đấy chứ. Các @ là không cần thiết, mặc dù.
Iszi

Một điều nữa, mặc dù tôi có tội giống nhau trong rất nhiều kịch bản của tôi. Thách thức không xác định rằng đầu vào có thể đến từ một đối số. Thay thế $nbằng $argstrong vòng lặp, và bạn có thể làm mà không $n=read-host;hoàn toàn. Lưu 8. Xóa @, như đã đề cập ở trên và bạn giảm xuống còn 54.
Iszi

Sửa chữa: Giảm xuống còn 52!
Iszi

Cố gắng tìm hiểu tại sao kịch bản thứ hai của bạn không hoạt động và tôi bị thua lỗ. Điều thú vị là tôi có thể thay đổi ra $argscho $input, do đó ăn năm từ các đường ống dẫn, và kịch bản sẽ chạy nhưng nó luôn luôn kết quả đầu ra 3.
Iszi

5

R 76 72 57

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

Có thể dễ dàng giảm số này xuống 4 bằng cách thay thế "%a %d")=="Fri 13"bằng "%w%d)=="513")bằng cách sử dụng dow dưới dạng số và xóa khoảng trắng.
chmullig

Nhiều đánh giá cao!
flodel

+1 Mặc dù chỉ làm trong seqtháng thực sự ngắn hơn ở đây! sum(format(as.Date(paste(scan(),1:12,13,sep="-")),"%w%d")=="513")chỉ có 65 ký tự!
plannapus

wow tôi đã không đoán được rằng <sẽ ép buộc một nhân vật thành một số nguyên. Bí quyết đẹp!
plannapus

@plannapus Nó khá phổ biến. Vì mã ký tự là tất cả các số. Thậm chí java có thể so sánh int và 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

Thứ hai ngày 9 có thể không hoàn toàn giống với chiếc nhẫn nhưng nó cũng hoạt động tốt.

Chỉnh sửa: Một năm rưỡi để thông báo datengắn hơn datetime:)


Giải pháp thực sự tốt đẹp!
leancz

2
Bạn có thể lưu một char bằng cách thực hiệnfrom datetime import*
user80551

Tốt đẹp! Tôi đã kết thúc với một cái gì đó giống hệt một cách hiệu quả, nhưng tránh exec: f=lambda y:sum([date(y,m,13).weekday()==4 for m in range(1,13)]).... Mặc dù vậy, giải pháp kích thước tương tự với nhập (86 byte).
iwaseatenbyagrue

5

Không sử dụng bất kỳ thư viện hoặc chức năng ngày tích hợp:

Golfscript - 51

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

' [3/=RI[)a%:*.' cũng có thể 'feefefgeeffgfe'

Con trăn - 82 79

Về cơ bản cùng một thuật toán.

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

Sử dụng thủ thuật này , điều này có thể được đánh xuống để:

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

Điều này khai thác thực tế rằng, thông minh lịch, chỉ có 14 năm khác nhau, được phân biệt bởi ngày cuối cùng của họ và liệu họ có nhảy hay không. ltính toán số năm nhuận theo lý lẽ của nó (nếu lịch Gregorian kéo dài ngược lại năm 1). (2*i+3*l(i)-l(i-1))%14là viết tắt của l(i)-l(i-1)+(i+l(i))%7*2, trong đó l(i)-l(i-1)cho chúng ta biết liệu cuộc tranh luận có phải là một năm nhuận hay không và i+l(i)tổng hợp các ca làm việc của ngày cuối cùng (một trong một năm bình thường, hai trong một năm nhuận).


Vì đây là môn đánh gôn đầu tiên của tôi, tôi sẽ đánh giá cao bất kỳ gợi ý nào về việc đánh gôn tiếp theo.
Wrzlprmft

Tôi đã suy nghĩ về một giải pháp như vậy sử dụng thực tế là chỉ có 14 năm duy nhất thực sự, nhưng không chắc chắn là ngôn ngữ tốt nhất để làm cho nó cạnh tranh. Tôi nghĩ rằng đây là câu trả lời ngắn nhất không có thư viện. Nếu 4 năm nhuận được thống nhất cứ sau 4 năm, bạn có thể giành chiến thắng với điều này
Cruncher

4

C Hơn 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]-'`');}

Không phải là câu trả lời ngắn nhất, nhưng không sử dụng thư viện.


Này, bạn có sẵn lòng đưa ra câu trả lời không có căn cứ với một lời giải thích không? Tôi quan tâm đến chính xác những gì bạn đã làm
Cruncher

1
@Cruncher, đó là một bảng tra cứu trên cơ sở lịch Gregorian theo chu kỳ 400 năm.
Peter Taylor

1
Rõ ràng hơn (và dài hơn), C # : static char GetNumberOfFriday13s(int year) { const string perpetualCalendar = "1221212213113213122221122131122121221311321312222112213112212122131132131222211221311221212213113213112213113213122221122131122121221311321312222112213112212122131132131222211221311221212213113213122213113213122221122131122121221311321312222112213112212122131132131222211221311221212213113213122221122213122221122131122121221311321312222112213112212122131132131222211221311221212213113213122221122131"; return perpetualCalendar[year % 400];. Sẽ không làm việc trong những năm tiêu cực.
Jeppe Stig Nielsen

Dễ thương! Là một lỗi nhỏ, v[0]nên được v[1]. Bạn cũng có thể chơi golf này một chút; xem xét việc sử dụng strcat, lưu trữ các ký tự để in trực tiếp a[]và trừ các hằng số thay vì các hằng ký tự. :)
dùng1354557

1
Tôi cũng đã cải thiện khả năng nén: 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 ký tự)
user1354557

4

C ( 151 145 137 131 130 ký tự)

Tôi ngạc nhiên khi thấy rằng chỉ có một giải pháp khác không sử dụng các công cụ lịch tích hợp. Đây là một cách tiếp cận toán học (rất khó hiểu), cũng trong 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));}

(Các biên dịch trên trong GCC không có lỗi)

Giải pháp thay thế: C (287-> 215 ký tự)

Tôi khá thích giải pháp của Williham Totland và cách sử dụng nén của anh ấy. Tôi đã sửa hai lỗi nhỏ và điều chỉnh mã để rút ngắn độ dài của nó:

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;

Dựa trên

"Bất kỳ tháng nào bắt đầu vào Chủ nhật đều có Thứ Sáu ngày 13 và có ít nhất một Thứ Sáu ngày 13 trong mỗi năm dương lịch."

Từ http://en.wikipedia.org/wiki/Friday_the_13th


4

bash 47 36

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

Cảm ơn @DigitalTrauma vì đã lưu 10 ký tự bằng cách sử dụng seqvới bắt đầu mặc định 1.

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

(Phiên bản trước sử dụng echo hiện tại một lỗi vì dòng trống khi <(echo $1-{1..12}-6$'\n'). Vì vậy, chức năng này hoạt động tốt cho đến hôm nay thứ Sáu.

Hãy xem:

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

miền địa phương phụ thuộc , si nếu nó không hoạt động, bạn có thể phải

export LANG=C

hoặc là

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

Vào một chức năng; +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

Tiền thưởng: +78 -> 121

Từ đó, nếu chức năng của tôi trở thành:

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[@]};}

hoặc là

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

Điều này dường như là phụ thuộc địa phương.
Peter Taylor

Có, Điều này dựa trên mặc định C. Nhưng có một lỗi ...
F. Hauri 11/12/13

Lưu một char bằng cách bỏ qua chuỗi định dạng printf của bạn và thoát \ thay vào đó:%s\\n
Chấn thương kỹ thuật số

1
Hoặc sử dụng seqđể thả 8 ký tự:date -f<(seq -f$1-%g-6 1 12)|grep -c ^F
Chấn thương kỹ thuật số

1
Trên thực tế, bạn có thể cạo thêm 2 ký tự. Nếu bạn bỏ qua số thứ tự bắt đầu, seq sẽ bắt đầu ở 1 theo mặc định, đó là những gì bạn muốn:seq -f$1-%g-6 12|date -f-|grep -c ^F
Chấn thương kỹ thuật số

4

JavaScript, 70

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

và tại sao nó là -1?
Lukasz 'Severiaan' Grela 11/12/13

1
Có vẻ tốt! Bạn có thể tiết kiệm nhiều hơn một vài byte, bằng cách loại bỏ ,b,ctừ phần khai báo hàm (! Nó ok để rò rỉ vars cho golf), cũng như bđược chọn vào vai một Numberbạn có thể +=là kết quả của bài kiểm tra thay cho &&b++: b+=/^F/.test(new Date(a,c,6)). Tuy nhiên, bạn có thể lưu một byte khác, bằng cách sử dụng !new Date(a,c,1).getDay()(điều này hoạt động vìgetDay trả về 0 cho Chủ nhật và nếu ngày 13 là thứ Sáu, ngày 1 sẽ là Chủ nhật) thay vì testhoàn toàn sẽ giúp bạn tiết kiệm 7 byte!
Dom Hastings

@DomHastings: thx cho lời khuyên của bạn !!!
chàng777

3

k

64 ký tự

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

Đọc từ stdin


Ok, chỉ là những gì đang xảy ra ở đây? : P
Williham Totland

Đọc trong năm, xây dựng danh sách các ngày của ngày 13 hàng tháng, ngày kiểm tra trong tuần = thứ sáu, tổng hợp danh sách các
booleans

3

Lisp thường gặp (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))))))

Trời ơi, tôi không bao giờ có thể đọc được ..
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);}

Cảm ơn Jeppe Stig Nielsen cho linq và đề nghị kiểm tra chủ nhật vào ngày 8.

Cảm ơn Danko Durbić đã gợi ý >thay vì ==.


Thay vì c+=(int)new DateTime(y,i,13).DayOfWeek==5?1:0;sử dụng tương đương c+=new DateTime(y,i,8).DayOfWeek==0?1:0;. Bí quyết là trừ đi 5, bởi vì sau đó bạn có thể thoát khỏi dàn diễn viên int, và số 8này có một chữ số nhỏ hơn số 13. Chủ nhật thứ tám!
Jeppe Stig Nielsen

Với Linq : int g(int y){return Enumerable.Range(1,12).Count(m=>new DateTime(y,m,8).DayOfWeek==0);}. Tất nhiên là một lambda này y=>Enumerable.Range(1,12).Count(m=>new DateTime(y,m,8).DayOfWeek==0).
Jeppe Stig Nielsen

Bạn có thể lưu một ký tự bằng cách so sánh .DayOfWeek<1.
Danko Durbić

@ DankoDurbić Điều này có thể áp dụng cho c#câu trả lời nhưng không chắc chắn làm thế nào để áp dụng nó linq.
Kami

Lỗi của tôi; rõ ràng bạn không thể so sánh DayOfWeekvới bất kỳ số nguyên nào khác ngoài 0- error CS0019: Operator '<' cannot be applied to operands of type 'System.DayOfWeek' and 'int'.
Danko Durbić

2

PHP, 55 byte

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

Chạy với echo <year> | php -nR '<code>'.

Về cơ bản giống như Oleg đã thử và Damir Kasipovic đã làm, chỉ với việc chơi golf tốt hơn:
Mỗi tháng bắt đầu bằng chủ nhật, có một ngày thứ Sáu ngày 13.
Vì vậy, tôi lặp qua các tháng và đếm những ngày đầu tiên là chủ nhật.

phá vỡ

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

K, 42

{+/1={x-7*x div 7}"D"$"."/:'$+(x;1+!12;1)}

.

k){+/1={x-7*x div 7}"D"$"."/:'$+(x;1+!12;1)}'1776 2012 2013 2014
2 3 2 1

1

Bash ( 52 47 ký tự)

for m in {1..12};do cal $m $Y;done|grep -c ^15

1

Nổi loạn, 63

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

Ví dụ sử dụng trong bảng điều khiển Rebol:

>> y: 2012
== 2012

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

Giải pháp thay thế thu thập tất cả thứ Sáu ngày 13 trong năm nhất định là:

>> 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 và Sed, 39

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

ncal in lịch cho năm nhất định với các ngày trong tuần ở bên trái.

sedvới một /gcờ phụ ra tất cả 13 giây với dòng mới

grep -c đếm các dòng bắt đầu bằng "2" (20 luôn theo sau 13)

Cảm ơn @DigitalTrauma vì đã tìm ra lỗi trong phiên bản cũ của tôi và đề xuất giải pháp!


Nó không hoàn toàn phù hợp với tôi - Dòng thứ sáu chỉ được in một lần ngay cả khi chúng chứa nhiều hơn một 13.
Chấn thương kỹ thuật số

1
Tôi nghĩ điều tốt nhất tôi có thể làm với thứ như thế này là 38:ncal $1|sed /F/s/13/\\n/g|grep -c ^\ 2
Chấn thương kỹ thuật số

1
@DigitalTrauma Bạn nói đúng. Tại một số điểm kịch bản này đã làm việc. để tôi sửa nó.
Không phải Charles

1
@DigitalTrauma có vẻ như một số phiên bản dài hơn đã hoạt động. cảm ơn đã sửa chữa
Không phải Charles

Thật thú vị, biểu thức sed không được trích dẫn mà tôi đề xuất hoạt động với GNU sed (Linux) nhưng không phải với BSD sed (OSX). Tôi đoán bạn có thể kiếm được 1 char với chi phí tính di động nếu bạn chọn phiên bản GNU.
Chấn thương kỹ thuật số

1

Scala, 76 68 ký tự

Trong 78 ký tự:

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

Không có gì khác thường, ngoại trừ việc sử dụng số ma thuật cho DAY_OF_WEEK = 7FRIDAY = 6.

Phiên bản 68 ký tự:

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

Có, Java đã thay đổi giá trị của các hằng số trong tuần giữa các API.


Thật đáng xấu hổ new java.util.GregorianCalendarphải quá lâu :(
Cruncher

1

Con trăn 195/204

Chỉ hoạt động cho các năm trước, bởi vì monthdatescalendartrả về một lịch cho năm nhất định cho đến bây giờ . Tôi nghĩ rằng có rất nhiều tiềm năng tối ưu hóa còn lại :).

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)

Một giải pháp khác, hoạt động cho mọi ngày nhưng không nhỏ hơn:

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)

Trong ví dụ đầu tiên của bạn, phạm vi phải là (1,13) nếu không bạn sẽ bỏ lỡ ngày thứ Sáu ngày 13 tháng 12, như năm 2013.
leancz

1
Bạn thậm chí không bận tâm đến việc chơi golf. Loại bỏ một số không gian đó.
mbomb007

1

Perl 6, 55 53

{sum (1..12).map: {Date.new($_,$^a,1).day-of-week>6}}

Câu trả lời cũ:

{sum (1..12).map: {Date.new($_,$^a,13).day-of-week==5}}


0

Con trăn (v2) 120

import datetime as d,sys
s=0
for m in range(1, 13):
    if d.datetime(int(sys.argv[1]),m,6).weekday()==4: s=s+1
print s

0

Perl + lib POSIX 55

Với ý tưởng về không tìm kiếm 13thnhưng trước tiên, và như sunday0let này tiết kiệm 3 chars! Cảm ơn @ Iszi và Danko Durbić!

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

Có thể tính 2010 đến 2017 (đối với mẫu) theo cách này:

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

(Ok, không có dòng mới , nhưng điều đó không được hỏi;)

Bài cũ: 63

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

Trong hành động:

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

Trong Smalltalk (Squeak / Pharo hương vị), thực hiện phương pháp này trong Integer ( 86 chars)

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

Sau đó sử dụng nó như thế này : 2014countFriday13.

Tất nhiên, chúng ta có thể sử dụng một tên ngắn hơn, nhưng sau đó không phải là Smalltalk


0

C ++ - Quá nhiều byte :(

Tôi đã thử một giải pháp không sử dụng bất kỳ thư viện ngày nào.

Tôi tìm thấy một giải pháp khá tuyệt vời (nếu tôi có thể tự nói như vậy). Thật không may, tôi không thể có được nó ngắn hơn thế này, điều này thực sự làm tôi bực mình vì cảm thấy như có một cách tốt hơn.

Giải pháp bản lề cho thuật toán này chỉ có 44 byte. Thật không may, tôi cần thêm 100 byte để bọc nó một cách độc đáo ...

#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;}

Sản lượng thông qua các mã trả lại (trong C ++, sử dụng couthoặc printfhoặc bất cứ điều gì như thế đòi hỏi khác#include , trong đó sẽ thổi lên các giải pháp thậm chí nhiều hơn).

Chương trình lái xe / kiểm tra:

# 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

Đầu ra của chương trình điều khiển:

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

Tôi đếm 88 cho thuật toán, không phải 44. Thuật toán là gì và warpping là gì? ($m<3?$y--:$y-2)+3thay vì d=13,, d+=m<3?y--:y-2,d+4nên làm việc tốt và tiết kiệm rất nhiều. +5thay vì +3-5nên làm việc quá và tiết kiệm 2 byte. for(m=0;++m<13;)tiết kiệm một byte. Di chuyển m=0đến đầu chức năng lưu một byte khác; và di chuyển ()%7||++fđến đầu vòng lặp lưu một cái khác. Giảm từ 149 xuống 136 byte.
Tít

0

Clojure, 207 187 byte

-20 byte bằng cách loại bỏ importvà một số khoảng trắng tôi đã bỏ lỡ.

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

Bắt đầu từ ngày 1 tháng 1 của năm nhất định, nó lặp lại mỗi ngày. Nếu ngày là thứ Sáu ngày 13, nó sẽ tăng số đếm. Nó tiếp tục lặp lại cho đến khi nó đạt được vào năm tới.

(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, không có nội dung, 81 byte

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

Chạy với echo <year> | php -nR '<code>'.

phá vỡ

Các ngày trong tuần lặp lại sau mỗi 400 năm.
Trong các kết quả từ 1600 đến 1999 (ví dụ), có một khoảng thời gian 28 chiều chỉ với ba khoảng trống:

  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

Sau khi điều chỉnh năm cho các khoảng trống này, chúng ta có thể nhận được kết quả bằng hàm băm đơn giản:

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

Không ngắn (95 byte) nhưng đẹp. Và chúng ta có thể chơi gôn

  • 4 byte bằng cách sử dụng chuỗi ternary cho offset,
  • 8 byte bằng cách chuyển đổi bản đồ băm từ chuỗi cơ sở4 sang số nguyên,
  • thêm một bằng cách sử dụng biểu diễn hex
  • và một bằng cách hợp nhất các biểu thức.

Một cổng của câu trả lời C ++ của CompuChip, có thể được giảm xuống còn 84 byte: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 byte

CÆ5¥ÐUXD e

Thử nó

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
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.