Сколько в пятницу 13 числа в году?

28

Ваша задача состоит в том, чтобы написать программу, в которой, учитывая год, выводится число «Пятница 13-е».

Правила и детали:

  • Вы можете получить ввод через STDINили в качестве аргумента, передаваемого вашей программе.
  • Вы должны вывести результат в STDOUT.
  • Вы можете предположить, что ввод будет действительным годом и не будет предшествовать григорианскому календарю (в этих случаях допускается неопределенное поведение).
  • Календарь / Дата библиотеки разрешены.

Это , поэтому выигрывает самый короткий код (в байтах).

(Связанная ссылка вызов)

Cruncher
источник
7
Каков требуемый диапазон ввода? Если это произойдет намного раньше 1800 года, какие предположения следует сделать при переходе с юлианского на григорианский календарь?
Питер Тейлор
@PeterTaylor Я не думал об этом. Если дата предшествует григорианскому, то вы можете иметь неопределенное поведение.
Cruncher
1
Первые страны, принявшие григорианский календарь, сделали это в октябре 1582 года, следуя за быком самого Григория. Страны, принявшие новый календарь с опозданием, не изменились до 20-го века, например, Греция представила его 1 марта 1923 года.
Джепп Стиг Нильсен
@JeppeStigNielsen Я не знаю много о календарях и тому подобном. Приняли ли они их или нет, это не меняет григорианские даты. Библиотеки должны быть в состоянии рассчитать даты по довольно далеко назад я полагаю?
Cruncher
3
Я думаю, что я здесь оффтоп. Многие библиотеки, написанные англо-американскими программистами, используют сентябрь 1752 года как «правильное» время смены календарей. Это было, когда Британская империя изменилась. Новый календарь был сохранен, когда США были основаны, конечно. (Любопытно, что в некоторых программах SQL минимальный год равен 1753, поскольку они не хотят справляться с проблемой сентября 1752 года.) Однако использование сентября 1752 года крайне англоцентрично. Вы правы, григорианские даты одинаковы независимо от того, использовались они исторически или нет. Это так называемый пролептический григорианский календарь.
Джепп Стиг Нильсен

Ответы:

3

APL (Dyalog АПЗ) с калом от 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 Я добавил пояснительную ссылку в заголовок. Если вы откроете ссылку TIO, вы увидите, что справа написано «29 символов, 29 байт (SBCS)», то есть набор однобайтовых символов.
Адам
Ну, я полагаю, это новый победитель. Является ли стандартная практика в этой SE, чтобы изменить принятый ответ так долго после вопроса?
Кранчер
@ Кранчер Да. И есть даже значки, чтобы получить признание после ОП.
Адам
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

DavidC
источник
Один персонаж короче:f=DayName@{#,m,6}~Table~{m,12}~Count~Friday&
Мистер Волшебник
@ Mr.Wizard Да. Меня удивляет, что Mathematica может анализировать несколько случаев инфиксной записи.
DavidC
Дэвид, меня удивляет , что ты не видел моего (чрезмерного) использования этой объединенной нотации. : ^) (Примеры: (1) , (2) )
Мистер Волшебник
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}}
histocrat
источник
5
сохранение одного символа, если вы посчитаете число пятниц 6-го
Джон Дворжак
2
@JanDvorak умный!
гистократ
почему 6? Я не получил это.
НАРКОЗ
3
Если 6-е - пятница, то 13-е - тоже пятница
TwiNight
Если 8-е - воскресенье, то 1-е - тоже, и вы можете использовать Time.gm(m,i).wday<1. Кроме того, я не знаю, почему вы называете эту функцию.
Ли W
8

Powershell, 68 63 58 52 50

Спасибо Иззи за отзыв.

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

Используя тот факт, что если 1-й день в месяце - воскресенье, 13-й будет пятница.

Я также попробовал:

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

но это не то же самое $argsвнутри блока скрипта.

Данко Дурбич
источник
1
Мне нравится идея использовать первый день месяца.
Cruncher
Хороший трюк, там. @ Не является необходимым, хотя.
Изи
Другое дело, хотя я виноват в том же во многих моих сценариях. Задача определяет, что входные данные могут быть получены из аргумента. Заменить $nс $argsв цикле, и вы можете обойтись без $n=read-host;полностью. Сохраняет 8. Удалите @, как упомянуто выше, и вы опуститесь до 54.
Iszi
Исправление: сводится к 52!
Изи
Попытка выяснить, почему ваш второй сценарий не будет работать, и я в растерянности. Что интересно, что я могу переодеться $argsдля $input, таким образом , подавая год в из трубопровода, и скрипт будет работать , но он всегда выводит 3.
Iszi
5

R 76 72 57

sum(format(as.Date(paste(scan(),1:12,1,sep="-")),"%w")<1)
flodel
источник
Можно легко получить это 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 Это довольно часто. Так как коды символов - это все числа. Даже 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:)

ejrb
источник
Действительно хорошее решение!
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'

Питон - 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
источник
Так как это мой первый гольф-сценарий для гольфа, я был бы признателен за любые подсказки по дальнейшей игре в гольф.
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]);}
user1354557
источник
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
Цифровая травма
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}
guy777
источник
а почему это -1?
Лукаш 'Severiaan' Grela
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: спасибо за советы !!!
guy777
3

К

64 персонажа

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

Читает со стандартного ввода

skeevey
источник
Хорошо, что здесь происходит? : P
Виллихам Тотланд
Читайте в году, составьте список дат 13-го числа каждого месяца, тестовый день недели = пятница, итоговый итоговый список логических значений
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-го.

Спасибо Данко Дурбичу за предложение >вместо ==.

Ками
источник
Вместо того 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. Воскресенье восьмое!
Джепп Стиг Нильсен
С 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
Titus
источник
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
tmartin
источник
1

Баш ( 52 47 символов)

for m in {1..12};do cal $m $Y;done|grep -c ^15
jerous
источник
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]
draegtun
источник
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
Цифровая травма
1
@DigitalTrauma Ты прав. В какой-то момент этот скрипт работал. позвольте мне исправить это.
Не то чтобы Чарльз
1
@DigitalTrauma похоже, что работала более длинная версия. спасибо за исправление!
Не то, что Чарльз
Интересно, что выражение без кавычек, которое я предложил, работает с 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.

Karol S
источник
Обидно new java.util.GregorianCalendarдолжно быть так долго :(
Cruncher
1

Python 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)
klingt.net
источник
В вашем первом примере диапазон должен быть (1,13), иначе вы пропустите 13 декабря в пятницу, как в 2013 году.
leancz
1
Ты даже не стал играть в гольф. Удалить некоторые из этих мест.
mbomb007
1

Perl 6, 55 53

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

Старый ответ:

{sum (1..12).map: {Date.new($_,$^a,13).day-of-week==5}}
bb94
источник
48 байтов
Джо Кинг
0

Python (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
leancz
источник
0

Perl + lib POSIX 55

С идеей не ищет , 13thно первый, и , как sundayэто 0это пусть экономия 3 символов! Спасибо @ Iszi и Данко Дурбич!

$==$_;$_=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

aka.nice
источник
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
CompuChip
источник
Я считаю 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.
Carcigenicate
источник
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 в целое число,
  • еще один, используя шестнадцатеричное представление,
  • и один путем слияния выражений.
Titus
источник
Порт ответа 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
мохнатый
источник