Mon lait a-t-il expiré?

98

Aww, mec, cette date d'expiration n'écrit pas les mois avec des lettres! Je ne peux pas dire si elle expire le 10 mars ou le 3 octobre ... Attendez, non, ça ne fait rien, l'année 2012 est en cours .

Supposons donc un instant que vous soyez trop occupé pour essayer de raisonner quand ce pot de marinara est censé expirer. Vous voulez juste la version de Cliff Notes: quelle est la probabilité qu'il soit en retard? Ecrivons du code!

Vous savez que les fabricants impriment la date sous la forme d'un triple ordonné d'entiers, dans l'un des trois formats suivants:

YEAR  MONTH DAY
MONTH DAY   YEAR
DAY   MONTH YEAR

Et vous savez que certaines dates ne peuvent être interprétées que d'une ou deux manières, pas toutes les trois: le 55 dans 55-11-5doit être une année, ce qui signifie que cette boîte particulière de Twinkies a expiré le 5 novembre 1955. L'année est parfois donnée en quatre chiffres et pas deux, ce qui peut exclure certaines options. Quand il s'agit de deux chiffres, 50..99 signifie 1950..1999 et 0..49 signifie 2000..2049.

Votre travail consiste à écrire un programme ou une fonction qui prend un tableau d’entiers qui est une date valide dans au moins une des interprétations ci-dessus, et génère un pourcentage de chance qu’il soit toujours bon. Le pourcentage de chance est simplement le pourcentage d'interprétations valides de la date qui sont postérieures ou postérieures à la date du jour.

Le tableau d’entiers sera le [Int]type de longueur trois de votre langue s’il s’agit d’un argument pour une fonction et est indiqué sous la forme d’entiers entiers séparés par un tiret, une barre oblique ou un espace (vous devez choisir) s’il est utilisé comme entrée sur STDIN programme complet. *

La "date du jour" peut être la date du jour, obtenue via une fonction de date, ou la date indiquée dans un argument supplémentaire à function ou un paramètre supplémentaire dans STDIN. Il peut s’agir de secondes d’époque Unix, d’un autre triplet année-mois-jour entré d’une des manières ci-dessus, ou d’une autre manière plus pratique.

Ayons des exemples! La date d'expiration entrée sera dans le style séparé par tiret, et supposons pour les exemples ci-dessous que la date d'aujourd'hui est le 5 juillet 2006.

  • 14-12-14- Les deux interprétations valides pour cela (JJ et AMJ) sont équivalentes, le 14 décembre 2014. Le résultat est 100, car ce produit est définitivement bon.
  • 8-2-2006- Le dernier chiffre est un an, bien sûr, puisqu'il comporte quatre chiffres. Cela pourrait être soit le 8 février (expiré) ou le 2 août (toujours bon). La sortie est 50 .
  • 6-7-5- Cela pourrait être n'importe quoi! L’interprétation du "5 juillet 2006" est toujours valable (pour une journée seulement), mais les deux autres sont toutes les deux en 2005 et devraient être lancées le plus rapidement possible. La sortie est 33 .
  • 6-5-7- Ici, deux interprétations sur trois sont sans danger. Vous pouvez arrondir votre décimale vers le haut ou le bas. 66 ou 67 sont donc acceptables.
  • 12-31-99- D'accord, celui-ci est sans équivoque depuis le début du siècle (les années 50 à 99 sont 19XX et 31 ne peuvent pas être d'un mois). Un gros gros 0 , et vous devriez vraiment nettoyer votre réfrigérateur plus souvent.

Vous pouvez sans risque supposer que toute entrée qui ne répond pas aux normes ci-dessus n'est pas au courant des règles de sortie ci-dessus.

Pas de demandes Web ou de lacunes standard. Les bibliothèques de traitement de date sont autorisées. C'est du code golf: que le programme le plus court gagne.

* Si vous utilisez brainfuck ou un langage similaire handicapé par les types de données, vous pouvez supposer que les valeurs ASCII des trois premiers caractères en entrée sont les entiers de la date. Cela exclut la logique des années à quatre chiffres, bien sûr, mais je pense que nous serions trop étonnés de voir une solution à cela dans Brainfuck pour vous en vouloir.

algorithmeshark
la source
39
Umm ... l'année en cours est 2014, pas 2006. Votre lait a au mieux expiré huit ans.
John Dvorak
11
@ JanDvorak Je ne voulais tout simplement pas essayer très fort de construire des exemples significatifs, j'ai donc modifié la date du jour pour faciliter les choses.
algorithmshark
7
@ Dgrin91 m'en fous, je vais quand même les manger: D
aditsu
6
En Australie, le lait expire environ une semaine avant la date limite de
consommation
5
Vous devez ajouter un test avec un 00, car cela ne peut pas être un jour ou un mois légal.
MtnViewMark

Réponses:

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}

Invoke avec xde .z.D(un builtin) à titre de comparaison à aujourd'hui, ou une date littérale de votre choix autrement:

  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

Ceci est fondamentalement un port de la solution Python @ Alex-l, avec quelques astuces de golf diverses ajoutées:

  • Les instructions de réarrangement sont codées dans une chaîne pour enregistrer quelques caractères.
  • La logique conditionnelle (ab) utilise la vérité en tant qu'entier (mais d'une manière différente de la solution Python).
  • Le test de validité est légèrement différent - k4 / q analysera avec plaisir toute chaîne dans n'importe quel type de données; il retourne simplement un null s'il ne peut pas en comprendre le sens. Ainsi, je retourne une liste de dates de la fonction interne, qui peuvent ou non être nulles.
  • Le résultat final provient de la vérification du nombre d'interprétations de date possibles qui sont nulles par rapport à celles qui sont inférieures à la date de comparaison; il est important ici que la date nulle soit considérée comme inférieure à toute autre date.
Aaron Davies
la source
1
Vous pouvez enregistrer un caractère en supprimant le dernier 0 de "012201210", car #prend ses éléments de manière cyclique. En fait, vous pouvez enregistrer une deuxième ombles de cette façon en échangeant les deux derniers cas: 3 3#.:'"0122102".
algorithmshark
Rasé encore un caractère en inversant les arguments de fonction interne, en sauvant les parenthèses (mais en ajoutant un revers). Quelqu'un peut-il m'aider à sauver deux autres personnages? APL me bat!
Aaron Davies
Rasé cinq autres en réécrivant les maths à la fin. De retour en tête!
Aaron Davies
Et si je me penche pour l' écriture de code sérieusement non fonctionnel, je peux raser un autre octet en polluant l'espace de noms global: {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 caractères

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}

Ceci définit une fonction fqui prend deux arguments: un tableau contenant l'entrée et la date "aujourd'hui".

Exemples:

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
la source
12

Python 2.7 - 172

J'utilise le module datetime pour la validité et la comparaison des dates. Si datevous ne pouvez pas créer une date / heure valide à partir de l'entrée, elle se déclenche ValueError. Cette manière scorrespond à la somme des dates non expirées et tau nombre total de dates valides. Je profite du fait que True == 1pour l'ajout et l'indexation en Python. Je sauve également un personnage en utilisant 25 * (76,80) au lieu de (1900,2000).

Notez que les lignes du deuxième niveau d'indentation utilisent un caractère de tabulation, pas deux espaces.

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

Ajoutez ceci à la fin pour tester:

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
la source
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)
  • Entrée comme int[]paramètre via, par exemple

    PS> ./milk.ps1 5,6,7
    
  • Les messages d'erreur sont désactivés via try/ catch, tant que je ne sais pas si la sortie sur stderr est autorisée ou non.
  • Utilisation +"-1"de la date, ce qui est interprété de manière .AddDays(-1)à décaler la date du jour d’un jour, afin que nous puissions nous comparer à hier (au lieu d’aujourd’hui). Cela résout le problème que nous obtenons une date avec 0:00 comme heure, mais devons comparer avec une date avec l'heure d'aujourd'hui.
  • Fortement en ligne maintenant
  • Utiliser une nouvelle astuce pour réduire les erreurs au silence est un peu plus courte
Joey
la source
6

R, 269

Je m'attendais à ce que ce soit facile en R, mais les années à un chiffre étaient une courbe assez grosse. Je sens que cela pourrait être beaucoup mieux que ce qu'il est.

lubridateest un paquet du CRAN, vous devrez peut-être l'installer avec 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)}

Utilisation: f(c(d1,d2,d3))c(d1,d2,d3)est un vecteur d'entiers.

par exemple, les f(c(6,10,14))retours 0.3333333.

Le lubridatepaquet a une série de fonctions d'encapsulation pour analyser les dates dans différents ordres. J'utilise ceux-ci pour voir quels formats produisent des dates valides, jettent les non valides, puis quels sont ceux qui ne se sont pas encore produits.

shadowtalker
la source
6

Mathematica, 163 153 164 octets

( edit: dates fixes en dehors de la plage 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]]&

Ceci définit une fonction que vous pouvez appeler comme

f[{6,7,5}]

Actuellement, le pourcentage n'est pas arrondi (en attendant que le PO clarifie).

Voici une explication un peu de longue haleine qui devrait être compréhensible sans aucune connaissance Mathematica (notez que &fait tout en reste une fonction anonyme dont les paramètres sont appelés #, #2, #3...):

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

Ceci définit une fonction qui transforme 3 paramètres a,b,cen 3 listes {{a,b,c},{c,b,a},{c,a,b}. Notez que ce ##n'est qu'une séquence de tous les paramètres.

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

Appliqué à la date d'expiration, ceci donne une liste de {y,m,d}pour chacune des trois permutations possibles.

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

C'est une fonction anonyme qui prend trois paramètres a,b,cet renvoie une liste des trois, le premier ayant été converti en année selon les règles données: les nombres entre 50et 99(modulo 100) sont transformés en une année du 20ème siècle, les nombres entre 0et 49(( modulo 100) sont transformés en une année du 21ème siècle, tous les autres sont laissés. Voici ##2une séquence de paramètres commençant par le second, à savoir b,c.

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

Appliqué à chacun des trois résultats précédents, ceci canonise juste les formats d'année. Appelons cela canonicalDatespour raccourcir l'expression suivante:

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

Ceci filtre les interprétations non valides. DateList@dfait une {y,m,d,h,m,s}représentation complète à partir de divers formats de date. Il interprétera les listes dans le même ordre, mais le problème est que vous pouvez lui transmettre des informations telles que, {8,2,2006}dans ce cas, le calcul est effectué 8 years + 2 months + 2006 days. Nous vérifions donc que les trois premiers éléments de la liste renvoyée sont identiques à ceux de l’entrée (ce qui ne peut se produire que si le mois et le jour figurent dans les plages appropriées).

Pour raccourcir les lignes suivantes, je ferai référence au résultat de cette expression à validDatespartir de maintenant:

DateDifference[#,Date[]]&

Une autre fonction anonyme qui prend une date et retourne la différence en jours à aujourd'hui (obtenue à partir de Date[]).

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

Mappez cela sur les interprétations de date valides.

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

Encore une autre fonction anonyme qui, à partir d’une liste ( #), retourne le pourcentage de nombres non positifs dans cette liste. Le résultat .n’est pas une multiplication mais juste un chiffre décimal, afin d’éviter des nombres rationnels (vous obtiendrez des choses comme 100/3au lieu de 33.333- je ne sais pas vraiment si cela pose un problème).

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

Appliqué à la liste des différences de dates, cela nous donne la fraction d'interprétations non encore expirées.

Martin Ender
la source
Je pense que vous convertissez incorrectement des années comme 2999 ou 2099 en 1999.
Ventero
@ Ventero c'est vrai. J'avais un peu supposé que nous ne traitions que des années 1950 à 2049 (et leurs versions à 1 ou 2 chiffres), mais relire le défi ne fait aucune mention de cela.
Martin Ender
@Ventero corrigé (mais vous m'aviez déjà battu de façon significative de toute façon;))
Martin Ender
Je suis surpris de voir que vous avez un compte sur Mathematica mais que vous n'avez posté aucune question ou réponse. Est-ce que quelque chose vous retient?
Mr.Wizard
@ Mr.Wizard désolé, totalement oublié de vous répondre. Questions: jusqu'à présent, tous les problèmes que je rencontrais pouvaient être résolus avec googler / d'autres questions SE. Réponses: Je ne sais pas ... Je suppose que je ne me considère pas comme que compétent en matière d'utilisation de Mathematica productive ... Je ne l' utilise que pour des extraits rapides ici et là (et le golf de code). De plus, je suppose que pour répondre aux questions, je devrais regarder activement les nouvelles questions pour voir ce que je peux répondre, et actuellement tout mon temps de SE est alloué au PPCG. ;) Si vous voulez me convaincre du contraire, n'hésitez pas à le faire en chat! :)
Martin Ender
4

JavaScript (E6) 159 164 172

Edit Merci à nderscore pour les conseils et pour m'avoir poussé à réfléchir à nouveau. Réorganisé D en évitant les paramètres et en coupant certains caractères.

Edit 2 Une autre astuce de nderscore, 2 fonctions fusionnées en 1. Ensuite, deux parenthèses ont été supprimées pour fusionner les expressions séparées par des virgules. Lisibilité proche de 0. Note: Ne pas arrondir pourrait économiser 2 caractères (| 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 dans la console 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)))

Sortie:

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

Ungolfed

NB La fonction D essaie de créer une Date avec une année, un mois ou un jour donnés, mais renvoie faux si la date créée n’est pas celle voulue (! = Jour ou mois)

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
la source
@nderscore OK pour les modifications en D, erreur sintax pour l'autre. Mais sauvé encore plus quand même
edc65
Bizarre. Quelque chose a dû se passer quand je l'ai collé dans le commentaire. Vos dernières optimisations le rendent inutile cependant :)
nderscore
1
En mettant cela dans une pâte, car je ne fais plus confiance aux commentaires de SE: (-3) pastie.org/private/6bemdweyndcaiseay70kia
nderscore
4

C # dans LINQPad - 446 408 272 octets

Troisième édition: Merci à Le Canard fou d’avoir fait remarquer que DateTime.Today est correct, pas DateTime.Now. Deuxième édition: Merci à VisualMelon pour cette solution intelligente!

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: Merci à podiluska et edc65 de m'aider à raccourcir le code! J'ai également remarqué que ma solution n'était pas correcte si la valeur de l'année était de 4 octets. J'ai donc inclus le correctif de ce problème. Le score de cette solution est de 408 octets.

Même si je ne bat aucune des réponses précédentes, je voulais tout de même partager ma solution C #. Toute aide / suggestion est appréciée! ;)

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

Version formatée et non-golfée:

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

J'ai essayé de créer une solution où la partie "DateTime.TryParse" ne se répète pas comme dans cette solution, mais elle était plus longue de 21 octets.

Solution sans répéter "DateTime.TryParse": 467 octets

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

Version non-golfée:

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
la source
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
suggestion: utilisez ternaire (? :) si possible au lieu de if / else
edc65
1
@ThomasW. Je ne pense pas que puisque y a 2 valeurs différentes, une fois cela dépend de a, l'autre fois cela dépend de e. Merci quand même!
Tsavinho
1
Enlever les DateTime.TryParseappels était mon premier instinct, le remplacer par un lambda qui remettait également la valeur dans q. Également effectué quelques autres étapes ( pastebin ) pour obtenir 328chars: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, vous êtes vraiment bon en code-golf! Je n'avais jamais vu Action<string>auparavant, je pouvais donc apprendre quelque chose de votre part;) J'ai pu réduire votre réponse à 318 caractères en le remplaçant q.Where(i=>i>=DateTime.Now).Countpar q.Count(i=>i>=DateTime.Now. J'ai également supprimé les crochets xpour pouvoir sauvegarder 2 caractères supplémentaires!
Tsavinho
3

Haskell, 171 165 caractères

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)

Le nom de la fonction est %. Exécutez avec la date du test sous forme de tuple dans l'ordre canonique (y, m, d) avec l'année réelle, et le tampon de la boîte sous forme de tuple de trois chiffres:

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

La fonction de test serait:

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

Cette solution repose sur la compréhension de liste. Il emprunte l'astuce du modulo pour l'année à la solution Haskell. Il utilise également calendar:valid_date/1pour traiter les dates impossibles en raison du nombre de jours d'un mois donné (par exemple, "29-2-2" ne peut être qu'au format JMD). En outre, Today est au date()format Erlang (un tuple YMD).

Paul Guyot
la source
2

APL (85)

Cela utilise certaines des nouvelles fonctions de Dyalog APL 14, mais pas de bibliothèques externes. Pour changer, cela fonctionne sur TryAPL .

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

Il s'agit d'une fonction qui prend le tableau à 3 éléments comme argument de droite ( ) et la date à vérifier comme argument de gauche ( ), sous la forme d'un entier au YYYYMMDDformat. C'est-à-dire que la date 2014-07-09est représentée par le nombre 20140709.

Tester:

      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

Explication:

  • Z←(⊂⌽⍵),(⊂2⌽⍵),⊂⍵: transformer la date donnée au format AMJ en la retournant (⊂⌽⍵), en la tournant de 2 à gauche (⊂2⌽⍵)ou en ne faisant rien ⊂⍵. Au moins un de ceux-ci est maintenant une date appropriée au format AMJ, peut-être plus d'une si la date est ambiguë.
  • {∧/12 31≥1↓⍵}¨Z: teste si chaque date est valide: l'année (premier élément) est supprimée, puis le mois ne doit pas dépasser 12 et le jour ne doit pas dépasser 31.
  • Z/⍨: filtrer les dates valides de Z.
  • {... : pour chaque date valide:
    • ⍵+(99≥⊃⍵)×3↑1900+100×50>⊃⍵: si l'année n'est pas supérieure à 99, ajoutez 1900, puis 100 si l'année est inférieure à 50.
    • (3/100)⊥: décodez-le comme s'il s'agissait d'un ensemble de nombres en base 100. (L'année est supérieure à 100, mais cela n'a pas d'importance car c'est le premier élément.) Ceci donne un nombre pour chaque date valide dans le même format que l'argument de gauche.
  • ⍺≤: pour chaque date, voir si elle n'est pas plus petite que . Cela donnera un vecteur binaire où 1 signifie OKet 0 signifie spoiled.
  • 100×(+/÷⍴): divise la somme du vecteur binaire par sa longueur et multiplie par 100.
marinus
la source
Économisez 7 octets (et battez K avec une belle marge) en échouant et en {100×(+/÷⍴)⍺≤((3/100)⊥⊢+(99≥⊃)×3↑1900+100×50>⊃)¨Z/⍨{∧/12 31≥1↓⍵}¨Z←(⌽⍵)(2⌽⍵)⍵}
tacitant
0

Java: 349 caractères (3 sans espaces)

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

Voici une classe contenant qui peut être utilisée pour le tester, y compris une version (légèrement) dégradée de la méthode:

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

C’est ma première partie de golf de code, et je pense avoir compris pourquoi je ne vois généralement pas beaucoup de golfeurs Java.

boucliergenerator7
la source
1
Vous devez accepter un int[]argument, pas trois int.
Joey
ok, je l'ai réparé.
shieldgenerator7
0

C # 287 octets

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

Première fois golf, à la recherche de conseils. Notamment, supprimer les octets en raison de l'espace de noms.

Abuser du fait que seule une fonction est requise, pas un programme réel. En outre, la fonction entraîne toujours une exception non interceptée.

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
la source
0

Mathematica , 118

En utilisant le code de m.buettner comme point de départ, j'ai quelques améliorations:

⌊100Mean@UnitStep@Cases[DateDifference@{If[#<100,Mod[#+50,100]+1950,#],##2}&@@@{#,RotateRight@#,Reverse@#},_Integer]⌋&
Mr.Wizard
la source
Le golf peut être une fonction prenant comme argument une liste de trois Int.
algorithmshark
@ algorithmshark Merci. Je ne sais pas comment j'ai raté ça. Mise à jour de ...
Mr.Wizard