Скільки п'ятниці 13 за рік?


28

Ваше завдання полягає в тому, щоб написати програму, яка, враховуючи рік, видає в ній число "П’ятниця 13-го".

Правила та подробиці:

  • Ви можете взяти вхід через STDINабо як аргумент, переданий вашій програмі.
  • Вам слід вивести результат STDOUT.
  • Ви можете припустити, що введення буде дійсним роком, але не має дату григоріанського календаря (невизначена поведінка дозволена в цих випадках).
  • Бібліотеки календарів / дат дозволені.

Це , тому найкоротший код (у байтах) виграє.

(Пов'язане посилання на виклик)


7
Який необхідний діапазон введення? Якщо це відбудеться значно до 1800 року, то які припущення слід зробити про перехід з юліанського на григоріанський календар?
Пітер Тейлор

@PeterTaylor Я не думав про це. Якщо побачення заздалегідь григоріанське, то у вас може бути невизначена поведінка.
Cruncher

1
Перші країни, які прийняли григоріанський календар, зробили це в жовтні 1582 року, слідуючи за биком Григорія. Країни, які прийняли новий календар пізно, змінилися до 20 століття, наприклад, Греція представила його 1 березня 1923 року.
Джеппе Стіг Нільсен

@JeppeStigNielsen Я мало знаю про календарі та подібні. Прийняли вони їх чи ні, це не змінює, якими є григоріанські дати. Бібліотеки повинні мати можливість обчислювати дати з цілком можливих способів назад?
Cruncher

3
Я думаю, що я тут перебуваю в офтопіку. У багатьох бібліотеках, написаних англо-американськими програмістами, вересень 1752 р. Використовується як "правильний" час зміни календарів. Це було, коли змінилася Британська імперія. Новий календар зберігався, звичайно, із заснуванням США. (Як цікавість, деяке програмне забезпечення SQL має 1753 рік як мінімальний рік, оскільки вони не хочуть впоратися з проблемою вересня 1752 року.) Однак використання вересня 1752 р. Є надзвичайно англоцентричним. Ви маєте рацію. Григоріанські дати однакові, використовувались вони історично чи ні. Це так званий пролептичний григоріанський календар.
Jeppe Stig Nielsen

Відповіді:


3

APL (Dyalog APL) з cal від dfns , 29 байт

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

Спробуйте в Інтернеті!

⍳ 12 цілі числа один через дванадцять

⎕ ,¨ візьміть числовий ввід і додайте до кожного з дванадцяти чисел

{ На кожній з пар застосуйте функцію…

cal⍵ отримати календар на той рік-місяць

2 ↓ опустити два ряди (підпис і дні)

 транспонировать (щоб ми могли адресувати стовпці замість рядків)

¯5 ↑ візьміть останні п'ять (дві цифри на кожну п'ятницю та суботу плюс один пробіл)

3 ↑ візьміть перші два (дві цифри за п’ятницю плюс пробіл)

 перенести (так ми отримуємо порядок читання)

, хитатися

 виконати як вираз APL (дає список дат п’ятниці)

13 ∊ тринадцять є членом цього списку?

+/ суму 12 булів


Використовуючи алгоритм @ 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)" праворуч, тобто набір символів однобайтових.
Адам

Ну, мабуть, це новий переможець, чи є стандартною практикою в цій ДП змінити прийняту відповідь на це довгий час після питання?
Cruncher

@Cruncher Так. І навіть існують значки для прийняття через ДП.
Adám

12

Математика 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
заощадження, якщо рахувати числа п'ятниць 6-го
Джон Дворак

2
@JanDvorak розумний!
гістократ

чому 6? Я цього не зрозумів.
НАРКОЗ

3
Якщо 6-й - це п'ятниця, то 13-й - це також п’ятниця
TwiNight

Якщо 8-а - це неділя, то 1-й - це так само, і ви можете використовувати Time.gm(m,i).wday<1. Крім того, я не знаю, чому ви називаєте функцію.
Lee W

8

Powershell, 68 63 58 52 50

Дякую Ізі ​​за пораду.

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

Використовуючи той факт, що якщо перший день у місяці - неділя, 13 числа буде п’ятницею.

Я також спробував:

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

але $argsвсередині блоку скриптів це не те саме .


1
Мені подобається ідея використання першого дня місяця.
Cruncher

Гарний трюк, є. Хоча @ є непотрібним.
Іссі

Інша річ, хоча я винен у тому ж у багатьох своїх сценаріях. У виклику вказується, що вхід може виходити з аргументу. Замінити $nз $argsв циклі, і ви можете обійтися без $n=read-host;повністю. Заощаджує 8. Видаліть @, як згадувалося вище, і ви знизилися до 54.
Ізі

Виправлення: знижується до 52!
Іссі

Намагаючись розібратися, чому ваш другий сценарій не працюватиме, і я розгублений. Що цікаво, що я можу переодягнутися $argsдля $input, таким чином , подаючи рік в з трубопроводу, і скрипт буде працювати , але він завжди виводить 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")допомогою Дау як число, і видалення пробілів.
chmullig

цінується!
флодель

+1 Хоча робити seqєдиний місяць тут насправді коротше! sum(format(as.Date(paste(scan(),1:12,13,sep="-")),"%w%d")=="513")всього 65 символів!
планнапус

Нічого б я не здогадувався, що <примусить персонаж до цілого числа. Гарний трюк!
планнапус

@plannapus Це досить часто. Оскільки символьні коди - це всі числа. Навіть java може порівнювати 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
Ви можете зберегти char, виконавшиfrom datetime import*
user80551

Приємно! Я закінчив щось фактично ідентичне, але уникаючи exec: f=lambda y:sum([date(y,m,13).weekday()==4 for m in range(1,13)]).... Однак однаковий розмір рішення з імпортом (86 байт).
iwaseatenbyagrue

5

Не використовуючи жодних бібліотек або вбудованих функцій дати:

Гольфскрипт - 51

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

' [3/=RI[)a%:*.' могла б бути 'feefefgeeffgfe'

Пітон - 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)підсумовує зрушення останнього дня (один у звичайному році, два у високосний рік).


Оскільки це мій перший гольф-скрипт, я вдячний за будь-які підказки щодо подальшого гольфу.
Wrzlprmft

Я замислювався над таким рішенням, використовуючи той факт, що насправді існує лише 14 унікальних років, але не був впевнений, найкраща мова, щоб зробити його конкурентоспроможним. Я думаю, що це найкоротша відповідь, коли немає бібліотек. Якщо високосні роки були рівномірно кожні 4 роки, ви могли б перемогти з цим
Cruncher

4

С 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-річним циклом.
Пітер Тейлор

1
Більш явно (і більше), C #: static char GetNumberOfFriday13s(int year) { const string perpetualCalendar = "1221212213113213122221122131122121221311321312222112213112212122131132131222211221311221212213113213112213113213122221122131122121221311321312222112213112212122131132131222211221311221212213113213122213113213122221122131122121221311321312222112213112212122131132131222211221311221212213113213122221122213122221122131122121221311321312222112213112212122131132131222211221311221212213113213122221122131"; return perpetualCalendar[year % 400];. Не буде працювати негативні роки.
Джеппе Стіг Нільсен

Симпатичний! Як маленький клоп, 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 символів)
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 символів)

Мені швидше сподобалося рішення Вілліхама Тотленда та його використання стиснення. Я виправив дві маленькі помилки і змінив код, щоб скоротити його довжину:

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 символів, використовуючи seqзапуск за замовчуванням до 1.

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

Є чи це мовної стандарт залежить, сі , якщо вона не працює, ви , можливо , доведеться

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

Це, мабуть, залежить від локальності.
Пітер Тейлор

Так, це засновано на замовчуванні C. Але є помилка ...
Ф. Хаурі

Збережіть діаграму, відмінивши рядок формату printf та вимкнувши \ замість:%s\\n
Digital Trauma

1
Або скористайтеся seqдля скидання 8 символів:date -f<(seq -f$1-%g-6 1 12)|grep -c ^F
Digital Trauma

1
Насправді ви можете поголити ще два коси. Якщо ви опустите початковий номер послідовності, 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
Виглядає добре! Ви можете заощадити ще кілька байт, видаливши ,b,cз оголошення функції (! Це нормально текти вари для гри в гольф), а також , як bвідливають як Numberви можете +=результат тесту замість &&b++: b+=/^F/.test(new Date(a,c,6)). Однак ви можете зберегти інший байт, використовуючи !new Date(a,c,1).getDay()(це працює, тому що getDayповертається 0 за неділю, а якщо 13-а - п’ятниця, 1-й буде неділя), замість цього в testцілому ви повинні заощадити 7 байт!
Дом Гастінгс

@DomHastings: THX за ваші поради !!!
guy777

3

к

64 символи

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

Читає від stdin


Гаразд, тільки що тут відбувається? : P
Вілліхам Тотланд

Прочитайте рік, складіть список дат 13-го числа кожного місяця, день тестування тижня = п’ятниця, підсумовуйте список
булів

3

Лист звичайний (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))))))

О боже, я ніколи не міг прочитати lisp ..
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);}

Дякую Джеппе Стігу Нільсену за linq та пропозицію перевірити в неділю 8-го.

Дякую Данко Дурбіч за те, що він запропонував >замість цього ==.


Замість цього 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

З Linq : int g(int y){return Enumerable.Range(1,12).Count(m=>new DateTime(y,m,8).DayOfWeek==0);}. Звичайно, як лямбда це y=>Enumerable.Range(1,12).Count(m=>new DateTime(y,m,8).DayOfWeek==0).
Джеппе Стіг Нільсен

Ви можете зберегти один символ, порівнюючи .DayOfWeek<1.
Данько Дурбич

@ DankoDurbić Це може стосуватися c#відповіді, але не впевнений, як її застосувати linq.
Камі

Моя помилка; мабуть, ви не можете порівняти DayOfWeekжодне інше ціле число, ніж 0- error CS0019: Operator '<' cannot be applied to operands of type 'System.DayOfWeek' and 'int'.
Данько Дурбич

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

К, 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

Ребол, 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

Баш і Сед, 39

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

ncal друкує календар на даний рік із днями тижня вліво.

sedз /gпрапором виділяються всі 13 з новими рядками

grep -c підраховує рядки, які починаються з "2" (20 завжди слід 13)

Дякуємо @DigitalTrauma, що знайшов помилку в моїй старій версії та запропонував рішення!


Мені не зовсім підходить - рядки в п’ятницю друкуються лише один раз, навіть якщо вони містять більше одного 13.
Digital Trauma

1
Я думаю, що найкраще, що я можу зробити з подібним чином, це 38:ncal $1|sed /F/s/13/\\n/g|grep -c ^\ 2
Digital Trauma

1
@DigitalTrauma Ви маєте рацію. У якийсь момент цей сценарій спрацював. дозвольте це виправити.
Не те, що Чарльз

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 = 7і FRIDAY = 6.

Версія з 68 символів:

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

Так, Java змінила значення констант дня тижня між API.


Прикро new java.util.GregorianCalendarмає бути таким довгим :(
Cruncher

1

Пітон 195/204

Працює лише попередні роки, тому що monthdatescalendarповертає календар на даний рік до цих пір . Я думаю, що залишилось багато оптимізуючого потенціалу :).

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)

Ще одне рішення, що працює на кожну дату, але воно не менше:

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)

У вашому першому прикладі діапазон повинен бути (1,13), інакше ви пропустите 13 грудня в п'ятницю, як у 2013 році.
leancz

1
Ви навіть не займалися гольфом. Видаліть деякі з цих пробілів.
mbomb007


0

Пітон (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

З ідеєю не шукає , 13thале перший, і , як sundayце 0це нехай економія 3 символів! Дякую @ Ізі та Данко Дурбіч!

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

Чи можна було обчислити 2010-2017 рр. (Для вибірки) таким чином:

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

(Гаразд, немає нового рядка , але про це не запитували;)

Старий пост: 63

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

Дія:

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

У Smalltalk (аромат Squeak / Pharo) реалізуйте цей метод у Integer ( 86 символів)

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

Потім використовувати його як це: 2014countFriday13.

Звичайно, ми могли б використовувати коротшу назву, але тоді це не буде Smalltalk


0

C ++ - Забагато байтів :(

Я спробував рішення, яке не використовує жодної бібліотеки дат.

Я знайшов досить класне (якщо можна так сказати і сам) рішення. На жаль, я не можу отримати його коротше, ніж це, що насправді клопоче мене, бо відчувається, що має бути кращий шлях.

Рішення залежить від цього алгоритму, який становить лише 44 байти. На жаль, мені потрібно ще 100 байт, щоб красиво обернути це ...

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

Виводиться через код повернення (в C ++, використовуючи coutабо printfщось подібне, потрібен інший #include, що ще більше підірве рішення).

Програма драйвера / тесту:

# 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

Вихід програми драйвера:

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

Я рахую 88 за алгоритм, а не 44. Що таке алгоритм і що таке перекручування? ($m<3?$y--:$y-2)+3замість цього d=13,, d+=m<3?y--:y-2,і d+4повинен працювати так само, і багато економить. +5замість +3і -5теж повинен працювати і економить 2 байти. for(m=0;++m<13;)зберігає один байт. Перехід m=0до функції функції зберігає ще один байт; а переміщення ()%7||++fдо петлевої головки економить ще одну. Вниз від 149 до 136 байт.
Тит

0

Clojure, 207 187 байт

-20 байт, позбувшись importпробілу, і деякий пробіл, який я пропустив.

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

Починаючи з 1-го року в Джанауарі, вона перетинає кожен день. Якщо день п'ятниця 13-го, він збільшує кількість. Він продовжує циклічно, поки не досягне наступного року.

(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, без вбудованих файлів, 81 байт

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

Бігайте з echo <year> | php -nR '<code>'.

зламатися

Будні повторюються кожні 400 років.
У підсумках за 1600 - 1999 рр. (Наприклад) існує 28-тривалий період із трьома прогалинами:

  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

Відкоригувавши рік для цих прогалин, ми можемо отримати результат простим хешем:

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

Не коротка (95 байт), але гарна. І ми можемо займатися гольфом

  • 4 байти, використовуючи потрійну ланцюг для зміщення,
  • 8 байт шляхом перетворення хеш-карти з рядка base4 в ціле число,
  • ще один за допомогою шестигранного представлення,
  • і один шляхом злиття виразів.

Порт відповіді CompuChip C ++ можна збільшити до 84 байтів:for(;++$m<13;23*$m/9+($m<3?$y--:$y-2)+5+$y/4-$y/100+$y/400)%7?:$f++)$y=$argn;echo$f;
Тит

0

Japt -x , 10 байт

CÆ5¥ÐUXD e

Спробуй це

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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.