Czy moje mleko wygasło?

98

Aww, stary, ta data ważności nie pisze miesięcy listami! Nie wiem, czy wygasa 10 marca, czy 3 października ... Poczekaj, nie, nieważne, rok mówi 2012. (aleja oops w połowie zużyta cegła sera do kosza może jak zawodowiec)

Załóżmy więc przez chwilę, że jesteś zbyt zajęty, aby spróbować zrozumieć, kiedy ten słoik marinara ma wygasnąć. Chcesz tylko wersję Cliff Notes: jak prawdopodobne jest, że jest przeterminowana? Napiszmy kod!

Wiesz, że producenci drukują datę jako zamówioną potrójną liczbę całkowitą, w jednym z trzech formatów:

YEAR  MONTH DAY
MONTH DAY   YEAR
DAY   MONTH YEAR

I wiesz, że niektóre daty można interpretować tylko na jeden lub dwa sposoby, a nie wszystkie trzy: 55 w 55-11-5musi być rokiem, co oznacza, że ​​to konkretne pudełko Twinkies wygasło 5 listopada 1955 r. Rok ten jest czasem podawany w czterech cyfrach i nie dwa, co może wykluczyć niektóre opcje. Kiedy są to dwie cyfry, 50..99 oznacza 1950..1999, a 0..49 oznacza 2000..2049.

Twoim zadaniem jest napisanie programu lub funkcji, która pobiera tablicę liczb całkowitych, która jest prawidłową datą w co najmniej jednej z powyższych interpretacji i daje procent szansy, że nadal jest dobra. Procentowa szansa to po prostu procent prawidłowych interpretacji daty, która przypada w dniu dzisiejszym lub później .

Tablica liczb całkowitych będzie [Int]typu trzech długości twojego języka, jeśli jest argumentem funkcji i podana jako liczba całkowita rozdzielona myślnikiem, ukośnikiem lub spacjami (możesz wybrać), jeśli jest używana jako dane wejściowe STDIN do pełny program. *

„Dzisiejsza data” może być dzisiejszą rzeczywistą datą uzyskaną za pomocą funkcji daty lub datą podaną w dodatkowym argumencie funkcji lub dodatkowym parametrze w STDIN. Może to być sekunda epoki uniksowej, kolejny potrójny dzień-miesiąc wprowadzony na jeden z trzech powyższych sposobów lub inna wygodniejsza moda.

Zobaczmy kilka przykładów! Wprowadzanie daty wygaśnięcia będzie odbywało się w stylu rozdzielanym myślnikiem i przyjmijmy w poniższych przykładach, że dzisiejsza data to 5 lipca 2006 r.

  • 14-12-14- Obie ważne interpretacje tego (DMY i YMD) są równoważne, 14 grudnia 2014 r. Wynik wynosi 100, ponieważ ten produkt jest zdecydowanie dobry.
  • 8-2-2006- Ostatni numer to na pewno rok, ponieważ ma cztery cyfry. Może to być 8 lutego (wygasł) lub 2 sierpnia (nadal dobry). Wyjście wynosi 50 .
  • 6-7-5- To może być cokolwiek! Interpretacja „5 lipca 2006 r.” Jest nadal dobra (tylko na jeden dzień), ale pozostałe dwie są w 2005 r. I powinny zostać odrzucone tak szybko, jak to możliwe. Wyjście to 33 .
  • 6-5-7- Tutaj dwie z trzech interpretacji są bezpieczne. Możesz zaokrąglać ułamek dziesiętny w górę lub w dół, więc 66 lub 67 są w porządku.
  • 12-31-99- Okej, ten jest jednoznaczny z przełomu wieków (lata od 50 do 99 to 19XX, a 31 nie może być miesiącem). Duży tłuszcz 0 i naprawdę powinieneś częściej czyścić lodówkę.

Możesz bezpiecznie założyć, że wszelkie dane wejściowe, które nie spełniają powyższych standardów, nie są objęte powyższymi regułami dotyczącymi wyników.

Brak żądań internetowych lub standardowych luk. Biblioteki obsługi dat są dozwolone. To jest kod golfowy: może wygrać najkrótszy program.

* Jeśli używasz głupoty lub jakiegoś języka z podobnym upośledzeniem typu danych, możesz założyć, że ASCII pierwszych trzech wprowadzonych znaków to liczby całkowite dla daty. To wyklucza czterocyfrową logikę roku, oczywiście, ale myślę, że bylibyśmy zbyt zdumieni widząc rozwiązanie tego problemu w Brainfuck, aby cię za to lekceważyć.

algorytmshark
źródło
39
Umm ... bieżący rok to rok 2014, a nie 2006. Twoje mleko w najlepszym razie minęło osiem lat.
John Dvorak,
11
@JanDvorak Po prostu nie chciałem bardzo starać się budować sensownych przykładów, więc poprawiłem dzisiejszą datę, aby było łatwiej.
algorytmshark,
7
@ Dgrin91 nie obchodzi mnie, nadal jem: D
aditsu
6
W Australii mleko traci ważność na około tydzień przed terminem przydatności do spożycia
gnibbler
5
Powinieneś dodać test z cyfrą 00, ponieważ nie może to być dzień prawny ani miesiąc.
MtnViewMark

Odpowiedzi:

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}

Powołać się xod .z.D(a) do wbudowanego polecenia porównaniu do dzisiaj, lub dacie dosłownym swojego wyboru w inny sposób:

  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

Jest to w zasadzie port rozwiązania Pythona @ Alex-l, do którego dodano kilka różnych sztuczek golfowych:

  • Instrukcje przestawiania są kodowane w ciągu, aby zapisać kilka znaków.
  • Logika warunkowa (ab) używa prawdy jako liczby całkowitej (ale w inny sposób niż rozwiązanie Pythona).
  • Test poprawności jest nieco inny - k4 / q z przyjemnością parsuje dowolny ciąg znaków na dowolny typ danych; zwraca po prostu zero, jeśli nie ma sensu. Dlatego zwracam listę dat z funkcji wewnętrznej, która może być zerowa.
  • Ostateczny wynik pochodzi ze sprawdzenia, ile możliwych interpretacji dat jest zerowych, a ile mniejszych niż data porównania; ważne jest tutaj, aby data zerowa była uważana za krótszą niż jakakolwiek inna data.
Aaron Davies
źródło
1
Możesz zapisać znak, usuwając ostatnie 0 "012201210", ponieważ #cyklicznie pobiera jego elementy. W rzeczywistości, można zapisać drugą Char ten sposób przez zamianę dwóch ostatnich przypadkach: 3 3#.:'"0122102".
algorytmshark
Ogolono jeszcze jeden znak, odwracając argumenty funkcji wewnętrznej, oszczędzając pareny (ale dodając odwrotność). Czy ktoś może mi pomóc uratować kolejne dwa znaki? APL mnie bije!
Aaron Davies,
Ogoliłem kolejne pięć, przepisując matematykę na końcu. Z powrotem na czele!
Aaron Davies,
A jeśli ja schylać do pisania poważnie kod niefunkcjonalny, mogę golić kolejny bajt przez zanieczyszczających globalnej przestrzeni nazw: {c*(+/~d<x)%3-+/^d:{"D"$"."/:$|z,y,x+(c*19+x<50)*x<c::100}.'y@/:3 3#.:'$21020101}.
Aaron Davies,
14

Ruby, 115 znaków

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}

Definiuje funkcję, fktóra przyjmuje dwa argumenty: tablicę zawierającą dane wejściowe i „dzisiejszą” datę.

Przykłady:

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
Ventero
źródło
12

Python 2.7 - 172

Używam modułu datetime do ważności i porównywania dat. Jeśli datenie można utworzyć prawidłowej daty i godziny na podstawie danych wejściowych, podnosi ValueError. W ten sposób ssuma dat, które nie wygasły, tjest całkowitą liczbą ważnych dat. Korzystam z faktu, że True == 1do celów dodawania i indeksowania w Pythonie. Zapisuję też postać, używając 25 * (76,80) zamiast (1900,2000).

Zauważ, że linie na drugim poziomie wcięcia używają znaku tabulacji, a nie 2 spacji.

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

Dodaj to do końca, aby przetestować:

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))
Alex L.
źródło
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)
  • Wprowadź jak int[]za pomocą parametru, np

    PS> ./milk.ps1 5,6,7
    
  • Komunikaty o błędach są wyciszane przez try/ catch, o ile nie wiem, czy wyjście na stderr jest dozwolone, czy nie.
  • Używanie +"-1"daty, która jest interpretowana jako .AddDays(-1)przesunięcie bieżącej daty o jeden dzień, dzięki czemu możemy porównać do wczoraj (zamiast tylko dzisiaj). To rozwiązuje problem, że otrzymujemy datę z godziną 0:00, ale musimy porównać ją z datą od dzisiaj.
  • Mocno podkreślony
  • Korzystanie z nowej sztuczki wyciszania błędów, która jest nieco krótsza
Joey
źródło
6

R 269

Spodziewałem się, że będzie to łatwe w R, ale jednocyfrowe lata były dość dużą krzywą. Wydaje mi się, że to może być znacznie lepsze niż obecnie.

lubridatejest pakietem CRAN, być może będziesz musiał go zainstalować 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)}

Zastosowanie: f(c(d1,d2,d3))gdzie c(d1,d2,d3)jest wektorem liczb całkowitych.

np . f(c(6,10,14))zwraca 0.3333333.

lubridatePakiet posiada szereg funkcji otoki dla parsowania dat w różnych zleceń. Używam ich, aby zobaczyć, które formaty generują prawidłowe daty, wyrzucam niepoprawne, a następnie sprawdzam, które jeszcze nie wystąpiły.

Shadowtalker
źródło
6

Mathematica, 163 153 164 bajty

( edycja: ustalono daty poza zakresem 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]]&

Definiuje funkcję, którą możesz wywołać

f[{6,7,5}]

Obecnie odsetek ten nie jest zaokrąglany (oczekiwanie na wyjaśnienie PO).

Tutaj jest nieco przydługi wyjaśnienie, które powinny być zrozumiałe bez wiedzy Mathematica (uwaga, że &czyni wszystko, co z niej zostało anonimowa funkcja, której parametry są określane jako #, #2, #3...):

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

Definiuje funkcję, która zamienia 3 parametry a,b,cw 3 listy {{a,b,c},{c,b,a},{c,a,b}. Zauważ, że ##to tylko sekwencja wszystkich parametrów.

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

Stosowana do daty wygaśnięcia daje listę {y,m,d}dla każdej z trzech możliwych kombinacji.

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

Jest to anonimowa funkcja, która pobiera trzy parametry a,b,ci zwraca listę trzech, z których pierwszy został przekonwertowany na rok zgodnie z podanymi regułami: liczby pomiędzy 50i 99(modulo 100) są zamieniane na rok XX wieku, liczby między 0i 49( modulo 100) zostały przekształcone w rok 21 wieku, wszystkie pozostałe pozostały. Oto ##2sekwencja parametrów zaczynająca się od drugiego, tj b,c.

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

Zastosowane do każdego z trzech poprzednich wyników, to tylko kanonizuje formaty roku. Nazwijmy to, canonicalDatesaby skrócić następujące wyrażenie:

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

To odfiltrowuje nieprawidłowe interpretacje. DateList@dzapewnia pełną {y,m,d,h,m,s}reprezentację różnych formatów dat. Zinterpretuje listy w tej samej kolejności, ale haczyk polega na tym, że można przekazać takie rzeczy, jak {8,2,2006}w takim przypadku, które zostaną obliczone 8 years + 2 months + 2006 days. Sprawdzamy więc, czy pierwsze trzy elementy zwracanej listy są identyczne z danymi wejściowymi (co może się zdarzyć tylko wtedy, gdy miesiąc i dzień w odpowiednich przedziałach).

Aby skrócić następujące wiersze, validDatesodtąd będę odwoływał się do wyniku tego wyrażenia :

DateDifference[#,Date[]]&

Kolejna anonimowa funkcja, która pobiera datę i zwraca różnicę w dniach do dzisiaj (uzyskana z Date[]).

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

Odwzoruj to na prawidłowe interpretacje dat.

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

Kolejna anonimowa funkcja, która podając list ( #), zwraca procent liczb dodatnich na tej liście. To .nie jest mnożenie, ale tylko cyfra dziesiętna, aby w rezultacie uniknąć liczb wymiernych (dostaniesz takie rzeczy 100/3zamiast 33.333- nie wiem, czy to jest problem).

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

Zastosowanie do listy różnic dat daje nam ułamek interpretacji, które jeszcze nie wygasły.

Martin Ender
źródło
Myślę, że niepoprawnie przeliczasz lata takie jak 2999 lub 2099 na 1999.
Ventero,
@Ventero to prawda. Przypuszczam, że mieliśmy do czynienia tylko z latami 1950-2049 (i ich 1 lub 2 cyfrowymi wersjami), ale ponownie czytając wyzwanie, nie ma o tym wzmianki.
Martin Ender
@Ventero naprawiono (ale i tak już znacznie mnie pobiłeś;))
Martin Ender
Jestem zaskoczony, że masz konto na Mathematica, ale nie opublikowałeś żadnych pytań ani odpowiedzi. Czy coś Cię powstrzymuje?
Mr.Wizard
@ Mr.Wizard przepraszam, całkowicie zapomniałem odpowiedzieć na ciebie. Pytania: jak dotąd każdy problem, który miałem, można było rozwiązać za pomocą googlingu / innych pytań SE. Odpowiedzi: Nie wiem ... Chyba nie uważam się za tak sprawnego, jeśli chodzi o produktywne wykorzystanie Mathematiki ... Używam go tylko do szybkich fragmentów tu i tam (i golfa kodowego). Wydaje mi się również, że muszę odpowiadać na pytania, które musiałbym aktywnie oglądać na nowe, aby zobaczyć, na co mogę odpowiedzieć, a obecnie cały mój czas na SE przeznaczam na PPCG. ;) Jeśli chcesz mnie przekonać, że jest inaczej, możesz to zrobić na czacie! :)
Martin Ender
4

JavaScript (E6) 159 164 172

Edytuj Podziękowania dla nderscore za podpowiedzi i za popchnięcie mnie do ponownego myślenia. Zreorganizowano D, unikając parametrów i odcinając niektóre znaki.

Edycja 2 Kolejna sztuczka nderscore, 2 funkcje połączone w 1. Następnie dwa nawiasy usunęły scalone wyrażenia rozdzielone przecinkami w jedno. Czytelność w pobliżu 0. Sidenote: Brak zaokrąglenia może uratować kolejne 2 znaki (| 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

Testuj w konsoli 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)))

Wynik:

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

Nie golfił

NB Funkcja D próbuje utworzyć datę z podanym rokiem, miesiącem, dniem, ale zwraca wartość false, jeśli utworzona data nie jest zgodna z zamierzeniami (! = Dzień lub miesiąc)

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  
)   
edc65
źródło
@nderscore OK dla zmian w D, błąd sintax dla drugiego. Ale i tak zaoszczędził jeszcze więcej
edc65
Dziwne. Coś musiało się stać, kiedy wkleiłem to w komentarzu. Twoje ostatnie optymalizacje sprawiają, że nie ma to jednak znaczenia :)
nderscore
1
Wklejam to, bo nie ufam już komentarzom SE: (-3) pastie.org/private/6bemdweyndcaiseay70kia
nderscore
4

C # w LINQPad - 446 408 272 bajtów

Trzecia edycja: Podziękowania dla Le Canard fou za wskazanie, że data i godzina są prawidłowe, a nie data i godzina. Druga edycja : Dzięki VisualMelon za to sprytne rozwiązanie!

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

Edycja: Dzięki podiluska i edc65 za pomoc w skróceniu kodu! Zauważyłem również, że moje rozwiązanie nie było poprawne, jeśli dane wejściowe roku miały 4 bajty, dlatego załączyłem naprawę tego problemu. Wynik dla tego rozwiązania wynosi 408 bajtów.

Mimo że nie biję żadnej z poprzednich odpowiedzi, nadal chciałem udostępnić moje rozwiązanie C #. Każda pomoc / sugestie są mile widziane! ;)

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

Wersja sformatowana i nie golfowa:

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

Próbowałem stworzyć rozwiązanie, w którym część „DateTime.TryParse” nie jest powtarzana jak w tym rozwiązaniu, ale była o 21 bajtów dłuższa.

Rozwiązanie bez powtarzania „DateTime.TryParse”: 467 bajtów

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

Wersja bez golfa:

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;
    }
tsavinho
źródło
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
sugestia: użyj ternary (? :) jeśli to możliwe zamiast if / else
edc65
1
@ThomasW. Nie sądzę, skoro y ma 2 różne wartości, jeden raz zależy od a, drugi raz zależy od e. W każdym razie dzięki!
tsavinho
1
Usunięcie DateTime.TryParsewywołań było moim pierwszym instynktem, zastąpiłem je lambda, które również przywróciło wartość q. Wykonał także kilka innych kroków ( pastebin ), aby uzyskać 328 znaków: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 Wow, jesteś naprawdę dobry w golfie kodu! Nigdy Action<string>wcześniej nie widziałem , więc mogłem się czegoś od ciebie nauczyć;) udało mi się sprowadzić twoją odpowiedź do 318 znaków, zastępując q.Where(i=>i>=DateTime.Now).Countq.Count(i=>i>=DateTime.Now. Usunąłem też nawiasy, xaby zapisać 2 kolejne postacie!
tsavinho
3

Haskell, 171 165 znaków

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)

Nazwa funkcji to %. Uruchom z datą testu jako krotkę w porządku kanonicznym (y, m, d) z faktycznym rokiem, a pieczęć kartonowa jako krotka z trzech liczb:

λ: (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
MtnViewMark
źródło
2

Erlang, 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).

Funkcją testową byłoby:

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

Nie golfił

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

To rozwiązanie opiera się na listach. Pożycza sztuczkę modulo na rok z rozwiązania Haskell. Służy również calendar:valid_date/1do obsługi niemożliwych dat ze względu na liczbę dni w danym miesiącu (np. „29-2-2” może być tylko w formacie YMD). Ponadto Today jest w date()formacie Erlanga (krotka YMD).

Paul Guyot
źródło
2

APL (85)

Wykorzystuje to niektóre z nowych funkcji Dyalog APL 14, ale nie ma bibliotek zewnętrznych. Dla odmiany działa na TryAPL .

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

Jest to funkcja, która przyjmuje tablicę 3-elementową jako argument po prawej stronie ( ), a datę do sprawdzenia jako argument po lewej stronie ( ) jako liczbę całkowitą YYYYMMDDformatu. Tj. Data 2014-07-09jest reprezentowana jako liczba 20140709.

Test:

      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

Wyjaśnienie:

  • Z←(⊂⌽⍵),(⊂2⌽⍵),⊂⍵: zamień podaną datę na format YMD (⊂⌽⍵), obracając, obracając ją w lewo o 2 (⊂2⌽⍵)lub po prostu nic nie robiąc ⊂⍵. Przynajmniej jedna z nich jest teraz poprawną datą w formacie YMD, może więcej niż jedną, jeśli data jest niejednoznaczna.
  • {∧/12 31≥1↓⍵}¨Z: sprawdź, czy każda data jest ważna: rok (pierwszy element) jest pomijany, a następnie miesiąc nie może być dłuższy niż 12, a dzień nie może być wyższy niż 31.
  • Z/⍨: filtruj prawidłowe daty od Z.
  • {... : dla każdej ważnej daty:
    • ⍵+(99≥⊃⍵)×3↑1900+100×50>⊃⍵: jeśli rok nie jest wyższy niż 99, dodaj 1900, a następnie 100, jeśli rok jest niższy niż 50.
    • (3/100)⊥: dekoduj go tak, jakby to był zbiór liczb podstawowych 100. (Rok jest wyższy niż 100, ale to nie ma znaczenia, ponieważ jest to pierwszy element.) Daje to liczbę dla każdej prawidłowej daty w tym samym formacie, co lewy argument.
  • ⍺≤: dla każdej daty sprawdź, czy nie jest ona mniejsza niż . To da wektor binarny, gdzie 1 oznacza, OKa 0 oznacza spoiled.
  • 100×(+/÷⍴): podziel sumę wektora binarnego przez jego długość i pomnóż przez 100.
marinus
źródło
Zaoszczędź 7 bajtów (i pokonaj K o ładnym marginesie) dzięki splocie i ukrytej funkcji wewnętrznej:{100×(+/÷⍴)⍺≤((3/100)⊥⊢+(99≥⊃)×3↑1900+100×50>⊃)¨Z/⍨{∧/12 31≥1↓⍵}¨Z←(⌽⍵)(2⌽⍵)⍵}
Adám
0

Java: 349 znaków (3 bez spacji)

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

Oto klasa zawierająca, której można użyć do jej przetestowania, w tym (nieco) odśledzoną wersję metody:

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+"%");
   }   
}

To moja pierwsza runda golfa kodowego i myślę, że zorientowałem się, dlaczego zazwyczaj nie widzę zbyt wielu golfistów Java.

shieldgenerator7
źródło
1
Musisz zaakceptować int[]argument jako argument, a nie trzy int.
Joey,
ok, naprawiłem to.
shieldgenerator7
0

C # 287 bajtów

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

Pierwszy raz grałem w golfa, szukając porad. W szczególności usuwanie bajtów z powodu przestrzeni nazw.

Nadużywanie faktu, że wymagana jest tylko funkcja, a nie rzeczywisty program. Ponadto funkcja zawsze powoduje nieprzechwycony wyjątek.

Nie golfił

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); 
        } 
    } 
}
Le Canard fou
źródło
0

Mathematica , 118

Używając kodu m.buettner jako punktu wyjścia, mam kilka ulepszeń:

⌊100Mean@UnitStep@Cases[DateDifference@{If[#<100,Mod[#+50,100]+1950,#],##2}&@@@{#,RotateRight@#,Reverse@#},_Integer]⌋&
Mr.Wizard
źródło
Gra w golfa może być funkcją przyjmującą za argument argument trzy-Int.
algorytmshark
@al algorytmshark Thanks. Nie wiem jak mi tego brakowało. Aktualizacja ...
Mr.Wizard