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


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.