Calendrier de survol

17

Ceci est inspiré par l'une des questions de Downgoat dans Sandbox, où j'ai suggéré qu'il inclue le 31 avril comme jour Pi pour les personnes qui utilisent le format jour / mois, seulement pour lui pour m'informer qu'il n'y a pas de 31 avril!

Étant donné une chaîne de date au format mois / jour qui peut ne pas être valide, affichez la date correcte à l'aide du survol. (Survolez d'abord le mois, puis le jour).

Exemples:

"15/43" - Cela se lit comme le 43e jour du 15e mois. Tout d'abord, nous reportons le mois sur l'année suivante, nous nous retrouvons donc avec 3 (mars). Maintenant, comme le mois de mars ne compte que 31 jours, nous reportons les jours supplémentaires au mois d'avril, nous affichons donc la date réelle comme "4/12" (12 avril).

"3/16" - Ceci est une date valide (16 mars). Retournez-le tel quel.

"12/64" - Ah, tant de bons souvenirs du 64 décembre ... Décembre a 31 jours, janvier a 31 jours, donc ce que je veux dire c'est "2/2" (2 février).

"19/99" - Tout d'abord, le 19 devient un 7 (juillet). Juillet a 31 jours, août a 31 jours, septembre a 30 jours, donc la sortie est "10/7" (7 octobre).

"1/99999" - Une année compte 365 jours. 99999 (mod 365) = 354. Le 354 jour de l'année est "12/20" .

"9999999/10" - Apparemment, 9999999 (mod 12) = 3, c'est donc "3/10" (10 mars).

Critères:

Le mois d'entrée est un entier> 0. Le jour d'entrée est un entier> 0. L'année n'a jamais besoin d'être spécifiée, car il n'y a pas d'années bissextiles à gérer.

Mise à jour:

Comme je pense que cela simplifierait trop le défi, les fonctions de calendrier, telles que celles de la classe Java Calendar , sont interdites. Les fonctions d'analyse et de formatage des dates sont cependant toujours autorisées.

geokavel
la source
1
Un autre cas de test important serait celui qui a suffisamment de jours pour s'étaler sur plus de 8 ans, de sorte que les réponses qui utilisent des éléments intégrés doivent prêter attention à ces éléments intégrés utilisant des années bissextiles.
Martin Ender
Oh, cela répond à cela ... J'étais sur le point de publier une réponse Mathematica qui utilise un intégré. : /
Martin Ender
@Martin Désolé à ce sujet;).
geokavel
Pour référence, la solution Mathematica comptait toujours 90 octets (bien que celle-ci ait été massivement dominée par le traitement des chaînes). Si vous voulez quand même ajouter un tel cas de test, ça 1/99999devrait céder 12/19je pense.
Martin Ender

Réponses:

11

LabVIEW, 32 primitives LabVIEW

Eumel
la source
C'était rapide.
Addison Crump
Pouvez-vous m'assurer qu'aucune fonction de calendrier n'est utilisée ici?
geokavel
La bonne chose à propos de LabVIEW est que c'est fondamentalement ce qu'il semble être. La première chose scanne les nombres à partir d'une chaîne de 2 modules, la boîte est une structure de boîtier de commutation qui donne 28,30 ou 31, puis elle est à nouveau assemblée sous forme de chaîne.
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 : fixe pour fonctionner pour des cas comme 24/1, 36/1, etc. et golfé un peu. Merci pour les commentaires, il y a plusieurs endroits que j'ai économisés un peu!

Non golfé:

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
la source
Tout d'abord: Bienvenue dans la communauté! Je suppose que vous pourriez économiser quelques octets en attribuant le dictionnaire dans une boucle ou en utilisant une fonction de commutation (pas de C # pro ici cependant). L'impression directe ´m + "/" + d´ peut aussi aider un peu. Et enfin (cela pourrait ou non fonctionner) en utilisant char * au lieu de chaîne dans les arguments.
Eumel
Cela échoue sur certains cas de test, par exemple 24/1.
LegionMammal978
@Eumel merci! L'impression directe utilise Console.Writeplus que return, et en C # j'utiliserais char[]en remplacement string, mais c'est la même quantité de caractères et rend le fractionnement /plus problématique. Mais, votre note sur le dictionnaire m'a conduit à une bien meilleure version!
DrewJordan
4

R, 208 182 octets

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="/")

Obtenez le mois en divisant par 12, puis bouclez, en supprimant le nombre de jours du mois en cours jusqu'à ce que vous obteniez un nombre négatif., Inversez la dernière étape et imprimez.

Sur plusieurs lignes (besoin d'utiliser un fichier et de le source):

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
la source
Voici le message que j'obtiens en essayant d'exécuter votre programme dans R: pastebin.com/dPh1n64a
geokavel
Étrange, je revérifierai plus tard
Tensibai
J'ai aussi reçu ce message. Votre programme semble avoir des problèmes avec quelques mois. Sinon, ça tourne. pastebin.com/g3BCUDi8
geokavel
Merci pour les commentaires. Je suis sur la route en fait, je vais le corriger
Tensibai
1
@Tensibai oui vous avez raison, ma mauvaise (j'aurais dû me rappeler que le message d'erreur dit qu'il attend "un vrai").
plannapus
3

PHP> = 5,5, 181 octets

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

PHP prend presque en charge le rollover avec des instructions d'analyse et de formatage de date uniquement. Par exemple:

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

Cependant, une fois que l'un des nombres est supérieur à 100, PHP rejette l'analyse et renvoie une erreur (probablement pour une raison arbitraire). Donc, la théorie avec cette réponse est de la ramener là où PHP va l'analyser, puis de la soumettre date_create_from_format().

Non golfé:

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

Essayez-le en ligne

nickb
la source
1
Vous devez me donner un moyen d'entrer la chaîne de date ou d'en faire une fonction.
geokavel
Les paramètres GET ne sont pas acceptables comme méthode d'entrée en PHP . Vous devrez soit en faire une fonction et passer l'entrée en tant que paramètres de fonction, soit obtenir une entrée de $argvou STDIN.
Mego
@Mego Jeeze, donnez-moi un peu de temps pour mettre à jour ma réponse car l'OP n'a pas énoncé d'exigences d'entrée - il est assez simple de passer $tà $argv[1]et maintenant il lit à partir de l'entrée de ligne de commande.
nickb
Le PO indiquant les exigences d'entrée n'est pas pertinent; nous avons une liste de méthodes d'E / S acceptables par défaut (que j'ai liées) afin que les auteurs de défis n'aient pas à les spécifier à chaque défi.
Mego
2

JavaScript (ES6), 106 octets

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

Explication

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

Tester

user81655
la source
1

Réponse non concurrente - Bash + coreutils, 55

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

"Les fonctions d'analyse et de formatage des dates sont toujours autorisées" - je suppose que celadate utilitaire est autorisé.

L'entrée est lue à partir de la ligne de commande, par exemple:

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

Ceci n'est pas en concurrence car la commande date s'étend à quelque chose comme ça qui ajoute un certain nombre de jours:

date -d1-3-1+42day +%-m/%-d
Traumatisme numérique
la source
Il est autorisé tant qu'il ne fait rien comme date.add(875)augmenter la date de 875 jours. C'est surtout ce que j'allais chercher.
geokavel
@geokavel oh, je vois. La datecommande entièrement développée ici est date -d1-3-1+42day +%-m/%-d, donc c'est exactement ce qu'elle fait. Je suppose que c'est une réponse non concurrente alors :(
Digital Trauma