Ist meine Milch abgelaufen?

98

Oh Mann, dieses Verfallsdatum schreibt die Monate nicht mit Buchstaben! Ich kann nicht sagen , ob es am 10. März auslaufenden ist oder 3. Oktober ... Bitte warten, nein, geschweige denn, das Jahr 2012 sagt (Alley-Oops Ziegel Käse in den Müll Hälfte verwendet wird, kann ein Pro mögen)

Nehmen wir für einen Moment an, Sie sind zu beschäftigt, um zu überlegen, wann dieses Glas Marinara abläuft. Sie möchten nur die Cliff Notes-Version: Wie wahrscheinlich ist es, dass sie überfällig ist? Schreiben wir einen Code!

Sie wissen, dass die Hersteller das Datum als geordnetes Dreifach von ganzen Zahlen in einem von drei Formaten drucken:

YEAR  MONTH DAY
MONTH DAY   YEAR
DAY   MONTH YEAR

Und Sie wissen, dass einige Daten nur auf eine oder zwei Arten interpretiert werden können, nicht alle drei: Die 55 in 55-11-5müssen ein Jahr sein, was bedeutet, dass diese spezielle Box von Twinkies am 5. November 1955 abgelaufen ist. Das Jahr wird manchmal vierstellig und angegeben Nicht zwei, die einige Optionen ausschließen können. Wenn es sich jedoch um zwei Ziffern handelt, bedeutet 50..99 1950..1999 und 0..49 2000..2049.

Ihre Aufgabe ist es, ein Programm oder eine Funktion zu schreiben, die ein Array von Ganzzahlen verwendet, das in mindestens einer der obigen Interpretationen ein gültiges Datum ist, und eine prozentuale Wahrscheinlichkeit ausgibt, dass es immer noch gut ist. Die prozentuale Wahrscheinlichkeit ist einfach der Prozentsatz der gültigen Interpretationen des Datums, die am oder nach dem heutigen Datum liegen.

Das Array von Ganzzahlen ist der [Int]Typ der Länge drei für Ihre Sprache, wenn es sich um ein Argument für eine Funktion handelt, und wird entweder als durch Bindestriche, Schrägstriche oder Leerzeichen getrennte Ganzzahlen (Sie können Ganzzahlen auswählen) angegeben, wenn sie als Eingabe für STDIN für a verwendet werden Volles Programm. *

"Heutiges Datum" kann das aktuelle Datum sein, das über eine Datumsfunktion ermittelt wurde, oder das Datum, das in einem zusätzlichen Argument für die Funktion oder einem zusätzlichen Parameter in STDIN angegeben wurde. Es kann in Unix-Epoche Sekunden sein, ein weiteres Jahr-Monat-Tag-Tripel, das auf eine der drei oben genannten Arten eingegeben wurde, oder eine andere bequemere Art und Weise.

Lassen Sie uns einige Beispiele haben! Die Eingabe des Ablaufdatums erfolgt im strichgetrennten Stil. In den folgenden Beispielen wird davon ausgegangen, dass das heutige Datum der 5. Juli 2006 ist.

  • 14-12-14- Beide gültigen Interpretationen (DMY und YMD) entsprechen dem Stand vom 14. Dezember 2014. Die Ausgabe beträgt 100, da dieses Produkt definitiv noch gut ist.
  • 8-2-2006- Die letzte Zahl ist sicher ein Jahr, da sie vierstellig ist. Dies könnte entweder der 8. Februar (abgelaufen) oder der 2. August (immer noch gut) sein. Die Ausgabe ist 50 .
  • 6-7-5- Das könnte alles sein! Die Interpretation "5. Juli 2006" ist immer noch gut (nur für einen Tag), aber die verbleibenden beiden sind beide im Jahr 2005 und sollten so schnell wie möglich geworfen werden. Die Ausgabe ist 33 .
  • 6-5-7- Hier sind zwei von drei Interpretationen sicher. Sie können Ihre Dezimalstelle auf- oder abrunden, also sind 66 oder 67 beide in Ordnung.
  • 12-31-99- Okay, dieser stammt eindeutig aus der Jahrhundertwende (Jahre von 50 bis 99 sind 19XX, und 31 kann unmöglich ein Monat sein). Eine große fette 0 , und Sie sollten Ihren Kühlschrank wirklich öfter ausräumen.

Sie können davon ausgehen, dass Eingaben, die den oben genannten Standards nicht entsprechen, nicht mit den oben genannten Ausgaberegeln übereinstimmen.

Keine Webanfragen oder Standardlücken. Datumsbearbeitungsbibliotheken sind zulässig. Das ist Codegolf: Möge das kürzeste Programm gewinnen.

* Wenn Sie Brainfuck oder eine ähnlich datentypbehinderte Sprache verwenden, können Sie davon ausgehen, dass die ASCII-Werte der ersten drei Zeichen in der Eingabe die Ganzzahlen für das Datum sind. Dies schließt natürlich die vierstellige Jahreslogik aus, aber ich denke, wir wären zu erstaunt, wenn wir in Brainfuck eine Lösung dafür finden würden, um Sie dafür zu beleidigen.

algorithmshark
quelle
39
Ähm ... das aktuelle Jahr ist 2014, nicht 2006. Ihre Milch ist bestenfalls acht Jahre nach Ablauf.
John Dvorak
11
@JanDvorak Ich wollte mich einfach nicht sehr anstrengen, um aussagekräftige Beispiele zu konstruieren, also habe ich das heutige Datum angepasst, um es einfacher zu machen.
Algorithmushai
7
@ Dgrin91 egal, ich werde sie immer noch essen: D
aditsu
6
In Australien läuft die Milch etwa eine Woche vor dem
Verfallsdatum ab
5
Sie sollten einen Test mit einer 00 hinzufügen, da dies kein gesetzlicher Tag oder Monat sein kann.
MtnViewMark

Antworten:

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}

Rufen Sie mit xof .z.D(ein eingebautes) zum Vergleich mit dem heutigen Tag oder mit einem Datums-Literal Ihrer Wahl auf:

  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

Dies ist im Grunde eine Portierung von @ Alex-ls Python-Lösung, mit einigen zusätzlichen Golf-Tricks:

  • Die Anweisungen zur Neuanordnung sind in einer Zeichenfolge codiert, um ein paar Zeichen zu speichern.
  • Die bedingte Logik (ab) verwendet Wahrheit als Ganzzahl (jedoch anders als die Python-Lösung).
  • Der Gültigkeitstest unterscheidet sich geringfügig - k4 / q parst jeden String problemlos in einen beliebigen Datentyp. es gibt einfach eine Null zurück, wenn es keinen Sinn ergibt. Daher gebe ich eine Liste von Daten aus der inneren Funktion zurück, die null sein kann oder nicht.
  • Das Endergebnis ergibt sich aus der Überprüfung, wie viele der möglichen Datumsinterpretationen null sind und wie viele weniger als das Vergleichsdatum sind. Hierbei ist es wichtig, dass das Nulldatum als kürzer als jedes andere Datum angesehen wird.
Aaron Davies
quelle
1
Sie können ein Zeichen speichern, indem Sie die letzte 0 von entfernen "012201210", da #die Elemente zyklisch übernommen werden. In der Tat, können Sie ein zweites Zeichen auf diese Weise sparen , indem sie die beiden letzten Fällen tauschen: 3 3#.:'"0122102".
Algorithmushai
Rasieren Sie einen weiteren Buchstaben, indem Sie die Args der inneren Funktion umkehren und die Parens speichern (aber eine Rückseite hinzufügen). Kann mir jemand helfen, zwei weitere Zeichen zu retten? APL schlägt mich!
Aaron Davies
Rasiert weitere fünf durch Umschreiben der Mathematik am Ende. Zurück an der Spitze!
Aaron Davies
Und wenn ich bücken ernsthaft nicht-funktionalen Code zu schreiben, kann ich ein weiteres Byte rasiert , indem Sie den globalen Namensraum verschmutzen: {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 Zeichen

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}

Dies definiert eine Funktion f, die zwei Argumente akzeptiert: ein Array, das die Eingabe enthält, und das "heutige" Datum.

Beispiele:

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
quelle
12

Python 2.7 - 172

Ich benutze das datetime-Modul für die Gültigkeit und den Vergleich von Daten. Wenn datedie Eingabe keine gültige Datums- / Uhrzeitangabe enthält, wird sie ausgelöst ValueError. Auf diese Weise sergibt sich die Summe der nicht abgelaufenen Daten und tdie Gesamtzahl der gültigen Daten. Ich nutze die Tatsache, dass True == 1zum Zwecke des Hinzufügens und Indizierens in Python. Ich speichere ein Zeichen auch, indem ich 25 * (76,80) anstelle von (1900,2000) verwende.

Beachten Sie, dass die Zeilen in der zweiten Ebene der Einrückung ein Tabulatorzeichen und keine zwei Leerzeichen enthalten.

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

Fügen Sie dies zum Testen am Ende hinzu:

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
quelle
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)
  • Eingabe wie int[]über Parameter, z

    PS> ./milk.ps1 5,6,7
    
  • Fehlermeldungen werden über try/ stummgeschaltet catch, solange ich nicht weiß, ob die Ausgabe auf stderr erlaubt ist oder nicht.
  • Verwenden Sie +"-1"das Datum, das interpretiert wird .AddDays(-1), um das aktuelle Datum um einen Tag zu verschieben, damit wir es mit dem von gestern vergleichen können (anstatt nur heute). Dies löst das Problem, dass wir ein Datum mit 0:00 als Uhrzeit erhalten, aber mit einem Datum mit der Uhrzeit von heute vergleichen müssen.
  • Mittlerweile stark eingebettet
  • Verwenden Sie einen neuen Trick, um Fehler zu unterdrücken , der viel kürzer ist
Joey
quelle
6

R 269

Ich hatte erwartet, dass dies in R einfach sein würde, aber die einstelligen Jahre waren eine ziemlich große Kurve. Ich denke, das könnte viel besser sein als es ist.

lubridateist ein Paket von CRAN, mit dem Sie es möglicherweise installieren müssen 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)}

Verwendung: f(c(d1,d2,d3))Wo c(d1,d2,d3)ist ein Vektor von ganzen Zahlen.

zB f(c(6,10,14))kehrt zurück 0.3333333.

Das lubridatePaket verfügt über eine Reihe von Wrapper-Funktionen zum Parsen von Datumsangaben in verschiedenen Reihenfolgen. Ich benutze diese, um zu sehen, welche Formate gültige Daten erzeugen, die ungültigen wegwerfen und dann sehen, welche noch nicht aufgetreten sind.

Shadowtalker
quelle
6

Mathematica, 163 153 164 Bytes

( Bearbeiten: feste Daten außerhalb des Bereichs von 1950 bis 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]]&

Dies definiert eine Funktion, die Sie gerne aufrufen können

f[{6,7,5}]

Derzeit ist der Prozentsatz nicht gerundet (warten, bis das OP geklärt ist).

Hier ist eine etwas längere Erklärung , die ohne Mathematica Wissen (Anmerkung , die verständlich sein sollte &alles links davon eine anonyme Funktion , deren Parameter macht , wird als #, #2, #3...):

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

Dies definiert eine Funktion, die 3 Parameter a,b,cin 3 Listen umwandelt {{a,b,c},{c,b,a},{c,a,b}. Beachten Sie, dass dies ##nur eine Folge aller Parameter ist.

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

Auf das Verfallsdatum angewendet, gibt dies eine Liste {y,m,d}für jede der drei möglichen Permutationen.

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

Dies ist eine anonyme Funktion, die drei Parameter verwendet a,b,cund eine Liste der drei zurückgibt, wobei die erste gemäß den angegebenen Regeln in ein Jahr konvertiert wurde: Zahlen zwischen 50und 99(Modulo 100) werden in ein Jahr des 20. Jahrhunderts umgewandelt, Zahlen zwischen 0und 49( modulo 100) werden in ein Jahr des 21. Jahrhunderts verwandelt, alle anderen bleiben mit. Hier ##2ist eine Folge von Parametern beginnend mit dem zweiten, dh b,c.

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

Auf jedes der drei vorherigen Ergebnisse angewendet, kanonisiert dies nur die Jahresformate. Nennen wir dies canonicalDates, um den folgenden Ausdruck abzukürzen:

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

Dadurch werden ungültige Interpretationen herausgefiltert. DateList@dmacht eine vollständige {y,m,d,h,m,s}Darstellung aus verschiedenen Datumsformaten. Es interpretiert Listen in der gleichen Reihenfolge, aber der Haken ist, dass Sie es weitergeben können , wie {8,2,2006}in welchem ​​Fall es berechnet 8 years + 2 months + 2006 days. Wir überprüfen also, ob die ersten drei Elemente der zurückgegebenen Liste mit der Eingabe identisch sind (was nur passieren kann, wenn Monat und Tag in den entsprechenden Bereichen liegen).

Um die folgenden Zeilen zu verkürzen, verweise ich validDatesab sofort auf das Ergebnis dieses Ausdrucks :

DateDifference[#,Date[]]&

Eine weitere anonyme Funktion, die ein Datum annimmt und die Differenz in Tagen zum heutigen Tag zurückgibt (erhalten von Date[]).

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

Ordnen Sie das den gültigen Datumsinterpretationen zu.

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

Eine weitere anonyme Funktion, die bei gegebener list ( #) den Prozentsatz der nicht positiven Zahlen in dieser Liste zurückgibt. Das .ist keine Multiplikation, sondern nur die Dezimalstelle, um rationale Zahlen als Ergebnis zu vermeiden (Sie würden Dinge wie 100/3anstelle von erhalten 33.333- ich weiß eigentlich nicht, ob das ein Problem ist).

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

Bezogen auf die Liste der Datumsunterschiede ergibt dies den Anteil der Interpretationen, die noch nicht abgelaufen sind.

Martin Ender
quelle
Ich denke, Sie konvertieren falsch Jahre wie 2999 oder 2099 bis 1999.
Ventero
@Ventero das stimmt. Ich nahm ein bisschen an, dass wir uns nur mit den Jahren 1950 - 2049 (und ihren ein- oder zweistelligen Versionen) befassten, aber als ich die Herausforderung noch einmal las, gab es keinen Hinweis darauf.
Martin Ender
@Ventero behoben (aber Sie hatten mich ohnehin schon deutlich geschlagen;))
Martin Ender
Ich bin überrascht zu sehen, dass Sie einen Account bei Mathematica haben, aber keine Fragen oder Antworten gepostet haben. Hält dich etwas zurück?
Mr.Wizard
@ Mr.Wizard sorry, habe total vergessen auf dich zu antworten. Fragen: Bisher konnte jedes Problem, das ich hatte, mit Googeln / anderen SE-Fragen gelöst werden. Antwort: Ich weiß es nicht ... Ich glaube , ich mache mich nicht so sehen , dass beherrschen , wenn sie produktiv mit Mathematica kommen ... Ich kann es nur nutzen für schnelle Schnipsel hier und dort (und Code - Golf). Ich schätze, um Fragen zu beantworten, müsste ich mir aktiv neue ansehen, um zu sehen, was ich beantworten kann, und momentan ist meine gesamte SE-Zeit für PPCG reserviert. ;) Wenn du mich sonst überzeugen willst, kannst du das gerne im Chat tun! :)
Martin Ender
4

JavaScript (E6) 159 164 172

Edit Danke an nderscore für die Hinweise und dafür, dass ich zum Nachdenken angeregt habe. Reorganisation von D unter Vermeidung von Parametern und Abschneiden von Zeichen.

Edit 2 Ein weiterer Trick von nderscore, bei dem 2 Funktionen zu 1 zusammengeführt wurden. Dann wurden zwei Klammern entfernt, um kommagetrennte Ausdrücke zu einem zusammenzuführen. Lesbarkeit in der Nähe von 0. Nebenbemerkung: Durch Nichtrunden können weitere 2 Zeichen (| 0) eingespart werden.

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

Test In FireFox Konsole

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

Ausgabe:

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

Ungolfed

NB D-Funktion versucht, ein Datum mit einem bestimmten Jahr, Monat oder Tag zu erstellen, gibt jedoch false zurück, wenn das Erstellungsdatum nicht der beabsichtigten Zeit entspricht (! = Tag oder Monat).

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
quelle
@nderscore OK für Änderungen in D, sintax error für den anderen. Aber trotzdem noch mehr gespart
edc65
Seltsam. Es muss etwas passiert sein, als ich es in den Kommentar eingefügt habe. Ihre letzten Optimierungen machen es jedoch irrelevant :)
nderscore
1
Fügen Sie dies in eine Paste ein, da ich den Kommentaren von SE nicht mehr vertraue: (-3) pastie.org/private/6bemdweyndcaiseay70kia
nderscore
4

C # in LINQPad - 446 408 272 Bytes

Dritte Änderung: Vielen Dank an Le Canard fou, der darauf hingewiesen hat, dass DateTime.Today korrekt ist und nicht DateTime.Now. Second Edit: Danke VisualMelon für diese clevere Lösung!

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

Edit: Danke an podiluska und edc65, die mir geholfen haben, den Code zu verkürzen! Ich bemerkte auch, dass meine Lösung nicht korrekt war, wenn die Eingabe für das Jahr 4 Byte lang war. Deshalb habe ich das Problem behoben. Die Punktzahl für diese Lösung beträgt 408 Bytes.

Auch wenn ich keine der vorherigen Antworten geschlagen habe, wollte ich dennoch meine C # -Lösung freigeben. Hilfe / Vorschläge sind willkommen! ;)

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

Formatierte und ungolfierte Version:

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

Ich habe versucht, eine Lösung zu finden, bei der das "DateTime.TryParse" -Teil nicht wie in dieser Lösung wiederholt wird, aber 21 Byte länger ist.

Lösung ohne Wiederholung von "DateTime.TryParse": 467 Bytes

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

Ungolfed-Version:

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
quelle
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
vorschlag: benutze ternary (? :) wenn möglich anstatt if / else
edc65 07.07.14
1
@ThomasW. Ich glaube nicht, dass y 2 verschiedene Werte hat, einmal ist es abhängig von a, das andere Mal ist es abhängig von e. Danke trotzdem!
Tsavinho
1
Das Entfernen der DateTime.TryParseAnrufe war mein erster Instinkt und ersetzte es durch ein Lambda, das auch den Wert zurück in q setzte. Führen Sie auch einige andere Schritte ( Pastebin ) aus, um 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();}
Zeichen
1
@VisualMelon Wow, du bist wirklich gut im Code-Golfen! Ich sah nie Action<string>vor, so konnte ich etwas von Ihnen lernen;) ich in der Lage war zu 318 Zeichen Ihre Antwort unten zu erhalten durch Ersetzen q.Where(i=>i>=DateTime.Now).Countmit q.Count(i=>i>=DateTime.Now. Ich habe auch die Klammern entfernt, xdamit ich 2 weitere Zeichen speichern kann!
Tsavinho
3

Haskell, 171 165 Zeichen

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)

Der Name der Funktion lautet %. Führen Sie das Testdatum als Tupel in kanonischer (y, m, d) Reihenfolge mit dem tatsächlichen Jahr und dem Kartonstempel als Tupel mit drei Zahlen aus:

λ: (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
quelle
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).

Testfunktion wäre:

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

Ungolfed

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

Diese Lösung basiert auf Listenverständnissen. Es leiht den Modulo-Trick für das Jahr aus der Haskell-Lösung. Es wird auch verwendet calendar:valid_date/1, um unmögliche Daten aufgrund der Anzahl der Tage in einem bestimmten Monat zu verarbeiten (z. B. "29-2-2" kann nur im YMD-Format sein). Außerdem ist Today im Erlang- date()Format (ein YMD-Tupel).

Paul Guyot
quelle
2

APL (85)

Dies verwendet einige der neuen Funktionen von Dyalog APL 14, jedoch keine externen Bibliotheken. Zur Abwechslung funktioniert es auf TryAPL .

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

Dies ist eine Funktion, die das Array mit 3 Elementen als Argument für die rechte Seite ( ) und das zu überprüfende Datum als Argument für die linke Seite ( ) als Ganzzahl des YYYYMMDDFormats verwendet. Das heißt, das Datum 2014-07-09wird als Zahl dargestellt 20140709.

Prüfung:

      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

Erläuterung:

  • Z←(⊂⌽⍵),(⊂2⌽⍵),⊂⍵: Verwandle das angegebene Datum in das YMD-Format, indem du (⊂⌽⍵)es um 2 nach links drehst (⊂2⌽⍵)oder einfach nichts tust ⊂⍵. Mindestens eines davon ist jetzt ein richtiges Datum im YMD-Format, möglicherweise mehr als eins, wenn das Datum nicht eindeutig ist.
  • {∧/12 31≥1↓⍵}¨Z: Testen Sie, ob jedes Datum gültig ist: Das Jahr (erstes Element) wird gelöscht, und dann darf der Monat nicht höher als 12 und der Tag nicht höher als 31 sein.
  • Z/⍨: Filter die gültigen Daten von Z.
  • {... : für jedes gültige Datum:
    • ⍵+(99≥⊃⍵)×3↑1900+100×50>⊃⍵: Wenn das Jahr nicht höher als 99 ist, addieren Sie 1900 und 100, wenn das Jahr niedriger als 50 ist.
    • (3/100)⊥: decodiere es, als ob es eine Menge von Basis-100-Zahlen wäre. (Das Jahr ist höher als 100, aber das spielt keine Rolle, da es das erste Element ist.) Dies gibt eine Zahl für jedes gültige Datum im gleichen Format wie das linke Argument an.
  • ⍺≤: Überprüfen Sie für jedes Datum, ob es nicht kleiner als ist . Dies ergibt einen binären Vektor, wobei 1 bedeutet OKund 0 bedeutet spoiled.
  • 100×(+/÷⍴): Teilen Sie die Summe des binären Vektors durch seine Länge und multiplizieren Sie mit 100.
Marinus
quelle
Sparen Sie 7 Bytes (und schlagen Sie K mit einem schönen Vorsprung), indem Sie verseilen und eine innere Funktion implizieren:{100×(+/÷⍴)⍺≤((3/100)⊥⊢+(99≥⊃)×3↑1900+100×50>⊃)¨Z/⍨{∧/12 31≥1↓⍵}¨Z←(⌽⍵)(2⌽⍵)⍵}
Adám
0

Java: 349 Zeichen (3 ohne Leerzeichen)

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

Hier ist eine enthaltene Klasse, die zum Testen verwendet werden kann, einschließlich einer (leicht) entgolften Version der Methode:

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

Dies ist meine erste Runde Codegolf, und ich glaube, ich habe herausgefunden, warum ich normalerweise nicht sehr viele Java-Golfer sehe.

Schildgenerator7
quelle
1
Sie müssen ein int[]Argument als Argument akzeptieren , nicht drei int.
Joey
ok, ich habe es behoben.
Shieldgenerator7
0

C # 287 Bytes

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

Das erste Mal Golf spielen, auf der Suche nach Ratschlägen. Insbesondere das Entfernen von Bytes aufgrund von Namespace.

Missbrauch der Tatsache, dass nur eine Funktion erforderlich ist, kein tatsächliches Programm. Außerdem führt die Funktion immer zu einer nicht erfassten Ausnahme.

Ungolfed

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
quelle
0

Mathematica , 118

Mit dem Code von m.buettner als Ausgangspunkt habe ich ein paar Verbesserungen:

⌊100Mean@UnitStep@Cases[DateDifference@{If[#<100,Mod[#+50,100]+1950,#],##2}&@@@{#,RotateRight@#,Reverse@#},_Integer]⌋&
Mr.Wizard
quelle
Der Golf kann eine Funktion sein, die eine Drei-Int-Liste als Argument verwendet.
Algorithmushai
@algorithmshark Danke. Ich weiß nicht, wie ich das verpasst habe. Aktualisierung ...
Mr.Wizard