[Question]
  [
*Aww, man, this expiry date doesn't write the months with letters! I can't tell if it's expiring on March 10th or October 3rd... Wait, no, never mind, the year says 2012. **(alley-oops half-used brick of cheese into the trash can like a pro)***
So let's suppose for a moment that you're too busy to try to reason out when this jar of marinara is supposed to expire. You just want the Cliff Notes version: how likely is it that it's past due? Let's write some code!
You know that the manufacturers print the date as an ordered triple of integers, in one of three formats:
```
YEAR  MONTH DAY
MONTH DAY   YEAR
DAY   MONTH YEAR
```
And you know that some dates can only be interpreted in one or two ways, not all three: the 55 in `55-11-5` has to be a year, meaning this particular box of Twinkies expired November 5th, 1955. The year is sometimes given in four digits and not two, which can rule out some options. When it's two digits, though, 50..99 means 1950..1999 and 0..49 means 2000..2049.
Your job is to write a program or function that takes an array of integers which is a valid date in at least one of the interpretations above, and outputs a percent chance it is still good. The percent chance is simply the percentage of valid interpretations of the date that are **on or later** than today's date.
The array of integers will be your language's `[Int]` type of length three if it is an argument to a function, and given as either dash-, slash-, or space-separated (you get to pick) integers if used as input on STDIN to a full program.\*
"Today's date" can be today's actual date, as obtained through a date function, or the date given in an extra argument to function or extra paramater in STDIN. It may be in Unix epoch seconds, another year-month-day triple entered in one of the three ways above, or another more convenient fashion.
Let's have some examples! The expiry date input will be in the dash-separated style, and assume for the examples below that today's date is July 5th, 2006.
* `14-12-14` - Both valid interpretations for this (DMY and YMD) are equivalent, December 14, 2014. The output is **100** because this product is definitely still good.
* `8-2-2006` - The last number is a year, for sure, since it has four digits. This could be either February 8th (expired) or August 2nd (still good). The output is **50**.
* `6-7-5` - This could be anything! The "July 5th, 2006" interpretation is still good (for one day only), but the remaining two are both in 2005 and should be tossed as quickly as possible. The output is **33**.
* `6-5-7` - Here, two out of three interpretations are safe. You can round your decimal up or down, so **66** or **67** are both okay.
* `12-31-99` - Okay, this one is unambiguously from the turn of the century (years from 50 to 99 are 19XX, and 31 can't possibly be a month). A big fat **0**, and you really should clean out your fridge more often.
You can safely assume that any input which does not meet the standards above is not privy to the output rules above.
No web requests or standard loopholes. Date handling libraries are allowed. This is code golf: may the shortest program win.
\* If you are using brainfuck or some similarly datatype-handicapped language, you can assume the ASCII values of the first three characters in input are the integers for the date. This excludes the four-digit year logic, sure, but I think we would be too astounded by seeing a solution to this in Brainfuck to slight you for it.
  
[Answer]
## Ruby, 115 characters
```
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}
```
This defines a function `f` that takes two arguments: an array containing the input, and "today's" date.
Examples:
```
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
```
[Answer]
# Python 2.7 - 172
I use the datetime module for validity and comparison of dates. If `date` can't make a valid datetime out of the input, it raises `ValueError`. This way `s` is the sum of the non-expired dates and `t` is the total number of valid dates. I'm taking advantage of the fact that `True == 1` for the purposes of addition and indexing in Python. I also save a character by using 25\*(76,80) instead of (1900,2000).
Note the lines in the second level of indentation use a tab character, not 2 spaces.
```
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
```
Add this to the end to test:
```
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))
```
[Answer]
## 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)
```
* Input as `int[]` via parameter, e.g.
```
  PS> ./milk.ps1 5,6,7
```
* Error messages are silenced via `try`/`catch`, as long as I don't know whether output on stderr is allowed or not.
* Using `+"-1"` on the date, which gets interpreted as `.AddDays(-1)` to shift the current date by one day, so that we can compare to yesterday (instead of just today). This solves the problem that we get a date with 0:00 as time but need to compare with a date with time from today.
* Heavily inlined by now
* Using [a new trick for silencing errors](https://codegolf.stackexchange.com/a/33113/15) that's quite a bit shorter
[Answer]
## R, 269
I was expecting this to be easy in R, but the single-digit years were a pretty big curveball. I feel like this could be much better than it is.
`lubridate` is a package from CRAN, you might need to install it with `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)}
```
Usage: `f(c(d1,d2,d3))` where `c(d1,d2,d3)` is a vector of integers.
e.g.
`f(c(6,10,14))` returns `0.3333333`.
The `lubridate` package has a series of wrapper functions for parsing dates in different orders. I use these to see which formats produce valid dates, throw out the invalid ones, and then see which ones haven't occurred yet.
[Answer]
## Mathematica, ~~163~~ ~~153~~ 164 bytes
(*edit:* fixed dates outside the 1950 - 2049 range)
```
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]]&
```
This defines a function which you can call like
```
f[{6,7,5}]
```
Currently, the percentage isn't rounded (waiting for the OP to clarify).
Here is a slightly lengthy explanation that should be understandable without any Mathematica knowledge (note that `&` makes everything left of it an anonymous function whose parameters are referred to as `#`, `#2`, `#3`...):
```
{{##},{#3,#2,#},{#3,#,#2}}&
```
This defines a function, which turns 3 parameters `a,b,c` into 3 lists `{{a,b,c},{c,b,a},{c,a,b}`. Note that `##` is just a sequence of all parameters.
```
{{##},{#3,#2,#},{#3,#,#2}}&@@#
```
Applied to the expiry date, this gives a list of `{y,m,d}` for each of the three possible permutations.
```
{If[#<100,Mod[#+50,100]+1950,#],##2}&
```
This is an anonymous function that takes three parameters `a,b,c` and returns a list of the three, where the first has been converted to a year as per the given rules: numbers between `50` and `99` (modulo `100`) are turned into a 20th century year, numbers between `0` and `49` (modulo `100`) are turned into a 21st century year, all others are left along. Here, `##2` is a sequence of parameters starting with the second one, i.e. `b,c`.
```
{If[#<100,Mod[#+50,100]+1950,#],##2}&@@@{{##},{#3,#2,#},{#3,#,#2}}&@@#
```
Applied to each of the three previous results, this just canonicalises the year formats. Let's call this `canonicalDates` to shorten the following expression:
```
Cases[canonicalDates,d_/;DateList@d~Take~3==d]
```
This filters out invalid interpretations. `DateList@d` makes a full `{y,m,d,h,m,s}` representation out of various date formats. It will interpret lists in the same order, but the catch is that you *can* pass it things like `{8,2,2006}` in which case it will calculate `8 years + 2 months + 2006 days`. So we check that the first three elements of the returned list are identical to the input (which can only happen if the month and day in the appropriate ranges).
To shorten the following lines, I'll refer to the result of that expression as `validDates` from now on:
```
DateDifference[#,Date[]]&
```
Another anonymous function which takes a date and returns the difference in days to today (obtained from `Date[]`).
```
DateDifference[#,Date[]]&/@validDates
```
Map that onto the valid date interpretations.
```
100.Count[#,x_/;x<1]/Length@#&
```
Yet another anonymous function which, given a list (`#`), returns the percentage of non-positive numbers in that list. The `.` is not a multiplication but just the decimal digit, to avoid rational numbers as the result (you'd get things like `100/3` instead of `33.333` - I don't actually know if that's a problem).
```
100.Count[#,x_/;x<1]/Length@#&[DateDifference[#,Date[]]&/@validDates]
```
Applied to the list of date differences, this gives us the fraction of interpretations which are not yet expired.
[Answer]
# k4 ~~(90)~~ ~~(88)~~ ~~(87)~~ (82)
```
{100*(+/~d<x)%3-+/^d:{"D"$"."/:$|z,y,x+(x<100)*100*19+x<50}.'y@/:3 3#.:'$21020101}
```
Invoke with `x` of `.z.D` (a builtin) for comparison to today, or a date literal of your choice otherwise:
```
  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
```
This is basically a port of @Alex-l's Python solution, with a few miscellaneous golfing tricks added:
* The rearrangement instructions are encoded in a string to save a couple characters.
* The conditional logic (ab)uses truth-as-integer (but in a different way from the Python solution).
* The validity test is slightly different--k4/q will happily parse any string into any datatype; it simply returns a null if it can't make sense of it. Thus, I return a list of dates from the inner function, which may or may not be null.
* The final result comes from checking how many of the possible date interpretations are null vs. how many are less than the comparison date; it's important here that the null date is considered less than any other date.
[Answer]
# JavaScript (E6) 159 ~~164 172~~
**Edit** Thanks to nderscore for the hints and for pushing me to think again. Reorganized D avoiding parameters and cutting some chars.
**Edit 2** Another trick by nderscore, 2 functions merged into 1. Then two parenthesis removed merging comma separated expressions into one. Readability near 0. Sidenote: Not rounding could save another 2 chars (|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
```
**Test** In FireFox console
```
;[[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)))
```
Output:
```
["14,12,14 100", "8,2,2006 50", "6,7,5 33", "6,5,7 66", "12,31,99 0"]
```
**Ungolfed**
NB D function tries to create a Date with given year, month, day but returns false if the created date is not what was intented (!= day or month)
```
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  
)   
```
[Answer]
# C# in LINQPad - 446 408 272 Bytes
**Third Edit:** Thanks to Le Canard fou for pointing out that DateTime.Today is correct, not DateTime.Now.
**Second Edit:** Thanks VisualMelon for this clever solution!
```
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:** Thanks to podiluska and edc65 for helping me shorting the code! I also noticed that my solution wasn't correct if the year input was 4 bytes long, therefore I included the fix for that problem. The score for this solution is **408 Bytes.**
Even though I'm not beating any of the previous answers, I still wanted to share my C# solution. Any help/suggestions are appreciated! ;)
```
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();}
```
Formatted and ungolfed 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();
    }
```
I tried to make a solution where the "DateTime.TryParse"-Part isn't repeated as in this solution, but it was 21 bytes longer.
**Solution without repeating "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;
    }
```
[Answer]
## Haskell, 171 165 characters
```
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)
```
The function's name is `%`. Run with the test date as an tuple in canonical (y,m,d) order with actual year, and the carton stamp as a tuple of three numbers:
```
λ: (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
```
[Answer]
# 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).
```
Test function would be:
```
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).
```
This solution relies on list comprehensions. It borrows the modulo trick for the year from the Haskell solution. It also uses `calendar:valid_date/1` to handle impossible dates because of the number of days in a given month (e.g. "29-2-2" can only be in YMD format). Also, Today is in Erlang's `date()` format (a YMD tuple).
[Answer]
## APL (85)
This uses some of Dyalog APL 14's new functions, but no external libraries. For a change, it works on [TryAPL](http://www.tryapl.org).
```
{100×(+/÷⍴)⍺≤{(3/100)⊥⍵+(99≥⊃⍵)×3↑1900+100×50>⊃⍵}¨Z/⍨{∧/12 31≥1↓⍵}¨Z←(⊂⌽⍵),(⊂2⌽⍵),⊂⍵}
```
This is a function that takes the 3-element array as its right side (`⍵`) argument, and the date to check against as its left side (`⍺`) argument, as an integer of `YYYYMMDD` format. I.e., the date `2014-07-09` is represented as the number `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
```
Explanation:
* `Z←(⊂⌽⍵),(⊂2⌽⍵),⊂⍵`: turn the given date into Y-M-D format by flipping `(⊂⌽⍵)`, rotating it to the left by 2 `(⊂2⌽⍵)`, or just doing nothing `⊂⍵`. At least one of these is now a proper date in Y-M-D format, maybe more than one if the date is ambiguous.
* `{∧/12 31≥1↓⍵}¨Z`: test if each date is valid: the year (first element) is dropped, and then the month must be no higher than 12 and the day must be no higher than 31.
* `Z/⍨`: filter the valid dates from `Z`.
* `{`...`}¨`: for each valid date:
	+ `⍵+(99≥⊃⍵)×3↑1900+100×50>⊃⍵`: if the year is not higher than 99, add 1900, then 100 if the year is lower than 50.
	+ `(3/100)⊥`: decode it as if it were a set of base-100 numbers. (The year is higher than 100, but this doesn't matter as it's the first element.) This gives a number for each valid date in the same format as the left argument.
* `⍺≤`: for each date, see if it is not smaller than `⍺`. This will give a binary vector where 1 means `OK` and 0 means `spoiled`.
* `100×(+/÷⍴)`: divide the sum of the binary vector by its length and multiply by 100.
[Answer]
## **Java: 349 Characters (3 w/o spaces)**
```
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;}
```
Here is a containing class that can be used to test it, including a (slightly) degolfed version of the method:
```
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+"%");
   }   
}
```
This is my first round of code golf, and I think I figured out why I don't usually see very many Java golfers.
[Answer]
# 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);}}}
```
First time golfing, looking for advices. Notably, removing bytes due to namespace.
Abusing the fact that only a function is required, not an actual program. Also, the function always results in an uncaught exception.
**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); 
        } 
    } 
}
```
[Answer]
## *Mathematica*, 118
Using m.buettner's code as a starting point I have a few improvements:
```
⌊100Mean@UnitStep@Cases[DateDifference@{If[#<100,Mod[#+50,100]+1950,#],##2}&@@@{#,RotateRight@#,Reverse@#},_Integer]⌋&
```
]