Чи закінчилося моє молоко?


98

Ах, чоловіче, цей термін придатності не пише місяці листами! Я не можу сказати, чи закінчується це 10 березня чи 3 жовтня ... Зачекайте, ні, неважливо, рік говорить 2012. (алей-ой, напіввжита цегла сиру в смітник може подобатися профі)

Тож припустимо на мить, що ви занадто зайняті, щоб спробувати розібратися, коли термін дії цієї баночки маринари закінчується. Ви просто хочете версію Cliff Notes: наскільки ймовірно, що вона прострочена? Давайте напишемо якийсь код!

Вам відомо, що виробники друкують дату як упорядковану трійку цілих чисел у одному з трьох форматів:

YEAR  MONTH DAY
MONTH DAY   YEAR
DAY   MONTH YEAR

І ви знаєте, що деякі дати можна інтерпретувати лише одним або двома способами, а не всі три: 55 років 55-11-5має бути роком, це означає, що ця конкретна скринька Twinkies закінчилась 5 листопада 1955 року. Рік іноді дається чотирма цифрами та не два, що може виключати деякі варіанти. Однак, якщо це дві цифри, 50..99 означає 1950..1999, а 0..49 означає 2000..2049.

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

Масив цілих чисел буде [Int]тип вашої мови тривалістю три, якщо він є аргументом функції, і дається як цілі чи знаки, косо-відмінні, або розділені пробілами (ви можете вибрати) цілі числа, якщо вони використовуються як вхід на STDIN до повна програма. *

"Сьогоднішня дата" може бути сьогоднішньою фактичною датою, отриманою за допомогою функції дати, або датою, вказаною в додатковому аргументі для функції або додаткового параметра в STDIN. Це може бути в епоху секунди Unix, ще одна трійка рік-місяць-день, введена одним із трьох вищезгаданих способів, або іншим більш зручним способом.

Приведемо кілька прикладів! Термін дії дати закінчується в стилі, розділеному тире, і для прикладів нижче припустимо, що сьогоднішня дата - 5 липня 2006 року.

  • 14-12-14- Обидві дійсні інтерпретації для цього (DMY та YMD) еквівалентні, 14 грудня 2014 р. Вихід 100, оскільки цей продукт, безумовно, ще хороший.
  • 8-2-2006- Останнє число - напевно, оскільки воно має чотири цифри. Це може бути 8 лютого (минув) або 2 серпня (все ще добре). Вихід - 50 .
  • 6-7-5- Це може бути що завгодно! Інтерпретація "5 липня 2006 року" все ще хороша (лише на один день), але решта двох - і в 2005 році, і їх слід кинути якнайшвидше. Вихід - 33 .
  • 6-5-7- Тут два з трьох тлумачень безпечні. Ви можете округлити свій десятковий знак вгору або вниз, так що 66 або 67 добре.
  • 12-31-99- Гаразд, це однозначно з межі століття (роки від 50 до 99 - це 19XX, а 31 не може бути місяцем). Великий жир 0 , і ви дійсно повинні частіше прибирати холодильник.

Ви можете з упевненістю припустити, що будь-який вхід, який не відповідає вищезазначеним стандартам, не є дотриманим вищезазначених правил виводу.

Немає веб-запитів або стандартних лазівки. Бібліотеки обробки дат дозволені. Це код гольфу: можливо, найкоротша програма виграє.

* Якщо ви використовуєте brainfuck або якусь подібну мову з обмеженими типами даних, ви можете припустити, що значення ASCII перших трьох символів, що вводяться, - цілі числа для дати. Це виключає чотиризначну логіку року, але я думаю, що ми були б дуже здивовані, побачивши в Brainfuck вирішення цього питання, аби вам це зробити.


39
Гм ... поточний рік - це 2014, а не 2006. Ваше молоко в кращому випадку закінчилося на вісім років.
— Джон Дворак

11
@JanDvorak Я просто не хотів дуже намагатися будувати змістовні приклади, тому я переробив сьогоднішню дату, щоб зробити її простішою.
— алгоритм

7
@ Dgrin91 байдуже, я все одно їх з'їм: D
— aditsu

6
В Австралії термін дії молока закінчується приблизно за тиждень до дати вживання
— гніблер

5
Ви повинні додати тест із позначкою 00, оскільки це не може бути законним днем ​​чи місяцем.
— MtnViewMark

Відповіді:


5

k4 (90) (88) (87) (82)

{100*(+/~d<x)%3-+/^d:{"D"$"."/:$|z,y,x+(x<100)*100*19+x<50}.'y@/:3 3#.:'$21020101}

Виклик з xз .z.D(в вбудована в нього ) для порівняння з сьогоднішнім днем, або дат буквальних вашого вибору в іншому випадку:

  f:{100*(+/~d<x)%3-+/^d:{"D"$"."/:$|z,y,x+(x<100)*100*19+x<50}.'y@/:3 3#.:'$21020101}
  .z.D f'(14 12 14;8 2 2006;6 7 5;6 5 7;12 31 99)
100 0 0 0 0f
  2006.07.05 f'(14 12 14;8 2 2006;6 7 5;6 5 7;12 31 99)
100 50 33.33333 66.66667 0

Це в основному порт рішення Python @ Alex-l, додано кілька різноманітних трюків з гольфу:

  • Інструкції з перестановки закодовані в рядок, щоб зберегти пару символів.
  • Умовна логіка (ab) використовує істину як ціле число (але в інший спосіб, ніж рішення Python).
  • Тест на валідність дещо інший - k4 / q із задоволенням буде розбирати будь-який рядок у будь-якому типі даних; він просто повертає нуль, якщо він не може мати сенс. Таким чином, я повертаю список дат із внутрішньої функції, який може бути, а може бути і недійсним.
  • Кінцевим результатом є перевірка того, скільки можливих інтерпретацій дати є нульовими порівняно з кількістю менших порівняно з датою порівняння; тут важливо, щоб нульова дата вважалася меншою, ніж будь-яка інша дата.

1
Ви можете зберегти знак, видаливши останні 0 з "012201210", оскільки #його елементи приймаються циклічно. Насправді, ви можете заощадити на секунду CHAR таким чином, змінюючи останні два випадки: 3 3#.:'"0122102".
— алгоритм

Поголив ще одну карту, обернувши аргументи внутрішнього функціоналу, врятувавши паронів (але додавши зворотний бік). Чи може хтось допомогти мені зберегти ще дві символи? APL мене б’є!
— Аарон Девіс

Поголив ще п’ять, переписавши математику в кінці. Назад вперед!
— Аарон Девіс

І якщо я нахилитися писати серйозно нефункціональні код, я можу голитися ще один байт, забруднюючи глобальний простір імен: {c*(+/~d<x)%3-+/^d:{"D"$"."/:$|z,y,x+(c*19+x<50)*x<c::100}.'y@/:3 3#.:'$21020101}.
— Аарон Девіс

14

Рубін, 115 символів

f=->a,t{[a,a.rotate(~s=r=0),a.reverse].map{|x,*y|(t>Time.gm(x<100?x+2e3-100*x/=50:x,*y)||r+=100
s+=1)rescue p}
r/s}

Це визначає функцію, fяка бере два аргументи: масив, що містить вхід, та "сьогоднішню" дату.

Приклади:

f[[14,12,14], Time.new]
100
f[[8,2,2006], Time.new]
0
f[[8,2,2006], Time.new(2006, 7, 5)]
50
f[[6,7,5], Time.new(2006, 7, 5)]
33

12

Пітон 2,7 - 172

Я використовую модуль datetime для дійсності та порівняння дат. Якщо dateви не можете зробити дійсний час із входу, воно збільшується ValueError. Цей спосіб sє сумою tнедійсних дат і є загальною кількістю дійсних дат. Я використовую той факт, що True == 1для додавання та індексації в Python. Я також зберігаю символ, використовуючи 25 * (76,80) замість (1900,2000).

Зверніть увагу, що рядки у другому рівні відступу використовують символ табуляції, а не 2 пробіли.

def f(e,c,s=0,t=3):
 for Y,M,D in(0,1,2),(2,0,1),(2,1,0):
  y=e[Y]
  try:s+=date(y+25*[[76,80][y<50],0][y>99],e[M],e[D])>=c
  except:t-=1
 return 100*s/t

Додайте це до кінця, щоб перевірити:

examples = [[14,12,14],[8,2,2006],[6,7,5],[6,5,7],[12,31,99]]
for e in examples:
 print f(e, date(2006,7,5))

10

PowerShell, 183 173 168

[int](100*(($d=@(($a,$b,$c=$args[0]),($c,$a,$b),($c,$b,$a)|%{$_[0]+=1900*($_[0]-le99)+100*($_[0]-le49)
.{date($_-join'-')}2>$x}|sort -u))-ge(date)+'-1').Count/$d.Count)
  • Введіть як int[]через параметр, наприклад

    PS> ./milk.ps1 5,6,7
    
  • Повідомлення про помилки відключаються через try/ catch, доки я не знаю, чи дозволено вихід на stderr чи ні.
  • Використовуючи +"-1"дату, яку інтерпретують як .AddDays(-1)зміщення поточної дати на один день, так що ми можемо порівняти з вчорашнім (а не просто сьогоднішнім). Це вирішує проблему, коли ми отримуємо побачення з 0:00 як час, але нам потрібно порівняти дату з часом від сьогоднішнього дня.
  • На сьогодні сильно накреслений
  • Використання нового трюку для приглушення помилок, що зовсім коротше

6

R, 269

Я очікував, що це буде легко в R, але одноцифрові роки були досить великою кривою. Я відчуваю, що це може бути набагато краще, ніж це є.

lubridateце пакет від CRAN, можливо, вам доведеться встановити його install.packages("lubridate").

require(lubridate)
f = function(d){
d=sapply(d,function(l)if(nchar(l)==1)sprintf("%02d",l)else l)
d=paste0(d,collapse="-")
t=ymd(Sys.Date())
s=na.omit(c(ymd(d),mdy(d),dmy(d)))
s=lapply(s,function(d){
if(year(d)>2049){year(d)=year(d)-100;d}
else d})
sum(s>t)/length(s)}

Використання: f(c(d1,d2,d3))де c(d1,d2,d3)вектор цілих чисел.

наприклад, f(c(6,10,14))повертає 0.3333333.

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


6

Mathematica, 163 153 164 байт

( редагувати: фіксовані дати поза діапазоном 1950 - 2049)

f=100.Count[#,x_/;x<1]/Length@#&[DateDifference[#,Date[]]&/@Cases[{If[#<100,Mod[#+50,100]+1950,#],##2}&@@@{{##},{#3,#2,#},{#3,#,#2}}&@@#,d_/;DateList@d~Take~3==d]]&

Це визначає функцію, яку можна викликати як

f[{6,7,5}]

Наразі відсоток не округлюється (очікуючи уточнення ОП).

Ось трохи довге пояснення , яке повинно бути зрозуміло без знання Mathematica (зауважимо , що &робить все від нього залишилося анонімна функція, параметри якої називають #, #2, #3...):

{{##},{#3,#2,#},{#3,#,#2}}&

Це визначає функцію, яка перетворює 3 параметри a,b,cв 3 списки {{a,b,c},{c,b,a},{c,a,b}. Зауважте, що ##це лише послідовність усіх параметрів.

{{##},{#3,#2,#},{#3,#,#2}}&@@#

Застосований до терміну придатності, це дає перелік {y,m,d}для кожної з трьох можливих перестановок.

{If[#<100,Mod[#+50,100]+1950,#],##2}&

Це анонімна функція, яка приймає три параметри a,b,cі повертає список з трьох, де перший був перетворений на рік відповідно до заданих правил: числа між 50та 99(за модулем 100) перетворюються на рік 20 століття, числа між 0і 49( modulo 100) перетворюються на рік 21 століття, всі інші залишаються поряд. Тут ##2подано послідовність параметрів, починаючи з другого, тобто b,c.

{If[#<100,Mod[#+50,100]+1950,#],##2}&@@@{{##},{#3,#2,#},{#3,#,#2}}&@@#

Застосований до трьох попередніх результатів, це просто канонізує формати року. Назвемо це, canonicalDatesщоб скоротити такий вираз:

Cases[canonicalDates,d_/;DateList@d~Take~3==d]

Це фільтрує недійсні інтерпретації. DateList@dстворює повне {y,m,d,h,m,s}представлення з різних форматів дати. Він буде інтерпретувати списки в тому самому порядку, але улов полягає в тому, що ви можете передавати йому такі речі, як {8,2,2006}у такому випадку, він обчислить 8 years + 2 months + 2006 days. Отже ми перевіряємо, що перші три елементи повернутого списку ідентичні вхідному (що може статися лише у тому випадку, якщо місяць та день у відповідних діапазонах).

Щоб скоротити наступні рядки, я validDatesвідтепер посилаюся на результат цього виразу :

DateDifference[#,Date[]]&

Ще одна анонімна функція, яка приймає дату і повертає різницю в днях до сьогодні (отримано з Date[]).

DateDifference[#,Date[]]&/@validDates

Позначте це на дійсних інтерпретаціях дати.

100.Count[#,x_/;x<1]/Length@#&

Ще одна анонімна функція, яка, надаючи список ( #), повертає відсоток непозитивних чисел у цьому списку. Це .не множення, а лише десяткова цифра, щоб уникнути раціональних чисел як результат (ви отримаєте такі речі, як 100/3замість 33.333- я насправді не знаю, чи це проблема).

100.Count[#,x_/;x<1]/Length@#&[DateDifference[#,Date[]]&/@validDates]

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


Я думаю, ви неправильно конвертуєте такі роки, як 2999 чи 2099 рік, до 1999 року.
— Вентеро

@ Вентеро це правда. Я якось припускав, що ми маємо справу лише з 1950 - 2049 роками (та їх дво- або двозначною версією), але перечитуючи виклик, про це не згадується.
— Мартін Ендер

@ Вентеро виправлено (але ви мене все одно вже значно побили;))
— Мартін Ендер

Я здивований, коли у вас є обліковий запис на Mathematica, але ви не опублікували жодних запитань і відповідей. Щось вас стримує?
— Mr.Wizard

@ Mr.Wizard вибачте, абсолютно забув відповісти на вас. Запитання: до цих пір кожну проблему, яку я мав, можна було вирішити з googling / іншими питаннями SE. Відповіді: Я не знаю ... Я припускаю , що я не вважаю себе , що досвідченим , коли мова заходить про використання Mathematica продуктивно ... Я тільки використовувати його для швидких фрагментів тут і там (і код для гольфу). Крім того, я думаю, щоб відповісти на запитання, мені доведеться активно спостерігати за новими, щоб побачити, на що я можу відповісти, і в даний час весь мій час в SE відводиться на PPCG. ;) Якщо ви хочете, щоб я переконав мене в іншому, сміливо робіть це в чаті! :)
— Мартін Ендер

4

JavaScript (E6) 159 164 172

Редагувати Завдяки nderscore за підказки та за те, що підштовхує мене до роздумів. Реорганізовано D уникнення параметрів та скорочення деяких символів.

Редагувати 2 Ще один трюк за допомогою nderscore, 2 функції об'єднані в 1. Потім дві круглі дужки вилучили злиття виразів, розділених комою, в одне. Читальність біля 0. Sidenote: Не округлення може зберегти ще два знаки (| 0).

F=(a,t)=>t?100*(3-((i=F([y,m,d]=a))<t)-((j=F([m,d,y]=a))<t)-((k=F([d,m]=a))<t))/(3-!i-!j-!k)|0:(q=new Date(y<50?y+2e3:y,--m,d)).getMonth()==m&q.getDate()==d&&q

Тест в консолі FireFox

;[[14,12,14],[8,2,2006],[6,7,5],[6,5,7],[12,31,99]]
.map(x=>x + ' ' + F(x, new Date(2006,6,5)))

Вихід:

["14,12,14 100", "8,2,2006 50", "6,7,5 33", "6,5,7 66", "12,31,99 0"]

Безумовно

NB D функція намагається створити дату із заданим роком, місяцем, днем, але повертає помилковим, якщо створена дата не є такою, що була наміром (! = День або місяць)

F=(d,t)=>
(
  D=(y,m,d)=>(
    q=new Date(y<50?y+2000:y, --m, d), // decr m as javascript (like java) counts months starting at 0
    q.getMonth() == m & q.getDate() == d && q
  ),
  [a,b,c] = d, 
  x=D(...d), // three ways of express the date ...
  y=D(c,a,b),
  z=D(c,b,a),
  100 * (3-(x<t)-(y<t)-(z<t)) / (3-!x-!y-!z) | 0  
)   

@nderscore ОК для змін у D, помилка sintax для іншого. Але врятували ще більше
— edc65

Дивно. Щось, мабуть, сталося, коли я вставив це в коментар. Ваші останні оптимізації роблять це неважливим :)
— nderscore

1
Вкладаючи це в пасту, оскільки я більше не довіряю коментарям SE: (-3) pastie.org/private/6bemdweyndcaiseay70kia
— nderscore

4

C # в LINQPad - 446 408 272 байт

Третя редакція: Дякую Ле Канар Фуу за те, що він вказав, що DateTime.Today правильний, а не DateTime.Now. Друга редакція : Дякую VisualMelon за це розумне рішення!

void g(int[]d){var p=".";int a=d[2],b=d[1],e=d[0],y=a+(a<100?a>49?1900:2000:0),q=0,s=0;DateTime c;Action<string>z=x=>{if(DateTime.TryParse(x,out c)){s++;if(c>=DateTime.Today)q+=100;}};z(e+p+b+p+y);z(b+p+e+p+y);z(a+p+b+p+(e<100?‌​e>49?1900+e:2000+e:e));(q/(s>0?s:1)).Dump();}

Редагувати: Завдяки podiluska та edc65 за те, що вони допомогли мені скоротити код! Я також помітив, що моє рішення не було правильним, якщо введення року було 4 байти, тому я включив виправлення цієї проблеми. Оцінка за це рішення - 408 байт.

Хоча я не перемагаю жодної з попередніх відповідей, я все-таки хотів поділитися своїм рішенням C #. Будь-яка допомога / пропозиції вдячні! ;)

void g(int[]d){var q=new List<DateTime>();var p=".";int s=0,a=d[2],b=d[1],e=d[0],y=0;var c=new DateTime();y=(a<100)?(a>49)?1900+a:2000+a:a;if(DateTime.TryParse(e+p+b+p+y,out c)){q.Add(c);s++;}if(DateTime.TryParse(b+p+e+p+y,out c)){q.Add(c);s++;}y=(e<100)?(e>49)?1900+e:2000+e:e;if(DateTime.TryParse(a+p+b+p+y,out c)){q.Add(c);s++;}q=q.Where(i=>i>=DateTime.Now).ToList();if(s==0){s=1;}(q.Count*100/s).Dump();}

Відформатована версія

void g(int[] d)
    {
        var q = new List<DateTime>();
        var p = ".";
        int s = 0, a = d[2],b = d[1],e = d[0], y=0;
        var c = new DateTime();
        y = (a < 100) ?((a > 49) ? 1900 + a : 2000 + a) : a;

        if (DateTime.TryParse(e + p + b + p + y, out c))
        {
            q.Add(c);
            s++;
        }
        if (DateTime.TryParse(b + p + e + p + y, out c))
        {
            q.Add(c);
            s++;
        }
        y = (e < 100) ? ((e > 49) ? 1900 + e : 2000 + e) : e;

        if (DateTime.TryParse(a + p + b + p + y, out c))
        {
            q.Add(c);
            s++;
        }
        q = q.Where(i => i >= DateTime.Now).ToList();
        if (s == 0)
        {
            s = 1;
        }
        (q.Count*100/s).Dump();
    }

Я спробував зробити рішення, де "DateTime.TryParse" -Part не повторюється, як у цьому рішенні, але на 21 байт довше.

Рішення без повторення "DateTime.TryParse": 467 байт

void g(int[]d){var q=new List<DateTime>();int s=0;int a=d[2];int b=d[1];int e=d[0];int y=0;if(a<100){if(a>49){y=1900+a;}else{y=2000+a;}}if(z(e,b,y,q)){s++;}if(z(b,e,y,q)){s++;}if(e<100){if(e>49){y=1900+e;}else{y=2000+e;}}if(z(a,b,y,q)){s++;}q=q.Where(i=>i>=DateTime.Now).ToList();if(s==0){s=1;}(q.Count*100/s).Dump();}bool z(int a,int b,int d,List<DateTime> q){var c=new DateTime();var p=".";if(DateTime.TryParse(a+p+b+p+d,out c)){q.Add(c);return true;}return false;}

Безгольова версія:

private void g(int[] d)
    {
        var q = new List<DateTime>();
        int s = 0;
        int a = d[2];
        int b = d[1];
        int e = d[0];
        int y = 0;
        if (a < 100)
        {
            if (a > 49)
            {
                y = 1900 + a;
            }
            else
            {
                y = 2000 + a;
            }
        }
        if (z(e, b, y, q))
        {
            s++;
        }
        if (z(b, e, y, q))
        {
            s++;
        }
        if (e < 100)
        {
            if (e > 49)
            {
                y = 1900 + e;
            }
            else
            {
                y = 2000 + e;
            }
        }
        if (z(a, b, y, q))
        {
            s++;
        }
        q = q.Where(i => i >= DateTime.Now).ToList();
        if (s == 0)
        {
            s = 1;
        }
        (q.Count*100/s).Dump();
    }

    private bool z(int a, int b, int d, List<DateTime> q)
    {
        var c = new DateTime();
        string p = ".";
        if (DateTime.TryParse(a + p + b + p + d, out c))
        {
            q.Add(c);
            return true;
        }
        return false;
    }

2
int s=0;int a=d[2];int b=d[1];int e=d[0];->int s=0,a=d[2],b=d[1],e=d[0];
— podiluska

2
пропозиція: використовуйте ternary (? :), коли можливо, замість if / else
— edc65

1
@ThomasW. Я не думаю, оскільки у y є 2 різні значення, один раз - це залежно від a, а інший - залежно від e. Все одно, дякую!
— цавіньо

1
Видалення DateTime.TryParseдзвінків було моїм першим інстинктом, замінивши його лямбда, який також повернув значення назад у q. Також виконав кілька інших кроків ( пастбін ), щоб отримати 328часів:void g(int[]d){var q=new List<DateTime>();var p=".";int a=d[2],b=d[1],e=d[0],y;DateTime c;y=(a<100)?(a>49)?1900+a:2000+a:a;Action<string>z=(x)=>{if(DateTime.TryParse(x,out c))q.Add(c);};z(e+p+b+p+y);z(b+p+e+p+y);y=(e<100)?(e>49)?1900+e:2000+e:e;z(a+p+b+p+y);(q.Where(i=>i>=DateTime.Now).Count()*100/(q.Any()?q.Count:1)).Dump();}
— VisualMelon

1
@VisualMelon Нічого собі, ти справді хороший у коді-гольфінгу! Я ніколи Action<string>раніше не бачив , тому я міг щось у вас навчитися;) Я зміг отримати вашу відповідь на 318 символів, замінивши q.Where(i=>i>=DateTime.Now).Countна q.Count(i=>i>=DateTime.Now. Я також зняв дужки навколо, xщоб я міг зберегти ще 2 символи!
— tsavinho

3

Haskell, 171 165 символів

l=length
r y|y<100=(y+50)`mod`100+1950|y>0=y
q d m y z|d<32&&m<13&&d*m>0=(r y,m,d):z|1<3=z
v(a,b,c)=q c b a$q b a c$q a b c[]
t%d=(l$filter(>t)(v d))*100`div`l(v d)

Назва функції - %. Виконайте дату випробування як кортеж у канонічному (y, m, d) порядку з фактичним роком, а картонний штамп - як кортеж з трьох чисел:

λ: (2006,6,5)%(14,12,14)
100

λ: (2006,6,5)%(8,2,2006)
50

λ: (2006,6,5)%(6,7,5)
33

λ: (2006,6,5)%(6,5,7)
66

λ: (2006,6,5)%(12,31,99)
0

λ: (2006,6,5)%(0,1,7)
0

2

Ерланг, 146

f([A,B,C]=U,N)->F=[T||T<-[{(Y+50)rem 100+1950,M,D}||[Y,M,D]<-[U,[C,A,B],[C,B,A]]],calendar:valid_date(T)],100*length([1||T<-F,T>=N])div length(F).

Тестовою функцією було б:

t() ->
    0 = f([12,31,99],{2006,6,5}),
    66 = f([6,5,7],{2006,6,5}),
    33 = f([6,7,5],{2006,6,5}),
    100 = f([14,12,14],{2006,6,5}),
    50 = f([8,2,2006],{2006,6,5}),
    100 = f([29,2,2],{2006,6,5}).

Безумовно

f([A,B,C]=U,Today)->
    Perms = [U,[C,A,B],[C,B,A]],
    WithYears = [{(Y+50) rem 100+1950,M,D} || [Y,M,D] <- Perms],
    ValidDates = [T || T <- WithYears, calendar:valid_date(T)],
    100*length([1 || T <- ValidDates, T >= Today]) div length(ValidDates).

Це рішення спирається на розуміння списку. Він запозичує модульний трюк на рік з рішення Haskell. Він також використовує calendar:valid_date/1для обробки неможливих дат через кількість днів у даному місяці (наприклад, "29-2-2" може бути лише у форматі YMD). Також "Сегодня" знаходиться у date()форматі Ерланга (кортеж YMD).


2

APL (85)

При цьому використовуються деякі нові функції Dyalog APL 14, але немає зовнішніх бібліотек. Для зміни він працює в TryAPL .

{100×(+/÷⍴)⍺≤{(3/100)⊥⍵+(99≥⊃⍵)×3↑1900+100×50>⊃⍵}¨Z/⍨{∧/12 31≥1↓⍵}¨Z←(⊂⌽⍵),(⊂2⌽⍵),⊂⍵}

Це функція, яка приймає 3-елементний масив як ⍵аргумент правої сторони ( ), а дата, яку слід перевірити як ⍺аргумент його лівої сторони ( ), як ціле число YYYYMMDDформату. Тобто дата 2014-07-09представлена ​​як число 20140709.

Тест:

      20060705 {100×(+/÷⍴)⍺≤{(3/100)⊥⍵+(99≥⊃⍵)×3↑1900+100×50>⊃⍵}¨Z/⍨{∧/12 31≥1↓⍵}¨Z←(⊂⌽⍵),(⊂2⌽⍵),⊂⍵} 14 12 14
100
      20060705 {100×(+/÷⍴)⍺≤{(3/100)⊥⍵+(99≥⊃⍵)×3↑1900+100×50>⊃⍵}¨Z/⍨{∧/12 31≥1↓⍵}¨Z←(⊂⌽⍵),(⊂2⌽⍵),⊂⍵} 8 2 2006
50
      20060705 {100×(+/÷⍴)⍺≤{(3/100)⊥⍵+(99≥⊃⍵)×3↑1900+100×50>⊃⍵}¨Z/⍨{∧/12 31≥1↓⍵}¨Z←(⊂⌽⍵),(⊂2⌽⍵),⊂⍵} 6 7 5
33.3333
      20060705 {100×(+/÷⍴)⍺≤{(3/100)⊥⍵+(99≥⊃⍵)×3↑1900+100×50>⊃⍵}¨Z/⍨{∧/12 31≥1↓⍵}¨Z←(⊂⌽⍵),(⊂2⌽⍵),⊂⍵} 12 31 99
0

Пояснення:

  • Z←(⊂⌽⍵),(⊂2⌽⍵),⊂⍵: перетворіть задану дату у формат YMD, перегортаючи (⊂⌽⍵), обертаючи її вліво на 2 (⊂2⌽⍵)або просто нічого не роблячи ⊂⍵. Принаймні одна з них зараз є власною датою у форматі YMD, можливо, більше однієї, якщо дата неоднозначна.
  • {∧/12 31≥1↓⍵}¨Z: перевірити, якщо кожна дата є дійсною: рік (перший елемент) випадає, а потім місяць повинен бути не більше 12, а день повинен бути не вище 31.
  • Z/⍨: відфільтруйте дійсні дати з Z.
  • {... }¨: на кожну дійсну дату:
    • ⍵+(99≥⊃⍵)×3↑1900+100×50>⊃⍵: якщо рік не вище 99, додайте 1900, то 100, якщо рік нижчий за 50.
    • (3/100)⊥: розшифруйте його так, ніби це набір базових чисел 100. (Рік вище 100, але це не має значення, оскільки це перший елемент.) Це дає номер для кожної дійсної дати в тому ж форматі, що і аргумент зліва.
  • ⍺≤: для кожної дати дивіться, чи не менше вона ⍺. Це дасть бінарний вектор, де 1 означає OKі 0 означає spoiled.
  • 100×(+/÷⍴): ділимо суму двійкового вектора на його довжину і помножимо на 100.

Збережіть 7 байтів (і добрий запас поб'єте K), {100×(+/÷⍴)⍺≤((3/100)⊥⊢+(99≥⊃)×3↑1900+100×50>⊃)¨Z/⍨{∧/12 31≥1↓⍵}¨Z←(⌽⍵)(2⌽⍵)⍵}
— накресливши прямування

0

Java: 349 символів (3 без пробілів)

int e(int[]n,Date t){int a=n[0],b=n[1],c=n[2];Date[]d=new Date[3];if(b<13&&c<32)d[0]=new Date((a<50?100:(a>100?-1900:0))+a,b-1,c);if(b<13&&a<32)d[1]=new Date((c<50?100:(c>100?-1900:0))+c,b-1,a);if(a<13&&b<32)d[2]=new Date((c<50?100:(c>100?-1900:0))+c,a-1,b);int v=0,g=0;for(int i=0;i<3;i++)if(d[i]!=null){if(!d[i].before(t))g++;v++;}return 100*g/v;}

Ось клас, що містить, який можна використовувати для його тестування, включаючи (злегка) дегольфіковану версію методу:

import java.util.*;
class i{

   int e(int[]n,Date t){
      int a=n[0],b=n[1],c=n[2];
      Date[]d=new Date[3];
      if(b<13&&c<32)d[0]=new Date((a<50?100:(a>100?-1900:0))+a,b-1,c);
      if(b<13&&a<32)d[1]=new Date((c<50?100:(c>100?-1900:0))+c,b-1,a);
      if(a<13&&b<32)d[2]=new Date((c<50?100:(c>100?-1900:0))+c,a-1,b);
      int v=0,g=0;
      for(int i=0;i<3;i++)
         if(d[i]!=null){
            if(!d[i].before(t))
               g++;
            v++;
         }
      return 100*g/v;}

   public static void main(String[] args){
      int[]i=new int[3];
      for(int k=0;k<3;k++)
         i[k] = Integer.parseInt(args[k]);
      int j = new i().e(i,new Date());
      System.out.println(j+"%");
   }   
}

Це мій перший раунд кодового гольфу, і я думаю, що я зрозумів, чому зазвичай не бачу дуже багатьох гольфістів на Java.


1
Вам потрібно прийняти int[]як аргумент, а не три ints.
— Joey

ок, я це виправив.
— shieldgenerator7

0

C # 287 байт

namespace System{class E{static float a,o,l;void M(int[]i){int d=i[0],m=i[1],y=i[2],t;if(l<3)try{if(l==1){t=y;y=d;d=t;}if(l++==0){t=d;d=m;m=t;}if(y<100&&(y+=1900)<1950)y+=100;o+=new DateTime(y,m,d)>=DateTime.Today?1:0;a++;if(l<3)i[9]=9;}catch{M(i);throw;}Console.Write(o/a);}}}

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

Зловживання тим, що потрібна лише функція, а не фактична програма. Також функція завжди призводить до невловимого винятку.

Безумовно

namespace System {
    class E {
        static float a, o, l;
        void M(int[] i) {
            int d = i[0], m = i[1], y = i[2], t;
            if (l < 3)
                try {
                    if (l == 1) { 
                        t = y; y = d; d = t; 
                    } 
                    if (l++ == 0) { 
                        t = d; d = m; m = t; 
                    } 
                    if (y < 100 && (y += 1900) < 1950)
                        y += 100; 
                    o += new DateTime(y, m, d) >= DateTime.Today ? 1 : 0; // # not expired
                    a++; // # valid dates
                    if (l < 3)
                        i[9] = 9; // throw new Exception()
                } 
                catch { 
                    M(i);
                    throw; // fail after the first Console.Write()
                } 
            Console.Write(o / a); 
        } 
    } 
}

0

Математика , 118

Використовуючи код m.buettner як вихідний пункт, я маю декілька вдосконалень:

⌊100Mean@UnitStep@Cases[DateDifference@{If[#<100,Mod[#+50,100]+1950,#],##2}&@@@{#,RotateRight@#,Reverse@#},_Integer]⌋&

Гольф може бути функцією, яка бере аргумент із списку «Три Int».
— алгоритм

@algorithmshark Дякую Я не знаю, як я це пропустив. Оновлення ...
— Mr.Wizard
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.