Já estamos?


22

Sou viajante do tempo e obcecado pela passagem do tempo. Adoro particularmente os momentos em que o ponteiro do relógio passa das 12, ou quando pulo para a próxima página do meu calendário, ou quando todos gritam "Feliz Ano Novo!"

Por favor, escreva para mim um programa para me mostrar a que distância estou do último momento para o próximo, na forma de uma barra de progresso. Por exemplo, se eu disser que a hora é 09:12, ela deve imprimir isto:

09:00 ####---------------- 10:00

Se eu disser que o mês é maio de 1982, ele deve imprimir o seguinte:

1982-01 #######------------- 1983-01

Eu mencionei que sou um viajante do tempo? Viajo para qualquer lugar, desde o primeiro milissegundo de 0 AD até o último milissegundo de 9999 AD, portanto, o programa precisa lidar com qualquer data e hora nesse intervalo.

Entrada

  • A entrada estará em um dos seguintes formatos:

    • YYYY-MM-DDThh:mm:ss.sss
    • YYYY-MM-DDThh:mm:ss
    • YYYY-MM-DDThh:mm
    • YYYY-MM-DDThh
    • YYYY-MM-DD
    • YYYY-MM

    Esses são os únicos formatos que precisam ser manipulados. Cada parte terá exatamente o número de dígitos mostrado, o que significa que segundos fracionários podem ter zeros à direita (por exemplo .120, nunca .12). A Té uma letra literal "T" que delimita a data a partir da hora. As horas estão em um relógio de 24 horas.

  • Meses e dias são baseados em 1 (mais sobre isso abaixo).

  • Entradas inválidas e fora da faixa não precisam ser manipuladas.

  • A critério do programador, a entrada pode ter uma única nova linha à direita.

Matemática da barra de progresso

O programa está preocupado com as unidades de menor e segundo menos significantes na entrada fornecida. Por exemplo, se a entrada tiver precisão no nível do dia (por exemplo 2016-12-14), a barra de progresso indicará qual a proporção de dias no mês de entrada decorrido versus o que resta.

A barra de progresso terá 20 unidades (caracteres) e a proporção representada será arredondado para o mais próximo incremento de 1 / 20 . Por exemplo, dada 2016-12-14T12:28a barra de progresso mostrará Rodada ( 2860 × 20) = 9 de 20 unidades "preenchidas".

Meses e dias baseados em 1

Embora o dia 1º de dezembro (por exemplo) esteja 01chegando 2016-12-01, para fins de cálculo, é o 0º dia do mês, porque as unidades truncadas implicam o 0º milissegundo do 0º minuto da 0ª hora do dia. Em outras palavras, 2016-12-01é 0 / 31 do caminho através de dezembro e 2016-12-02é 1 / 31 , e assim por diante.

Da mesma forma, 2016-01é o milissegundo 0 do dia 0 de Janeiro de modo em cálculos que é 0 / 12 , os quais meios 2016-12é 11 / 12 .

Sim, isso significa que meses e dias nunca preencherão completamente a barra de progresso.

Diferentes durações do mês e anos bissextos

Meses diferentes têm diferentes números de dias e a produção deve refletir isso - incluindo anos bissextos. A barra de progresso de 6 de fevereiro de 2017 será diferente da barra de progresso de 6 de fevereiro de 2016 (ou 6 de janeiro de ambos os anos).

Diversos

  • Os viajantes do tempo usam o calendário gregoriano pró-séptico . TL; DR: Não há casos especiais como dias perdidos em 1752 . A entrada incluirá datas no ano 0 AD
  • Os viajantes no tempo ignoram o horário de verão.
  • O programa não precisa contabilizar segundos bissextos, mas pode ser.

Saída

O programa (ou função) deve imprimir (ou retornar como uma sequência) uma barra de progresso de 20 caracteres orientada horizontalmente que é "preenchida" pelo tempo decorrido e "aberta" pelo tempo restante. Ele deve "preencher" da esquerda para a direita.

A barra de progresso deve ter um rótulo à esquerda mostrando o início do período sendo contado e outro à direita mostrando o início do próximo período, no mesmo formato da entrada (mas mostrando apenas duas unidades de precisão). Para o nosso exemplo, a 2016-12-14saída válida seria:

12-01 #########----------- 01-01

Aqui estão os formatos de etiqueta válidos para cada um dos períodos possíveis:

  • Meses: YYYY-MM
  • Dias: MM-DD
  • Horário: DDThh
  • Minutos: hh:mm
  • Segundos: mm:ss
  • Milissegundos: ss.sss

Nenhuma unidade adicional pode ser incluída nas etiquetas e nenhuma pode ser omitida.

Notas de saída

  • As unidades "preenchidas" da barra de progresso serão representadas por um #personagem. As unidades "abertas" serão representadas por -.
  • Deve haver exatamente um espaço entre a barra de progresso e cada rótulo.
  • Espaços iniciais ou finais e / ou uma nova linha final são permitidos.

Ganhando

Isso é . O menor código em bytes vence. Aplicam-se regras padrão. Falhas padrão proibidas.

Exemplos

Input                      Output
-----------------------    -------------------------------------
2016-12-12T12:17           12:00 ######-------------- 13:00
2016-12-12                 12-01 #######------------- 01-01
0000-01-01T00:00:00.000    00.000 -------------------- 01.000
0000-01-01T00:00           00:00 -------------------- 01:00
1899-12-31T23              31T00 ###################- 01T00
1899-12-31                 12-01 ###################- 01-01
1899-12                    1899-01 ##################-- 1900-01
1982-05-15T17:15           17:00 #####--------------- 18:00
1982-05-15T17              15T00 ##############------ 16T00
1982-05                    1982-01 #######------------- 1983-01
9999-12-31T23:59:59.999    59.000 #################### 00.000
9999-12                    9999-01 ##################-- 10000-01
2000-01-06                 01-01 ###----------------- 02-01
2000-02-06                 02-01 ###----------------- 03-01
2001-02-06                 02-01 ####---------------- 03-01
1742-09-10                 09-01 ######-------------- 10-01

4
Precisamos nos preocupar com segundos bissextos?
Riley

@Riley Boa pergunta. Não.
Jordan

2
Presumo que o horário de verão seja ignorado, pois não existe um formulário padronizado?
CAD97

3
@ CAD97 Boa pergunta. Você está certo. O horário de verão realmente complica as coisas para os viajantes do tempo, por isso nós o ignoramos.
Jordan

O exemplo "1899-12-31T23" não é válido de acordo com a lista fornecida de formatos de entrada, o mesmo para "1982-05-15T17". Por favor, verifique seus dados de teste.
Zeppelin

Respostas:


4

JavaScript, 282 bytes

(x,v=x.split(/\D/g),l=v.length-2,[a,b,c,d]=("10e5,01,-,12,01,-,"+new Date(v[0],v[1],0).getDate()+",00,T,24,00,:,60,00,:,60,000,.,1000").split`,`.slice(l*3,l*3+4),t=(v[l+1]-b)/d*20+.5|0,n=v[l],o=((n|0)+1)%a,r=l?('0'+o).slice(-2):o)=>n+c+b+' '+'#'.repeat(t)+'-'.repeat(20-t)+' '+r+c+b

Passa em todos os testes

(
x,
v=x.split(/\D/g),
l=v.length-2,
[a,b,c,d]=("10e5,01,-,12,01,-,"+new Date(v[0],v[1],0).getDate()+",00,T,24,00,:,60,00,:,60,000,.,1000").split`,`.slice(l*3,l*3+4),
t=(v[l+1]-b)/d*20+.5|0,
n=v[l],
o=((n|0)+1)%a,
r=l?('0'+o).slice(-2):o
) =>n+c+b+' '+'#'.repeat(t)+'-'.repeat(20-t)+' '+r+c+b

A função de teste não imprime nada para aprovação, valores para falha.

function test(value,expected){
    if (f(value)!=expected)
    {
        console.log(value);
        console.log(f(value));
        console.log(expected);
     }
}

Os casos de teste:

test('2016-12-12T12:17','12:00 ######-------------- 13:00')                 ;
test('2016-12-12','12-01 #######------------- 01-01')                       ;
test('0000-01-01T00:00:00.000','00.000 -------------------- 01.000')        ;
test('0000-01-01T00:00','00:00 -------------------- 01:00')                 ;
test('1899-12-31T23','31T00 ###################- 01T00')                    ;
test('1899-12-31','12-01 ###################- 01-01')                       ;
test('1899-12','1899-01 ##################-- 1900-01')                      ;
test('1982-05-15T17:15','17:00 #####--------------- 18:00')                 ;
test('1982-05-15T17','15T00 ##############------ 16T00')                    ;
test('1982-05','1982-01 #######------------- 1983-01')                      ;
test('9999-12-31T23:59:59.999','59.000 #################### 00.000')        ;
test('9999-12','9999-01 ##################-- 10000-01')                     ;
test('2000-01-06','01-01 ###----------------- 02-01')                       ;
test('2000-02-06','02-01 ###----------------- 03-01')                       ;
test('2001-02-06','02-01 ####---------------- 03-01')                       ;
test('1742-09-10','09-01 ######-------------- 10-01')                       ;

2
Eu tive que aprender um novo idioma para superar esta versão ... é muito conciso!
Rexroni

3

Pitão, 213 bytes

Meu primeiro código em pyth! Contemplar:

+%h=N:[d"%.4d"\-=Z"%.2d"\-Z\TZ\:Z\:Z\."%.3d")-*2lKr:w"[-T:.]"d7 3*2lKJ@K_2+@N1+%eN=b<lK4+d+*\#=Gs+*20c-eKb@=H[0^9T12?q2=k@K1+28+q0%=YhK4-q0%Y400q0%Y100+30%+k/k8 2 24 60 60 999)lK.5+*\--20G+d+%hN%+J1@H-lK1+@N1%eNb

Meu código pyth é estreitamente baseado na minha resposta python anterior. Aqui está a versão ungolfed com comentários:

"K is the input, as a list of numbers"
Kr:w"[-T:.]"d7
"Y=year"
=YhK
"k=month"
=k@K1
"H = a list of denominators"
=H[0 ^9T 12 ?q2k+28+q0%Y4-q0%Y400q0%Y100 +30%+k/k8 2 24 60 60 999)
"J is the second-to-last number of the input"
J@K_2
"b is the +1 starting point for months and days"
=b<lK4
"G is the number of hashtags in the statusbar"
=Gs+*20c-eKb@HlK.5
"N is the formatted string"
=N:[d"%.4d"\-=Z"%.2d"\-Z\TZ\:Z\:Z\."%.3d")-*2lK3 *2lK
+%hNJ+@N1+%eNb+d+*\#G+*\--20G+d+%hN%+J1@H-lK1+@N1%eNb

O teste de vários valores é realizado com facilidade, criando um loop de código e adicionando uma nova linha de impressão ao final:

Wp+%h=N:[d"%.4d"\-=Z"%.2d"\-Z\TZ\:Z\:Z\."%.3d")-*2lKr:w"[-T:.]"d7 3*2lKJ@K_2+@N1+%eN=b<lK4+d+*\#=Gs+*20c-eKb@=H[0^9T12?q2=k@K1+28+q0%=YhK4-q0%Y400q0%Y100+30%+k/k8 2 24 60 60 999)lK.5+*\--20G+d+%hN%+J1@H-lK1+@N1+%eNb"\n"

Então eu corri cat testinput | pyth code.pyth > outpute diff output testoutput Ou experimentá-lo on-line .


2

Python 2, 371 bytes

Esse desafio foi surpreendentemente difícil! Parecia que eu teria pouco menos de 300 anos até resolver a formatação da string de saída.

O tipo de parte legal é que minha resposta não usa nenhum pacote de datas:

import re
s=raw_input()
S=[int(i)for i in re.sub('[-T:.]',' ',s).split()]
l=len(S)
y,m=S[:2]
d=[0,20<<9,12,28+(y%4==0!=y%100)+(y%400==0)if m==2else 30+(m+m/8)%2,24,60,60,999]
a,n=S[-2:]
b=1-(1if l>3else 0)
h=int(20.*(n-b)/d[l]+.5)
x,y,z='- %.4d - %.2d - %.2d T %.2d : %.2d : %.2d . %.3d'.split()[l*2-3:l*2]
print x%a+y+z%b+' '+'#'*h+'-'*(20-h)+' '+x%((a+1)%d[l-1])+y+z%b
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.