Дата множення виклику


19

(Натхненний минулого тижня "Riddler" на FiveThirtyEight.com. Пісочниця .)

З огляду на рік в період між 2001 і 2099, вартістю і повертає кількість днів , в протягом цього календарного року , де mm * dd = yy(де yyє 2-значний рік).

На 2018 рік, наприклад, 5:

  • 18 січня (1 * 18 = 18)
  • 9 лютого (2 * 9 = 18)
  • 6 березня (3 * 6 = 18)
  • 3 червня (6 * 3 = 18)
  • 2 вересня (9 * 2 = 18)

Введення може бути дво- або чотиризначним числовим роком.

Вихід повинен бути цілим числом. Необов'язковий пробіл або повернення - це добре.

Повний список вводу / виводу:

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

Це виклик з , найнижча кількість байтів на кожній мові.

Попередній розрахунок і просто пошук відповідей, як правило, виключається згідно з нашими правилами лазівки , але я явно дозволяю це вирішити. Це дозволяє отримати декілька цікавих альтернативних стратегій, хоча список пошуку в 99 99 пунктів, швидше за все, буде найкоротшим.


Якщо це полегшить вашу мову, відповідь буде однаковою незалежно від століття; 1924 та 2124 рр.
Така

якщо результат mm * dd більше 100, він автоматично фільтрується?
DanielIndie

@DanielIndie Правильно, дати "обгортання" не слід вважати. Іншими словами, 12 грудня 2044 року не
рахується

Оскільки нам потрібно обробляти лише обмежену кількість входів, я все їх відредагував. Не соромтеся відкатати чи переформатувати.
Кудлатий

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
Дуже хороша. Ймовірно, варто згадати, що він потребує 2-значний рік у A1. Якщо ввести 4-значний рік, просто повертається 0.
BradC

Правда! Я відредагую це в описі.
Софія Лехнер

Також слід зазначити, що це специфічно для місцевості; це залежить від наявності локалу, який використовує впорядкування mm / dd / yy. У локалі з порядком dd / mm / yy відповідь, звичайно, була б такою ж кількістю байтів.
Софія Лехнер

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 лютого, виключаючи їх із діапазону.


5

Java (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. Формат дати може знадобитися змінити для інших культур.


2
"культура"? Ви мали на увазі "locale"? ...
користувач202729

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)

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

Як?

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




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

Розрив рядка призначений лише для читабельності. В основному натхненний рішенням Excel від Софії .

  • У верхньому рядку створюється 12-елементна таблиця номерів c яка приєднується до вхідної таблиці t .
  • Якщо це пройде, я збиваю кандидата на дату, використовуючи CONCAT(), що робить неявні varcharперетворення даних. Інакше мені доведеться зробити купуCAST або CONVERTзаяви.
  • Знайшов ідеальну функцію оцінювання ISDATE() , яка повертає 1 для дійсних дат і 0 для недійсних дат.
  • Загорніть його в СУМ і я закінчую.
  • EDIT : Переміщено цілочисельну перевірку ділення ( y%m=0) уWHERE пункт, щоб зберегти 2 байти, завдяки @RazvanSocol.

На жаль, він не набагато коротший, ніж версія таблиці пошуку (використовуючи рядок з версії osdavison ):

Пошук T-SQL, 129 байт

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

EDIT : Залишаючи свій оригінал вище, але ми можемо зберегти кілька байт, використовуючи пару нових функцій:

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


Як і в інших відповідях, порядок збирання дати ( m/d/y) залежить від параметрів місцевості екземпляра SQL. В інших місцевостях може знадобитися інший порядок або інший роздільник, але я не думаю, що це вплине на довжину коду.
BradC

Я думаю, ви зрозуміли, що перетворення "2/29/64" на дату дає 1964-02-29 (а не 2064-02-29), але враховуючи, що 2000 та 2100 роки виключені, це хороший спосіб отримати коротший код.
Разван Сокол

Використання SPLIT_STRINGзамість CTE знижує його до 120 байт. Використовуючи CONCAT_WSзамість цього, ви CONCATзберігаєте інший символ, отримуючи його до 119 байт.
Разван Сокол

@RazvanSocol Так, я не впевнений, де перерва між двозначними датами, які відображаються на 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. Якщо результат виключає вірно, ми перевіряємо дати , 1:28+3тобто 1:31, в іншому випадку ми перевіряємо тільки дату 1:28.

1:28достатньо для решти місяців (це покращення надихнуло на відповідь Рубі Асони Тухід ), оскільки:

  • для лютого єдиною можливістю був би 2*29 = 58, але 2058це не високосний рік, тому ми можемо припустити, що у Февраля завжди 28 днів.

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

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


3

JavaScript, 91 85 82 81 77 байт

Приймає введення як двозначний рядок (або 1 або 2 розрядне ціле число).

Скористайтеся тим, що new Dateбуде переходити на наступний місяць, і продовжуйте робити це, якщо ви передасте йому значення дня, яке перевищує кількість днів у місяці, коли ви переходите до нього, так що при першій ітерації він намагається побудувати дата, yyyy-01-345яка наступає yyyy-12-11, або yyyy-12-10у високосні роки. Нам не потрібно перевіряти дати після цього, оскільки це 12*11+призводить до 3-значний номер.

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 байт для підтримки чотиризначних років. Пояснення: Перший етап просто перетворюється на одинаковий. Другий етап починається зіставленням від 1 до 12 символів перед позицією матчу, що представляє місяць, а потім намагається заглянути вперед для цілої кількості повторень того місяця. Однак лококахед містить умовний, який вибирає до 27 або 30 подальших повторів залежно від місяця. Підрахунок позицій матчу - це бажаний результат.


2

R , 22 122 байти

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

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

Вирішили піти з підходом до таблиці пошуку. Рік введення повинен бути 2 цифри.


1
Також на TIO ви можете натиснути кнопку "посилання", і вона автоматично відформатує відповідь за вас. Дякуємо Деннісу за налаштування!
Джузеппе

Ви можете видалити початковий if, оскільки вхід може бути або двозначним, або чотиризначним, на ваш вибір (ви можете прийняти лише двозначний ввід). Але схоже, що код вважає, що кожен місяць містить 31 день, так, наприклад, 62 (за 2062 рік) повертає 1, де він повинен повернути 0.
sundar - Відновити Моніку

2
Я неправильно зрозумів. Зважаючи на це, я впевнений, що таблиця пошуку повинна бути включена до числа байтів.
ngm

@ngm Я також не був впевнений, чи потрібно включити таблицю пошуку, але я додам її до кількості байтів, щоб бути безпечною.
Роберт С.

Я досі не впевнений, які всі правила!
ngm

2

C (gcc), 65 60 59 байт

d(a,t,e){for(t=0,e=13;e-->1;)t+=a%e<1&a/e<(e-2?32:29);a=t;}

Відповідь Java на порт користувача 202729 . Спробуйте його онлайн тут . Дякую Джонатану Фреху за те, що він займався 1 байтом у гольф.


a=0,m=13;for(;~> for(a=0,m=13;.
Джонатан Фрех

@JonathanFrech Дякую, що вказав на це, я відредагував.
OOBalance

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

Python 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

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


5
Ласкаво просимо на сайт і приємне перше повідомлення! Є декілька способів, як можна пограти в це поле, наприклад, видалити пробіл, тому обов'язково ознайомтеся з цими порадами щодо гольфу в Python
caird coinheringaahing

@cairdcoinheringaahing Дякую за поради, посилання було дуже корисним!
акозі

1
158 байт - гольф трохи подалі, але в основному у вас був великий довгий пробіл на третій лінії, не знайте, як вони потрапили туди
Стівен

@Stephen Спасибі :) Я додав твої як дві редакції. Один для білого простору, а інший як гольф.
акозі

(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. Нарешті, лічильники змінних можна в основному скоротити до lenосягнення списків, це також дозволяє nзробити lambda. Це робить 118 .
Чорна сова Кай

2

Четвертий (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] - Форт має поняття подвійних чисел довжини, які зберігаються на стеці у вигляді двох одномірних чисел (форми xy, де значення подвійного = y * 2^(l) + xде l - розмір у бітах одиничного в далі реалізація, з якою ви працюєте).

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

Четвертий (gforth) , 61 байт

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

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

Зберегли кілька байтів, зрозумівши, що лише лютий має значення з точки зору правильної кількості днів у місяці

Пояснення

Четверте (принаймні gforth) порівняння повертає -1 для істинного та 0 для хибного

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

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

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


@Shaggy Дякую! (Залишився з попередньої версії, де я перебираю всі d
айси

Якщо ви перейдете &&на &той самий варіант відповіді, як відповідь Java Олів'є Грегреара, хоча він відповів на 19 хвилин раніше.
Кевін Кройсейсен

@KevinCruijssen Випадковий збіг. Хоча моя версія трохи гірша (непотрібне використання тернару).
користувач202729

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!
Кудлатий


1

Python 3, 132 байти

Це дійсно досить тривала програма, але я подумав, що це може зацікавити.

Усі значення знаходяться в межах від 0 до 7, тому я кодую кожне число по 3 біти в довгій двійковій рядку. Я спробував вставити сиру двійкову рядок у свою програму python, але я не зміг її працювати, тому я влаштувався на файл base64 у файлі.

I used the following string as a lookup table (ending 7 used for padding): 01223242434261334151533172234161321260115040331061312042410060032130113060021220420051013051110140127

The program takes this string and decodes it as a number, then uses bit shifting to extract the result.

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

66 bytes + 37 byte file = 103 bytes

This reads a binary file called e and avoids using base64.

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

Here is a hexdump of the read file (without padding):

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


1

Oracle SQL, 115 bytes

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

We may note that it does not really matter how many days in April (and later months), since 100/4 < 28. Also it's not necessary to check whether year is leap or not. We just have to specify that there are 28 days in February (not 29 because that validation will be executed only for 2058 which is not leap) otherwise it may be just 31 for any month.

Other approaches

Oracle SQL (12c Release 2 and later), 151 bytes

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 and later), 137 bytes

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

Іскровий 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

Іскра 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 байт

Використання введення аргументів командного рядка 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 байт як програма, thx до пропозиції від @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().


First version fails for 4-digit years, second fails for two-digit. But nice thinking. Try $m<5?$m-2?31:28:25 for the first and $d=strtotime("$y-1") for the second
Titus

Uhm ... Why did you put the y in the eval in quotes?
Titus

@Titus because PHP7 now treats digits preceeded with 0 as octal, so 08 and 09 are actually not valid. tio.run/##K8go@G9jXwAkU5Mz8hUMFWxtFQwsrP//BwA Using the date() function you can only get a 2 digit, zero-padded year.
640KB

Bummer! of course.
Titus

1
@Titus, updated second version using strtotime() instead of mktime() and re-implemented as program, -7 bytes. Also, I looked at the majority of the submissions, including the top voted ones, will only accept year as either 2 or 4 digits, so I'm going to take that to mean it is up to submitter. Thx again for the suggestions!
640KB

0

PHP, 74 70 bytes

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

accepts two-digit years only.

I adopted gwaugh´s considerations and golfed them; my 1st approach was longer than his (92 bytes):

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 allows to use 4-digit years.


Run as pipe with -nR or try them online.


You can save 4 bytes by removing the %100 and only taking 2 digit input, which is OK: codegolf.stackexchange.com/questions/162137/…
640KB
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.