Aww, cara, esse prazo de validade não escreve os meses com letras! Não sei dizer se está expirando em 10 de março ou 3 de outubro ... Espere, não, não importa, o ano diz 2012. (o beco-oops tijolo de queijo meio usado no lixo pode ser um profissional)
Então, vamos supor por um momento que você está muito ocupado para tentar pensar quando esse pote de marinara deve expirar. Você quer apenas a versão do Cliff Notes: qual a probabilidade de atraso? Vamos escrever um código!
Você sabe que os fabricantes imprimem a data como um triplo ordenado de números inteiros, em um dos três formatos:
YEAR MONTH DAY
MONTH DAY YEAR
DAY MONTH YEAR
E você sabe que algumas datas só podem ser interpretadas de uma ou duas maneiras, e não as três: a 55 em 55-11-5
tem que ser um ano, significando que essa caixa específica de Twinkies expirou em 5 de novembro de 1955. Às vezes, o ano é dado em quatro dígitos e não dois, o que pode excluir algumas opções. Quando tem dois dígitos, 50..99 significa 1950..1999 e 0..49 significa 2000..2049.
Seu trabalho é escrever um programa ou função que utilize uma matriz de números inteiros que seja uma data válida em pelo menos uma das interpretações acima e dê uma chance percentual de que ainda seja bom. A chance percentual é simplesmente a porcentagem de interpretações válidas da data que estão na data posterior ou posterior à data de hoje.
A matriz de números inteiros será o [Int]
tipo de comprimento três da sua linguagem, se for um argumento para uma função, e fornecida como inteiros separados por traço, barra ou espaço (você escolhe), se usados como entrada em STDIN para um programa completo. *
"Data de hoje" pode ser a data real de hoje, obtida através de uma função de data, ou a data fornecida em um argumento extra para funcionar ou paramater extra no STDIN. Pode ser no Unix, época segundos, outro triplo ano-mês-dia inserido de uma das três maneiras acima, ou de outra maneira mais conveniente.
Vamos dar alguns exemplos! A entrada da data de validade será no estilo separado por traço e assuma os exemplos abaixo que a data de hoje é 5 de julho de 2006.
14-12-14
- Ambas as interpretações válidas para isso (DMY e YMD) são equivalentes, 14 de dezembro de 2014. A saída é 100 porque este produto ainda é definitivamente bom.8-2-2006
- O último número é um ano, com certeza, uma vez que possui quatro dígitos. Pode ser 8 de fevereiro (expirado) ou 2 de agosto (ainda válido). A saída é 50 .6-7-5
- Isso pode ser qualquer coisa! A interpretação "5 de julho de 2006" ainda é boa (apenas por um dia), mas os dois restantes são ambos em 2005 e devem ser lançados o mais rápido possível. A saída é 33 .6-5-7
- Aqui, duas em cada três interpretações são seguras. Você pode arredondar seu decimal para cima ou para baixo, para que 66 ou 67 fiquem bem.12-31-99
- Tudo bem, este é inequivocamente da virada do século (anos de 50 a 99 são 19XX e 31 não pode ser um mês). Um 0 grande e gordo , e você realmente deve limpar sua geladeira com mais frequência.
Você pode assumir com segurança que qualquer entrada que não atenda aos padrões acima não tem acesso às regras de saída acima.
Sem solicitações da Web ou brechas padrão. Bibliotecas de manipulação de datas são permitidas. Este é o código golf: que o programa mais curto vença.
* Se você estiver usando brainfuck ou algum idioma com deficiência de tipo de dados similar, poderá assumir que os valores ASCII dos três primeiros caracteres de entrada são os números inteiros da data. Isso exclui a lógica dos quatro dígitos do ano, com certeza, mas acho que ficaríamos muito surpresos ao ver uma solução para isso em Brainfuck para menosprezá-lo.
Respostas:
k4
(90)(88)(87)(82)Invoque com
x
of.z.D
(a builtin) para comparação com hoje ou uma data literal de sua escolha: caso contrário:Esta é basicamente uma porta da solução Python do @ Alex-l, com alguns truques diversos de golfe adicionados:
fonte
"012201210"
, pois#
leva seus itens ciclicamente. Na verdade, você pode salvar um segundo caractere desta forma, trocando os dois últimos casos:3 3#.:'"0122102"
.{c*(+/~d<x)%3-+/^d:{"D"$"."/:$|z,y,x+(c*19+x<50)*x<c::100}.'y@/:3 3#.:'$21020101}
.Ruby, 115 caracteres
Isso define uma função
f
que recebe dois argumentos: uma matriz que contém a entrada e a data "de hoje".Exemplos:
fonte
Python 2.7 - 172
Eu uso o módulo datetime para validade e comparação de datas. Se
date
não for possível extrair um datetime da entrada, ele será geradoValueError
. Dessa forma,s
é a soma das datas não expiradas et
o número total de datas válidas. Estou aproveitando o fato de que,True == 1
para fins de adição e indexação em Python. Também salvei um personagem usando 25 * (76,80) em vez de (1900,2000).Observe que as linhas no segundo nível de recuo usam um caractere de tabulação, não 2 espaços.
Adicione isso ao final para testar:
fonte
PowerShell,
183173168Entrada como
int[]
via parâmetro, por exemplotry
/catch
, desde que eu não saiba se a saída no stderr é permitida ou não.+"-1"
na data, que é interpretada como.AddDays(-1)
para alterar a data atual em um dia, para que possamos comparar com ontem (em vez de apenas hoje). Isso resolve o problema de obter uma data com 0:00 como hora, mas precisamos comparar com uma data com hora a partir de hoje.fonte
R, 269
Eu esperava que isso fosse fácil no R, mas os anos de um dígito foram uma grande curva. Eu sinto que isso poderia ser muito melhor do que é.
lubridate
é um pacote do CRAN, pode ser necessário instalá-loinstall.packages("lubridate")
.Uso:
f(c(d1,d2,d3))
ondec(d1,d2,d3)
é um vetor de números inteiros.por exemplo,
f(c(6,10,14))
retornos0.3333333
.O
lubridate
pacote possui uma série de funções de wrapper para analisar datas em diferentes pedidos. Eu os uso para ver quais formatos produzem datas válidas, jogar fora os inválidos e depois ver quais ainda não ocorreram.fonte
Mathematica,
163153164 bytes( editar: datas fixas fora do intervalo de 1950 a 2049)
Isso define uma função que você pode chamar como
Atualmente, a porcentagem não é arredondada (aguardando o OP esclarecer).
Aqui está uma explicação um pouco demorado que deve ser compreensível sem qualquer conhecimento Mathematica (note que
&
faz tudo à esquerda dele uma função anônima cujos parâmetros são referidos como#
,#2
,#3
...):Isso define uma função que transforma 3 parâmetros
a,b,c
em 3 listas{{a,b,c},{c,b,a},{c,a,b}
. Observe que##
é apenas uma sequência de todos os parâmetros.Aplicado ao prazo de validade, fornece uma lista de
{y,m,d}
cada uma das três permutações possíveis.Esta é uma função anônima que aceita três parâmetros
a,b,c
e retorna uma lista dos três, onde o primeiro foi convertido em um ano de acordo com as regras fornecidas: números entre50
e99
(módulo100
) são transformados em um ano do século 20, números entre0
e49
( módulo100
) são transformados em um ano do século 21, e todos os outros são deixados. Aqui,##2
é uma sequência de parâmetros começando com o segundo, ieb,c
.Aplicado a cada um dos três resultados anteriores, isso apenas canoniza os formatos do ano. Vamos chamar isso
canonicalDates
para encurtar a seguinte expressão:Isso filtra interpretações inválidas.
DateList@d
faz uma{y,m,d,h,m,s}
representação completa de vários formatos de data. Ele interpretará as listas na mesma ordem, mas o problema é que você pode passar coisas como{8,2,2006}
, nesse caso, será calculado8 years + 2 months + 2006 days
. Portanto, verificamos se os três primeiros elementos da lista retornada são idênticos à entrada (o que só pode acontecer se o mês e o dia estiverem nos intervalos apropriados).Para encurtar as seguintes linhas, vou me referir ao resultado dessa expressão a partir
validDates
de agora:Outra função anônima que tira uma data e retorna a diferença de dias para hoje (obtida de
Date[]
).Mapeie isso para as interpretações de data válidas.
Ainda outra função anônima que, dada uma lista (
#
), retorna a porcentagem de números não positivos nessa lista. Não.
é uma multiplicação, mas apenas o dígito decimal, para evitar números racionais como resultado (você obteria coisas como em100/3
vez de33.333
- eu realmente não sei se isso é um problema).Aplicado à lista de diferenças de datas, isso nos dá a fração de interpretações que ainda não expiraram.
fonte
JavaScript (E6) 159
164 172Editar Obrigado ao nderscore pelas dicas e por me fazer pensar novamente. Reorganizei D evitando parâmetros e cortando alguns caracteres.
Editar 2 Outro truque do nderscore, 2 funções mescladas em 1. Em seguida, dois parênteses removeram a fusão de expressões separadas por vírgula em uma. Legibilidade próxima a 0. Nota: Não arredondar poderia salvar outros 2 caracteres (| 0).
Teste no console do FireFox
Resultado:
Ungolfed
NB A função D tenta criar uma Data com determinado ano, mês, dia, mas retorna false se a data criada não for a que foi pretendida (! = Dia ou mês)
fonte
C # no LINQPad -
446408272 BytesTerceiro Edit: Obrigado Le Canard fou por apontar que DateTime.Today está correto, não DateTime.Now. Segundo Edit: Obrigado VisualMelon por esta solução inteligente!
Edit: Obrigado a podiluska e edc65 por me ajudarem a reduzir o código! Também notei que minha solução não estava correta se a entrada do ano tivesse 4 bytes, portanto, incluí a correção para esse problema. A pontuação para esta solução é 408 bytes.
Embora não esteja superando nenhuma das respostas anteriores, ainda queria compartilhar minha solução C #. Qualquer ajuda / sugestão é apreciada! ;)
Versão formatada e não destruída:
Tentei criar uma solução em que a parte "DateTime.TryParse" não se repete como nesta solução, mas tinha 21 bytes a mais.
Solução sem repetir "DateTime.TryParse": 467 bytes
Versão não destruída:
fonte
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];
DateTime.TryParse
chamadas foi meu primeiro instinto e substituí-lo por um lambda que também colocava o valor novamente em q. Também realizou algumas outras etapas ( pastebin ) para obter 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();}
Action<string>
antes, para poder aprender algo com você;) Consegui reduzir sua resposta para 318 caracteres substituindoq.Where(i=>i>=DateTime.Now).Count
porq.Count(i=>i>=DateTime.Now
. Também removi os suportesx
para poder salvar mais 2 caracteres!Haskell,
171165 caracteresO nome da função é
%
. Execute com a data do teste como uma tupla em ordem canônica (y, m, d) com o ano real e o carimbo da caixa como uma tupla de três números:fonte
Erlang, 146
A função de teste seria:
Ungolfed
Esta solução depende da compreensão da lista. Ele empresta o truque do módulo para o ano da solução Haskell. Ele também é usado
calendar:valid_date/1
para lidar com datas impossíveis devido ao número de dias em um determinado mês (por exemplo, "29-2-2" pode estar apenas no formato YMD). Além disso, Hoje está nodate()
formato de Erlang (uma tupla YMD).fonte
APL (85)
Isso usa algumas das novas funções do Dyalog APL 14, mas nenhuma biblioteca externa. Para variar, funciona no TryAPL .
Essa é uma função que usa a matriz de 3 elementos como
⍵
argumento do lado direito ( ) e a data a ser comparada como⍺
argumento do lado esquerdo ( ), como um número inteiro deYYYYMMDD
formato. Ou seja, a data2014-07-09
é representada como o número20140709
.Teste:
Explicação:
Z←(⊂⌽⍵),(⊂2⌽⍵),⊂⍵
: transforme a data especificada no formato YMD, invertendo(⊂⌽⍵)
, girando-a para a esquerda por 2(⊂2⌽⍵)
ou simplesmente não fazendo nada⊂⍵
. Agora, pelo menos um deles é uma data adequada no formato YMD, talvez mais de um se a data for ambígua.{∧/12 31≥1↓⍵}¨Z
: teste se cada data é válida: o ano (primeiro elemento) é descartado e, em seguida, o mês não deve ser maior que 12 e o dia não deve ser maior que 31.Z/⍨
: filtre as datas válidas deZ
.{
...}¨
: para cada data válida:⍵+(99≥⊃⍵)×3↑1900+100×50>⊃⍵
: se o ano não for superior a 99, adicione 1900 e 100 se o ano for inferior a 50.(3/100)⊥
: decodifique como se fosse um conjunto de números da base 100. (O ano é superior a 100, mas isso não importa, pois é o primeiro elemento.) Isso fornece um número para cada data válida no mesmo formato que o argumento esquerdo.⍺≤
: para cada data, veja se não é menor que⍺
. Isso fornecerá um vetor binário em que 1 significaOK
e 0 significaspoiled
.100×(+/÷⍴)
: divida a soma do vetor binário pelo seu comprimento e multiplique por 100.fonte
{100×(+/÷⍴)⍺≤((3/100)⊥⊢+(99≥⊃)×3↑1900+100×50>⊃)¨Z/⍨{∧/12 31≥1↓⍵}¨Z←(⌽⍵)(2⌽⍵)⍵}
Java: 349 caracteres (3 sem espaços)
Aqui está uma classe que pode ser usada para testá-lo, incluindo uma versão (ligeiramente) degolfada do método:
Esta é minha primeira partida de golfe com código e acho que descobri por que não costumo ver muitos jogadores de Java.
fonte
int[]
argumento como, não trêsint
s.Bytes em C # 287
Golfe pela primeira vez, procurando conselhos. Notavelmente, removendo bytes devido ao espaço para nome.
Abusar do fato de que apenas uma função é necessária, e não um programa real. Além disso, a função sempre resulta em uma exceção não capturada.
Ungolfed
fonte
Mathematica , 118
Usando o código do m.buettner como ponto de partida, tenho algumas melhorias:
fonte