Calendário de sobreposição

17

Isso é inspirado em uma das perguntas de Downgoat no Sandbox, onde sugeri que ele incluísse o dia 31 de abril como dia do Pi para pessoas que usam o formato dia / mês, apenas para que ele me informasse que não há 31 de abril!

Dada uma sequência de datas no formato mês / dia que pode ser inválida, imprima a data correta usando rollover. (Primeiro rollover do mês e depois rollover do dia).

Exemplos:

"15/43" - é o 43º dia do 15º mês. Primeiro, rolamos o mês para o próximo ano e terminamos com 3 (março). Agora, como março tem apenas 31 dias, passamos os dias extras para abril, e produzimos a data real como "4/12" (12 de abril).

"3/16" - esta é uma data válida (16 de março). Devolva como está.

"12/64" - Ah, tantas boas lembranças de 64 de dezembro ... Dezembro tem 31 dias, janeiro tem 31 dias, então o que eu realmente quero dizer é "2/2" (2 de fevereiro).

"19/99" - Primeiro, os 19 se tornam 7 (julho). Julho tem 31 dias, agosto tem 31 dias, setembro tem 30 dias, portanto a saída é "10/7" (7 de outubro).

"1/99999" - um ano tem 365 dias. 99999 (mod 365) = 354. Os 354 dias do ano são "12/20" .

"9999999/10" - aparentemente, 9999999 (mod 12) = 3, então isso é "3/10" (10 de março).

Critério:

O mês de entrada é um número inteiro> 0. O dia de entrada é um número inteiro> 0. O ano nunca precisa ser especificado, portanto, não há anos bissextos para lidar.

Atualizar:

Como acho que simplificaria demais o desafio, funções de calendário, como as da classe Java Calendar , são proibidas. As funções de análise / formatação de data ainda são permitidas.

geokavel
fonte
11
Relacionado.
gato
11
Outro caso de teste importante seria aquele com dias suficientes para passar por mais de 8 anos, de modo que as respostas que usam os componentes internos devam prestar atenção àqueles que usam anos bissextos.
Martin Ender
Ah, isso responde que ... Eu estava prestes a postar uma resposta do Mathematica que usa um built-in. : /
Martin Ender
@ Martin Desculpe por isso;).
perfil completo de geokavel
Para referência, a solução Mathematica ainda tinha 90 bytes de comprimento (embora isso fosse massivamente dominado pelo processamento de strings). Se você quiser adicionar um caso de teste, no entanto, 1/99999deve render, 12/19eu acho.
Martin Ender

Respostas:

11

LabVIEW, 32 primitivas do LabVIEW

Eumel
fonte
Aquilo foi rápido.
Addison Crump
Você pode me garantir que não há funções de calendário usadas aqui?
geokavel
O lado bom do LabVIEW é que é basicamente o que parece ser. A primeira coisa que digitaliza números de uma string 2 modulos, a caixa é uma estrutura de caixa de distribuição que fornece 28,30 ou 31 e depois é montada novamente como uma string.
Eumel
4

C #, 269 223

string v(string n){var x=new[]{31,28,31,30,31,30,31,31,30,31,30,31};var s=n.Split('/');Func<string,int> p=int.Parse;var m=p(s[0]);var d=p(s[1]);m=m>=12?m%12:m;while(d>x[m]){d-=x[m];m=++m>=12?m%12:m;}return(m==0?1:m)+"/"+d;}

Edit : Corrigido para trabalhar em casos como 24/1, 36/1, etc. e jogava golfe um pouco. Obrigado pelos comentários, existem vários lugares que salvei um pouco!

Ungolfed:

string v(string n)
{
    var x = new [] { 31 ,28, 31, 30, 31, 30,31, 31, 30, 31, 30, 31 };

    var s = n.Split('/');
    Func<string,int> p = int.Parse;
    var m = p(s[0]);
    var d = p(s[1]);
    m = m >= 12 ? m % 12 : m;
    while (d > x[m])
    {
        d -= x[m];
        m = ++m >= 12 ? m % 12 : m;
    }
    return (m==0?1:m) + "/" + d;
}
DrewJordan
fonte
Primeiro de tudo: Bem-vindo à comunidade! Eu acho que você poderia salvar alguns bytes atribuindo o dicionário em um loop ou usando uma função de opção (nenhum C # pro aqui embora). Também imprimir diretamente ´m + "/" + d´ pode ajudar um pouco. E por último (isso pode ou não funcionar) usando char * em vez de string nos argumentos.
Eumel
Isso falha em certos casos de teste, por exemplo 24/1.
usar o seguinte
@Eumel thanks! A impressão direta usa Console.Writemais do que return, e em C # eu usaria char[]como substituto string, mas é a mesma quantidade de caracteres e torna a divisão /mais problemática. Mas, sua anotação no Dicionário me levou a uma versão muito melhor!
DrewJordan
4

R, 208 182 bytes

m=c(31,28,31,30,31,30,31,31,30,31,30,31)
e=scan(sep="/");n=(e[1]/12-1)*12;if(!n%%12)n=12;if(n<0)n=e[1];j=e[2];while((j<-j-m[n])>0){n=n+1;if(n>12)n=1};j=m[n]+j;cat(n,j,sep="/")

Adquira o mês dividindo por 12 e, em seguida, faça um loop, removendo o número de dias do mês atual até obter um número negativo., Inverse a última etapa e imprima.

Em várias linhas (é necessário usar um arquivo e originar):

m=c(31,28,31,30,31,30,31,31,30,31,30,31)
e=scan(sep="/")
n=(e[1]/12-1)*12
if(!n%%12)n=12
if(n<0)n=e[1]
j=e[2]
while((j<-j-m[n])>0){n=n+1;if(n>12)n=1}
j=m[n]+j;cat(n,j,sep="/")
Tensibai
fonte
Esta é a mensagem que recebo ao tentar executar o programa em R: pastebin.com/dPh1n64a
geokavel
Estranho, eu voltarei a verificar mais tarde
Tensibai
Eu também recebi esta mensagem. Seu programa parece ter problemas com alguns meses. Caso contrário, está funcionando. pastebin.com/g3BCUDi8
geokavel
Obrigado pelo feedback. Eu estou na estrada, na verdade, eu vou corrigi-lo
Tensibai
11
@ Tensibai sim, você está certo, meu mal (eu deveria ter lembrado que a mensagem de erro diz que espera "um real").
plannapus
3

PHP> = 5.5, 181 bytes

list($m,$d)=explode("/",$argv[1]);$m%=12;$d%=365;$i=0;while($d>100)$d-=[31,28,31,30,31,30,31,31,30,31,30,31][$i++];$m+=$i;echo date_create_from_format("m/d","$m/$d")->format("n/j");

O PHP quase suporta rollover apenas com instruções de análise e formatação de datas. Por exemplo:

echo date_create_from_format("m/d","12/64")->format("n/j"); // Output: 2/2

No entanto, uma vez que qualquer número fica maior que 100, o PHP rejeita a análise e retorna um erro (provavelmente por algum motivo arbitrário). Portanto, a teoria com esta resposta é voltar ao local onde o PHP irá analisá-lo e enviá-lo paradate_create_from_format() .

Ungolfed:

list($month, $day) = explode("/", $argv[1]);
$month = $month % 12;
$day = $day % 365;
$i = 0;
$days = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
while($day > 31) $day -= $days[$i++];
$month += $i;
echo DateTime::createFromFormat("m/d", $month . "/" . $day)->format("n/j");

Experimente online

nickb
fonte
11
Você precisa me dar uma maneira de inserir a sequência de datas ou torná-la uma função.
perfil completo de geokavel
Os parâmetros GET não são aceitáveis ​​como método de entrada no PHP . Você precisará fazer disso uma função e passar a entrada como parâmetros de função, ou obter entrada $argvou STDIN.
Mego
@Mego Jeeze, me dê um tempo para atualizar minha resposta, já que o OP não declarou nenhum requisito de entrada - é simples o suficiente para mudar $tpara $argv[1]e agora ele lê da entrada da linha de comando.
nickb
O PO, declarando requisitos para entrada, é irrelevante; temos uma lista de métodos de E / S aceitáveis ​​padrão (que vinculei) para que os autores do desafio não precisem especificá-los em todos os desafios.
Mego
2

JavaScript (ES6), 106 bytes

s=>eval('q="030101001010";p=s.split`/`;for(d=i=p[1],m=p[0]-1;i--;d>n&&(m++,d-=n))n=31-q[m%=12];m+1+"/"+d')

Explicação

s=>
  eval(`              // use eval to enable for loop without needing to write {} or return
    q="030101001010"; // q = array of 31 - days in each month
    p=s.split\`/\`;   // p = array of [ month, day ]
    for(
      d=i=p[1],       // d = day
        m=p[0]-1;     // m = month - 1
      i--;            // loop for each day, this is more iterations than needed but extra
                      //     iterations do not affect the result and it's the shortest way
                      //     to guarantee all months have been subtracted from d, it also
                      //     ensures the loop runs at least once to get m % 12
      d>n&&(m++,d-=n) // if too many days, subtract the month's days and increment month
    )
      n=31-q[m%=12];  // n = number of days in month, get m % 12
    m+1+"/"+d         // return the result
  `)

Teste

user81655
fonte
1

Resposta não concorrente - Bash + coreutils, 55

date -d1-$[(${1%/*}-1)%12+1]-1+$[${1#*/}-1]day +%-m/%-d

"As funções de análise / formatação de data ainda são permitidas" - presumo que isso signifiquedate utilitário é permitido.

A entrada é lida na linha de comando, por exemplo:

$ ./rollovercal.sh 15/43
4/12
$ 

Isso não é concorrente porque o comando date se expande para algo assim, que está adicionando vários dias:

date -d1-3-1+42day +%-m/%-d
Trauma Digital
fonte
É permitido desde que não esteja fazendo nada como date.add(875)incrementar a data em 875 dias. Isso é principalmente o que eu estava procurando.
precisa
@geokavel oh, entendo. O datecomando totalmente expandido aqui é date -d1-3-1+42day +%-m/%-d, então está fazendo exatamente isso. Eu acho que essa é uma resposta não competitiva, então :(
Digital Trauma