Задача умножения даты

19

(Вдохновленный Riddler на прошлой неделе на FiveThirtyEight.com. Песочница сообщение .)

Учитывая год между 2001 и 2099 годами, вычислите и верните число дней в этом календарном году, где mm * dd = yy(где yyэто год из двух цифр ).

2018, например, имеет 5:

  • 18 января (1 * 18 = 18)
  • 9 февраля (2 * 9 = 18)
  • 6 марта (3 * 6 = 18)
  • 3 июня (6 * 3 = 18)
  • 2 сентября (9 * 2 = 18)

Ввод может быть 2 или 4-значным числовым годом.

Вывод должен быть целым числом. Дополнительное место в конце или возврат в порядке.

Полный список ввода / вывода:

Input = Output
 2001 = 1     2021 = 3     2041 = 0     2061 = 0     2081 = 2
 2002 = 2     2022 = 3     2042 = 4     2062 = 0     2082 = 0
 2003 = 2     2023 = 1     2043 = 0     2063 = 3     2083 = 0
 2004 = 3     2024 = 7     2044 = 3     2064 = 2     2084 = 5
 2005 = 2     2025 = 2     2045 = 3     2065 = 1     2085 = 1
 2006 = 4     2026 = 2     2046 = 1     2066 = 3     2086 = 0
 2007 = 2     2027 = 3     2047 = 0     2067 = 0     2087 = 1
 2008 = 4     2028 = 4     2048 = 6     2068 = 1     2088 = 3
 2009 = 3     2029 = 1     2049 = 1     2069 = 1     2089 = 0
 2010 = 4     2030 = 6     2050 = 3     2070 = 3     2090 = 5
 2011 = 2     2031 = 1     2051 = 1     2071 = 0     2091 = 1
 2012 = 6     2032 = 3     2052 = 2     2072 = 6     2092 = 1
 2013 = 1     2033 = 2     2053 = 0     2073 = 0     2093 = 1
 2014 = 3     2034 = 1     2054 = 4     2074 = 0     2094 = 0
 2015 = 3     2035 = 2     2055 = 2     2075 = 2     2095 = 1
 2016 = 4     2036 = 6     2056 = 4     2076 = 1     2096 = 4
 2017 = 1     2037 = 0     2057 = 1     2077 = 2     2097 = 0
 2018 = 5     2038 = 1     2058 = 0     2078 = 2     2098 = 1
 2019 = 1     2039 = 1     2059 = 0     2079 = 0     2099 = 2
 2020 = 5     2040 = 5     2060 = 6     2080 = 4

Это испытание , выигрывает наименьшее количество байтов на каждом языке.

Предварительный расчет и простой поиск ответов обычно исключаются в соответствии с нашими правилами лазейки , но я явно разрешаю это для этой задачи. Это позволяет для некоторых интересных альтернативных стратегий, хотя его не вероятно, 98 99-элемента списка поиска будет коротким.

BradC
источник
Если вам будет легче на вашем языке, ответ будет одинаковым независимо от века; 1924 и 2124 имеют то же количество дней, что и 2024.
BradC
если результат mm * dd больше 100, он автоматически фильтруется?
DanielIndie
@DanielIndie Правильно, никакие даты не должны учитываться. Другими словами, 12 декабря 2044 года не считается, даже если 12 * 12 = 144.
BradC
Поскольку нам нужно обрабатывать только ограниченное количество входных данных, я отредактировал их все. Не стесняйтесь откатывать или переформатировать.
лохматый
1
@gwaugh Просто вы можете решить, какой из них принять в качестве действительного ввода (чтобы вам не пришлось тратить лишние символы на преобразование между ними).
BradC

Ответы:

14

Excel, 48 байт

Ура! Наконец-то Excel действительно хорош.

=COUNT(VALUE(ROW(1:12)&"/"&A1/ROW(1:12)&"/"&A1))

Принимает входные данные от A1 в виде целого числа 1-99, представляющего год, и выводит туда, где вы вводите эту формулу. Это формула массива, поэтому используйте Ctrl-Shift-Enter вместо Enter, чтобы ввести ее.

При этом используется тот факт, что COUNTошибки игнорируются, поэтому любые ошибки, вызванные либо месяцем, не делящим год (приводят к тому, что Excel анализирует что-то вроде2/12.5/25 либо датой, которая недействительна, например 2/29/58, просто игнорируются.

София Лехнер
источник
1
Очень хорошо. Вероятно, стоит упомянуть, что требуется год с двумя цифрами A1. Ввод 4-значного года просто возвращает 0.
BradC
Правда! Я отредактирую это в описании.
София Лехнер
Также я должен отметить, что это зависит от региона; это зависит от наличия локали, в которой используется порядок мм / дд / гг. В локали с порядком дд / мм / гг ответ, конечно, будет таким же числом байтов.
София Лечнер
1
Супер умный; Мне нравится, как вы тестируете только 12 кандидатов на свидания (по одному в месяц) вместо того, чтобы проходить каждый день года.
BradC
Зафиксируйте год для одного скачка сохраненного байта?
l4m2
6

Python 2 , 44 байта

[k/32%13*(k%32)for k in range(96,509)].count

Попробуйте онлайн!

Анонимная функция, заданная как объект метода. Производит все продукты(month, day) пара , (m, d)как кодируются k=32*m+dс 0≤m≤12, 0≤d≤31и упаковкой вокруг. Исключает 29-31 февраля, исключая их из диапазона.

XNOR
источник
5

Ява (JDK 10) , 65 байт

y->{int m=13,c=0;for(;m-->1;)if(y%m<1&y/m<29+m%2*3)c++;return c;}

Попробуйте онлайн!

кредиты

Оливье Грегуар
источник
Не подходит високосный год 29*n, поэтому не нужно проверять
l4m2
Спасибо за ваш вклад. Я мог бы удалить всего 27 байт с кучей других изменений.
Оливье Грегуар
1
Переход (m==2?29:32)на 29+m%2*3все еще, кажется, дает все OKрезультаты. Кредит @AsoneTuhid рубинового ответ «s .
Кевин Круйссен
4

PowerShell , 94 байта

param($a)for($x=Date 1/1/$a;$x-le(Date 12/9/$a);$x=$x.AddDays(1)){$z+=$x.Month*$x.Day-eq$a};$z

Попробуйте онлайн!

Принимает ввод в виде двузначного года, затем строит forцикл из 1/1/yearв 12/9/year(потому что 12/10 и далее никогда не будут учитываться, и это сохранит байт). Каждую итерацию мы увеличиваем, $zесли .Monthвремя .Dayравно нашему входному году. Вне петли,$z остается на конвейере и вывод неявный.

Редактировать - это зависит от культуры. Приведенный выше код работает для en-us. Формат даты может потребоваться изменить для других культур.

AdmBorkBork
источник
2
«культура»? Вы имели в виду "локаль"? ...
user202729
1
@ user202729 В разговорной речи да, но в документации PowerShell это называется «культура».
AdmBorkBork
«Культура» - это слово, которое MS обычно использует для обозначения языка, например. System.Globalization.CultureInfo в .NET.
sundar - Восстановить Монику
3

JavaScript (ES6), 91 байт

Мне было любопытно узнать, как жесткое кодирование можно сравнить с итеративным вычислением. Это определенно дольше (см . Ответ @ Shaggy ), но не намного дольше.

Редактировать : Однако, это намного длиннее, чем более прямая формула (см. Ответ @ l4m2 ).

Принимает ввод как целое число в [1..99] .

n=>(k=parseInt('8ijkskercdtbnqcejh6954r1eb2kc06oa3936gh2k0d83d984h'[n>>1],36),n&1?k>>3:k&7)

Попробуйте онлайн!

Как?

Нечетные годы имеют значительно меньше шансов на мм * дд = гг, чем четные годы. Конкретнее, нечетные годы имеют от 0 до 3 совпадений, а четные годы - от 0 до 7 совпадений. Это позволяет нам кодировать каждую пару лет всего 5 битами, которые удобно представлять в виде одного символа в базе 36.

Arnauld
источник
3

Утилиты Bash + GNU , 57

  • 1 байт сохранен благодаря @SophiaLechner
seq -f1/1/$1+%gday 0 365|date -f- +%m*%d-%y|bc|grep -c ^0

Обратите внимание, что seq команда всегда создает список из 366 дат - для не високосных лет будет включен 1 января следующего года. Однако в диапазоне дат 2001..2099 MM * DD никогда не будет YY на 1 января следующего года для любого из этих лет, поэтому этот дополнительный день не повлияет на результат.

Попробуйте онлайн!

Цифровая травма
источник
Очень хорошо - я даже не знал, dateбудет ли на этом математике встречаться при разборе. seqпосле него не требуется пробел -f, поэтому вы можете сохранить байт там.
София Лехнер,
3

T-SQL, 123 121 байт

Согласно нашим правилам ввода- вывода , ввод осуществляется через существующую таблицу t с целочисленным полем y , которое содержит год из двух цифр.

WITH c AS(SELECT 1m UNION ALL SELECT m+1FROM c WHERE m<12)
SELECT SUM(ISDATE(CONCAT(m,'/',y/m,'/',y)))FROM c,t WHERE y%m=0

Разрыв строки предназначен только для удобства чтения. В значительной степени вдохновлено решением Sophia's Excel .

  • Верхняя строка генерирует таблицу номеров из 12 элементов c, которая присоединяется к входной таблице t .
  • Если это проходит, я собираю воедино кандидата в даты CONCAT(), что делает неявные varcharпреобразования типов данных. В противном случае я должен был бы сделать кучу CASTили CONVERTзаявлений.
  • Найдена идеальная функция оценки ISDATE(), которая возвращает 1 для действительных дат и 0 для недействительных дат.
  • Оберните это в СУММУ, и я готов.
  • РЕДАКТИРОВАТЬ : переместил проверку целочисленного деления ( y%m=0) вWHERE переместил предложение, чтобы сохранить 2 байта, спасибо @RazvanSocol.

К сожалению, он не намного короче версии таблицы поиска (используя строку из версии osdavison ):

Поиск T-SQL, 129 байт

SELECT SUBSTRING('122324243426133415153317223416132126011504033106131204241006003213011306002122042005101305111014012',y,1)FROM t

РЕДАКТИРОВАТЬ : Оставляя мой оригинал выше, но мы можем сохранить несколько байтов, используя несколько новых функций:

  • STRING_SPLIT доступно в MS SQL 2016 и выше.
  • CONCAT_WS доступно в MS SQL 2017 и выше.
  • Как указано выше, заменено IIFнаWHERE

MS-SQL 2017, 121 118 байт

SELECT SUM(ISDATE(CONCAT_WS('/',value,y/value,y)))
FROM t,STRING_SPLIT('1-2-3-4-5-6-7-8-9-10-11-12','-')
WHERE y%value=0

MS-SQL 2017, дополнительная читерская версия: 109 байт

SELECT SUM(ISDATE(CONCAT_WS('/',number,y/number,y)))
FROM t,spt_values WHERE number>0AND y%number=0AND'P'=TYPE

Требует, чтобы вы были в masterбазе данных, которая содержит системную таблицу, spt_valuesкоторая (при фильтрации TYPE='P') дает вам счетные числа от 0 до 2048.

BradC
источник
Как и в других ответах, порядок, в котором я собираю дату ( m/d/y), зависит от настроек локальности экземпляра SQL. В других местах может потребоваться другой порядок или другой разделитель, но я не думаю, что это повлияет на длину кода.
BradC
Я думаю, вы поняли, что преобразование «29.0264» в дату дает 1964-02-29 (не 2064-02-29), но, учитывая, что 2000 и 2100 годы исключены, это хороший способ сократить время код.
Разван Соколь
Использование SPLIT_STRINGвместо CTE сокращает его до 120 байтов. Использование CONCAT_WSвместо CONCATсохранения другого символа, получая его до 119 байт.
Разван Соколь
@RazvanSocol Да, я не уверен, где разрыв между 2-значными датами, которые соответствуют 19xx против 20xx, но оба дают одинаковый ответ. Я попробую два других предложения, спасибо!
BradC
1
Заменить IIFна WHERE.
Разван Соколь
3

Юлия 0,6 , 49 44 42 байта

y->sum(y/i1:28+3(i%2i÷8)for i=1:12)

Попробуйте онлайн!

-5 байт, вдохновленный ответом Руби Асоне Тухида.
-2 байта, заменяющих счет суммой

Объяснение:

Для каждого месяца iот 1 до 12 рассчитайте y/iи проверьте, не является ли это одним из дней этого месяца. Месяцы с 31 днем ​​составляют 1, 3, 5, 7, 8, 10, 12 - поэтому они нечетные ниже 8 и даже на и выше 8. Так что либо i%2или i÷8(что равно 0 для i <8 и 1 для i> = 8 здесь) должно быть 1, но не оба - поэтому мы их XOR. Если результат xor равен true, мы проверяем даты, 1:28+3т. 1:31Е. В противном случае мы проверяем только даты 1:28.

1:28достаточно для остальных месяцев (это улучшение, вдохновленное ответом Асоне Тухида на Ruby ), потому что:

  • на февраль единственная возможность была бы 2*29 = 58, но2058 это не високосный год, поэтому мы можем предположить, что в феврале всегда 28 дней.

  • другие месяцы с 30 днями - это месяц 4 и выше, для которого i*29i*30) будет больше 100, что можно игнорировать.

Наконец, мы подсчитываем, сколько раз y/iпринадлежит этому списку дней (используя sumздесь логическое значение ), и возвращаем это.

sundar - Восстановить Монику
источник
3

JavaScript 91 85 82 81 77 байт

Принимает ввод в виде двухзначной строки (или целого числа из 1 или 2 цифр).

Использует тот факт, что new Dateбудет перенесен на следующий месяц, и продолжит делать это, если вы передадите ему значение дня, которое превышает число дней в месяце, которое вы ему передаете, так что на первой итерации он пытается построить Датаyyyy-01-345 которая становится yyyy-12-11, или yyyy-12-10високосные годы. Нам не нужно проверять даты после этого, в 12*11+результате получается трехзначное число.

y=>(g=d=>d&&([,M,D]=new Date(y,0,d).toJSON().split(/\D/),D*M==y)+g(--d))(345)

3 байта сохранены благодаря Арно .


Проверь это

f=
y=>(g=d=>d&&([,M,D]=new Date(y,0,d).toJSON().split(/\D/),D*M==y)+g(--d))(345)
o.innerText=[...Array(99)].map((_,x)=>(2001+x++)+` = `+f(x)).join`\n`
pre{column-count:5;width:480px;}
<pre id=o></pre>

мохнатый
источник
2

Excel, 83 байта

{=SUM(IF(MONTH(DATE(A1,1,0)+ROW(1:366))*DAY(DATE(A1,1,0)+ROW(1:366))=A1-2000,1,0))}

Вход в ячейку A1в формате yyyy. Это формула массива, которая вводится с помощью Ctrl+ Shift+, Enterчтобы получить фигурные скобки {}. Это довольно просто и без какой-либо хитрости.

Когда в формуле массива, DATE(A1,1,0)+ROW(1:366)дает нам массив из 366 значений даты. В не високосные годы это будет включать 1 января следующего года, но это не является проблемой, поскольку 1*1=1будет считаться ложноположительным, если следующий год, 2001но, поскольку требуемый диапазон2001 - 2099 , он никогда не возникнет как вопрос.

Если вы укоренили этот бит в просто ~, формулу, потому что гораздо проще следовать:

{=SUM(IF(MONTH(~)*DAY(~)=A1-2000,1,0))}

Я попытался использовать COUNTIF()вместо, SUM(IF())но Excel даже не позволил бы мне ввести его в качестве формулы массива, а тем более дать мне результат. Я сделал найти Google Sheets решения , используя , CountIf()но один и тот же метод , в противном случае , что оказалось 91 байт, в основном потому , что он использует ArrayFormula()вместо того , чтобы просто { }.

=CountIf(ArrayFormula(Month(Date(A1,1,0)+Row(1:366))*Day(Date(A1,1,0)+Row(1:366))),A1-2000)
Инженер Тост
источник
Я не видел консенсуса, но я обычно не включал внешние фигурные скобки в мои байты для Excel. Они больше похожи на способ форматирования отображения в Excel, чем на часть формулы. Мнения?
София Лехнер
@SophiaLechner Я включил их вместо того, чтобы решить, как включить дополнительные нажатия клавиш, необходимые для его ввода в качестве формулы массива. Есть мета-вопрос об этом, и единственный ответ говорит, что команда CTRL + ALT + ENTER будет считаться одним нажатием клавиши. Если вы используете то же самое, что и vim ( для мета ), то это нажатие клавиши будет считаться как 1 байт. Тем не менее, я обычно не считаю ENTER в конце ввода формулы как 1 байт в других ответах.
Инженер Тост
2

Сетчатка 0.8.2 , 55 байт

..
$*
(?<=^(1{1,12}))(?=(?(?<=^11$)\1{0,27}|\1{0,30})$)

Попробуйте онлайн! Занимает год с двумя цифрами; добавить 1 байт для поддержки 4-значных лет. Пояснение: Первый этап просто превращается в унарный. Второй этап начинается с сопоставления от 1 до 12 символов перед позицией совпадения, представляющих месяц, а затем попытается просмотреть целое число повторений этого месяца. Тем не менее, просмотр содержит условное условие, которое выбирает до 27 или 30 повторений в зависимости от месяца. Подсчет совпадений позиций является желаемым результатом.

Нил
источник
2

R , 22 122 байта

x=scan();substr("122324243426133415153317223416132126011504033106131204241006003213011306002122042005101305111014012",x,x)

Попробуйте онлайн!

Решил пойти с подходом таблицы поиска. Год ввода должен состоять из 2 цифр.

Роберт С.
источник
1
Также на TIO вы можете нажать кнопку «ссылка», и она автоматически отформатирует ответ для вас. Спасибо Деннису за настройку!
Джузеппе
Вы можете удалить начальные значения if, так как ввод может быть либо 2-значным, либо 4-значным по вашему выбору (так что вы можете принять только 2-значный ввод). Но похоже, что код считает, что каждый месяц содержит 31 день, поэтому, например, 62 (для 2062) возвращает 1, где он должен возвращать 0.
sundar - Восстановить Монику
2
Я неправильно понял. При этом, я почти уверен, что таблица поиска должна быть включена в число байтов.
НГМ
@ngm Я также не был уверен, нужно ли включать таблицу поиска, но я добавлю ее в число байтов, чтобы быть в безопасности.
Роберт С.
Я до сих пор не уверен, что все правила!
нгм
2

J , 29 байт

1#.(,x*i."+29+3*2~:x=.i.13)=]

Попробуйте онлайн!

Как это устроено

1#.(,x*i."+29+3*2~:x=.i.13)=]    Input: year (2-digit, 1..99)
                   x=.i.13       array of 0..12; assign to x
                2~:              1 1 0 1 .. 1
              3*                 3 3 0 3 .. 3
           29+                   32 32 29 32 .. 32
       i."+                      for each item of above, generate a row 0 .. n
    ,x*                          each row times 0 .. 12 and flatten
                           =]    1 for each item == input, 0 otherwise
1#.                              sum

Пытался изо всех сил получить под 2 раза раствор желе :)

Примечание

Если кто-то действительно хочет жестко закодировать 99-значные данные, вот немного информации:

Разделите 99-значный на куски по 2 цифры. Тогда первая цифра <4и вторая <8, что означает, что пять битов могут кодировать два числа. Затем все данные могут быть закодированы в 250 бит или 32 байта.

фонтанчик для питья
источник
2

Питон 3 , 158 162 215 241 байт

Удалено 4 Спасибо Стивену за игру в гольф.

Удалено 53 спасибо Стивену за указание на пустое пространство

Удалено 26 благодаря ссылке, предоставленной caird

Я довольно новичок в этом. Не мог придумать, как это сделать, не описывая дни месяца.

r=range
def n(Y):
 a,b,c=31,30,0
 for x in r(12):
  for y in r([a,(28if Y%4else 29),a,b,a,b,a,a,b,a,b,a][x]):
   if(x+1)*(y+1)==int(str(Y)[2:]):c+=1
 return c

Попробуйте онлайн!

akozi
источник
5
Добро пожаловать на сайт и приятного первого поста! Есть несколько способов
сыграть в
@cairdcoinheringaahing Спасибо за совет, ссылка была очень полезной!
Акози
1
158 байт - играли в гольф, но в основном у вас была большая длинная линия пробелов на третьей линии, не знаю, как они туда попали
Стивен
@ Stefhen Спасибо :) Я добавил ваши два изменения. Один для пустого пространства, а другой для игры в гольф.
Акози
(28if Y%4else 29)можно сократить до [29,28][Y%4>0]. Кроме того, длинный список может быть сокращен до [a,...]+2*[a,b,a,b,a]. a,b,cможно добавить в список параметров, чтобы сохранить строку. int(str(Y)[2:])можно сократить до Y%100. Наконец, переменные счетчика в большинстве случаев можно сократить до lens списков, это также позволяет nсделать a lambda. Это составляет 118 .
Черная сова Кай
2

Forth (gforth) , 60 59 байтов

: f 0 13 1 do over i /mod swap 32 i 2 = 3 * + 0 d< - loop ;

Попробуйте онлайн!

Эта версия использует тот факт, что не может быть более одного совпадающего дня в месяц и что год должен делиться на месяц, чтобы соответствовать.

объяснение

Повторяется по месяцам, проверяет, делится ли год на месяц, и если частное составляет <31 (28 на февраль). Месяцы после марта не могут совпадать для дней больше 25, поэтому мы можем просто предположить, что все месяцы (кроме февраля) есть 31 день для цели головоломки.

Код Объяснение

: f                   \ start new word definition
  0                   \ set up counter
  13 1 do             \ start a counted loop from 1 to 12
    over i /mod       \ get the quotient and remainder of dividing year by month
    swap              \ default order is remainder-quotient, but we want to swap them
    32 i 2= 3 * +     \ we want to compare to 32 days unless month is Feb
    0 d<=             \ treat the 4 numbers on the stack as 2 double-length numbers
                      \ and compare [1]
    -                 \ subtract result from counter (-1 is true in Forth)
  loop                \ end loop
;                     \ end word definition    

[1] - Forth имеет концепцию чисел двойной длины, которые хранятся в стеке как два числа одинарной длины (в форме xy, где значение double = y * 2^(l) + x где l - размер в битах одиночного числа в четвертая реализация, с которой вы работаете).

В этом случае я сравнил частное и остаток с 32 (или 29) 0. Если остаток был больше 0 (год не делится на месяц), первый дубль будет автоматически больше 32 (или 29) 0 и результат было бы ложным. Если остаток равен 0, то он эффективно разрешает регулярную проверку фактора <= 32 (или 29)

Forth (gforth) , 61 байт

: f 0 13 1 do i 2 = 3 * 32 + 1 do over i j * = - loop loop ; 

Попробуйте онлайн!

Сэкономили несколько байтов, поняв, что только февраль имеет значение с точки зрения правильного количества дней в месяце

объяснение

Сравнение Forth (по крайней мере, Gforth) возвращает -1 для true и 0 для false

0                     \ place 0 on top of the stack to use as a counter
13 1 do               \ begin the outer loop from 1 to 12
  i 2 = 3 *           \ if i is 2 place -3 on top of the stack, otherwise 0
  32 + 1 do           \ begin the inner loop from 1 to 31 (or 28)
    over              \ copy the year from stack position 2 and place it on top of the stack
    i j * = -         \ multiply month and day compare to year, subtract result from counter 
  loop                \ end the inner loop
loop                  \ end the outer loop
reffu
источник
1

Java (JDK 10) , 79 72 70 байт

y->{int a=0,m=13;for(;m-->1;)a+=y%m<1&&y/m<(m==2?29:32)?1:0;return a;}

Попробуйте онлайн!

user202729
источник
@ Shaggy Спасибо! (остаток от предыдущей версии, где я перебираю все dайсы)
user202729
Если вы измените &&к &нему тот же ответ , как Java ответ OlivierGrégoire, хотя он ответил 19 минут раньше.
Кевин Круйссен
@KevinCruijssen Случайное совпадение. Хотя моя версия немного хуже (ненужное использование троичного).
user202729
1

JavaScript (Node.js) , 108 байт

a=>'0122324243426133415153317223416132126011504033106131204241006003213011306002122042005101305111014012'[a]

f=a=>'0122324243426133415153317223416132126011504033106131204241006003213011306002122042005101305111014012'[a]
o.innerText=[...Array(99)].map((_,x)=>(2001+x++)+` = `+f(x)).join`\n`
pre{column-count:5;width:480px;}
<pre id=o></pre>


источник
Брутфорс, приятно!
BradC
Добро пожаловать в PPCG!
Shaggy
1

Python 3, 132 байта

Это действительно довольно длинная программа, но я подумал, что она может быть интересной.

Все значения находятся в диапазоне 0-7, поэтому я кодирую каждое число 3 битами в длинной двоичной строке. Я попытался вставить необработанную двоичную строку в мою программу на Python, но не смог заставить ее работать, поэтому я остановился на base64 в файле.

Я использовал следующую строку в качестве таблицы поиска (окончание 7 используется для заполнения): 01223242434261334151533172234161321260115040331061312042410060032130113060021220420051013051110140127

Программа берет эту строку и декодирует ее как число, а затем использует битовое смещение для извлечения результата.

import base64
lambda n:int.from_bytes(base64.b64decode(b'pNRRxYtw01s9Jw4tFYE0QNkYsoRQgYBosEsYBFIRAUgsUkgwFQM='),'big')>>(6306-3*n)&7

66 байт + файл 37 байт = 103 байта

Это читает двоичный файл с именем eи избегает использования base64.

lambda n:int.from_bytes(open('e','rb').read(),'big')>>(6306-3*n)&7

Вот hexdump прочитанного файла (без заполнения):

00000000  a4 d4 51 c5 8b 70 d3 5b  3d 27 0e 2d 15 81 34 40  |..Q..p.[='.-..4@|
00000010  d9 18 b2 84 50 81 80 68  b0 4b 18 04 52 11 01 48  |....P..h.K..R..H|
00000020  2c 52 48 30 0a                                    |,RH0.|
qwr
источник
1

Oracle SQL, 115 байт

select count(decode(sign(decode(l,2,29,32)-y/l),1,1))from t,
xmltable('1to 12'columns l int path'.')where mod(y,l)=0

Мы можем отметить, что на самом деле не имеет значения, сколько дней в апреле (и более поздних месяцах), так как 100/4 <28. Также нет необходимости проверять, является ли год високосным или нет. Мы просто должны указать, что в феврале 28 дней (а не 29, потому что эта проверка будет выполняться только для 2058 года, что не является скачком), в противном случае это может быть всего 31 за любой месяц.

Другие подходы

Oracle SQL (12c Release 2 и более поздние версии), 151 байт

select count(to_date(y/l||'-'||l||'-1' default '' on conversion error,'dd-mm-y'))from t,
(select level l from dual connect by level<=12)where mod(y,l)=0

Oracle SQL (12c Release 2 и более поздние версии), 137 байт

select sum(validate_conversion(y/l||'-'||l||'-1'as date,'dd-mm-y'))from t,
(select level l from dual connect by level<=12)where mod(y,l)=0

Оба решения могли бы быть 8 байт короче , если мы заменим (select level l from dual connect by level<=12)с , xmltable('1to 12'columns l int path'.')но Oracle бросает исключение из-за ошибки (проверено на версии 12.2.0.1.0, 18.3.0.0.0).

SQL> select count(to_date(y/l||'-'||l||'-1' default '' on conversion error,'dd-mm-y'))from t,
  2  xmltable('1to 12'columns l int path'.')where mod(y,l)=0
  3  /
select count(to_date(y/l||'-'||l||'-1' default '' on conversion error,'dd-mm-y'))from t,
*
ERROR at line 1:
ORA-00932: inconsistent datatypes: expected DATE got DATE


SQL> select sum(validate_conversion(y/l||'-'||l||'-1'as date,'dd-mm-y'))from t,
  2  xmltable('1to 12'columns l int path'.')where mod(y,l)=0
  3  /
select sum(validate_conversion(y/l||'-'||l||'-1'as date,'dd-mm-y'))from t,
*
ERROR at line 1:
ORA-43909: invalid input data type

Единственный случай в обоих решениях, когда год имеет значение, это 2058, который не является високосным, поэтому для указания не високосного года использовалось буквальное значение «-1».

Oracle SQL, 128 байт

select count(d)from t,(select date'1-1-1'+level-1 d from dual connect by level<365)
where to_char(d(+),'mm')*to_char(d(+),'dd')=y

Oracle SQL, 126 байт

select substr('122324243426133415153317223416132126011504033106131204241006003213011306002122042005101305111014012',y,1)from t

Обновить

Oracle SQL, 110 байт

select-sum(least(sign(y/l-decode(l,2,29,32)),0))from t,
xmltable('1to 12'columns l int path'.')where mod(y,l)=0

Oracle SQL, 108 байт

select sum(decode(sign(decode(l,2,29,32)-y/l)*mod(y+1,l),1,1))from t,
xmltable('1to 12'columns l int path'.')

Spark SQL, 137 байт

select count(cast(regexp_replace(concat_ws('-','2001',l,y/l),'.0$','')as date))
from(select explode(array(1,2,3,4,5,6,7,8,9,10,11,12))l),t

Spark 2.3+ SQL, 126 байт

( replaceфункция становится доступной)

select count(cast(replace(concat_ws('-','2001',l,y/l),'.0')as date))
from(select explode(array(1,2,3,4,5,6,7,8,9,10,11,12))l),t
Доктор У Вит
источник
1

PHP , 73 байта

Используя вход трубы и php -nR:

for(;++$m<13;$d=1)while($d<25+($m-2?$m>4?:7:4))$c+=$argn==$m*$d++;echo$c;

Попробуйте онлайн!

PHP , 76 байт

Использование командной строки arg input php dm.php 18:

for(;++$m<13;$d=1)while($d<25+($m-2?$m>4?:7:4))$c+=$argv[1]==$m*$d++;echo$c;

Попробуйте онлайн!

Итерационный подход. Поскольку единственный високосный год - 2 * 29 = 58, а 2058 год не високосный, нет необходимости рассматривать високосный год в февральских днях. И так как перенос не является проблемой - с апреля любой день, превышающий 25, будет превышать 100, мы просто говорим, что в остальные месяцы есть только 25 дней.

Ввод двухзначного года через командную строку (-10 байт как программа, спасибо предложению @Titus).

ИЛИ:

PHP , 101 байт

$y=$argv[1];for($d=strtotime("$y-1");date(Y,$d)==$y;$d+=86400)eval(date("$\x+=j*n=='y';",$d));echo$x;

Попробуйте онлайн!

Все еще итеративный, но с использованием функций отметки времени PHP. Принимает год как четырехзначное число. Спасибо @Titus за предложение использовать strtotime()вместо mktime().

640 КБ
источник
Первая версия терпит неудачу в течение четырехзначных лет, вторая - двухзначных. Но приятно думать. Попробуй $m<5?$m-2?31:28:25для первого и $d=strtotime("$y-1")для второго
Тит
Хм ... Почему вы положили yв Eval в кавычках?
Тит
@Titus, потому что PHP7 теперь обрабатывает цифры, начинающиеся с 0, как восьмеричные, поэтому 08 и 09 фактически недопустимы. tio.run/##K8go@G9jXwAkU5Mz8hUMFWxtFQwsrP//BwA Используя функцию date (), вы можете получить только 2-значный год с нулем.
640 КБ
Облом! конечно.
Тит
1
@Titus, обновленная вторая версия, использующая strtotime()вместо mktime()и повторно реализованная как программа, -7 байт. Кроме того, я рассмотрел большинство представлений, в том числе самых популярных, в которых год будет приниматься только в виде 2 или 4 цифр, поэтому я буду считать, что это зависит от заявителя. Спасибо еще раз за предложения!
640 КБ
0

PHP, 74 70 байт

while(++$m<13)for($d=$m<5?$m-2?31:28:25;$d;)$n+=$d--*$m==$argn;echo$n;

принимает только двузначные годы.

Я принял соображения Гво и играл в гольф; мой первый подход был длиннее его (92 байта):

for($y=$argn%100;++$m<13;)for($d=$m-2?30+($m+$m/8)%2:29-($y%4>0);$d;)$n+=$d--*$m==$y;echo$n;

%100 позволяет использовать 4-х значные годы.


Запустите как трубу с -nRили попробуйте их онлайн .

Titus
источник
Вы можете сохранить 4 байта, удалив% 100 и взяв только 2-значный ввод, что нормально: codegolf.stackexchange.com/questions/162137/…
640KB