Jour de la semaine du 29 février prochain


14

Écrivez une fonction qui prend une date et renvoie le jour de la semaine du 29 février suivant cette date.

  • L'entrée est une chaîne au format ISO Extended: AAAA-MM-JJ (par exemple, le 27 mai 2010 serait "2010-05-27").

  • La sortie est une chaîne qui est le nom du jour de la semaine (par exemple "lundi"). La capitalisation n'a pas d'importance, mais donnez le nom complet en anglais.

  • Si la date donnée est Février 29, puis revenez le jour de la semaine du prochain 29 Feburary.

  • Utilisez les calculs pour le calendrier grégorien proleptique (il utilise donc les calculs de l'année bissextile grégorienne pour toute sa longueur). Ne vous inquiétez pas du calendrier julien ou du moment où le passage de julien à grégorien s'est produit. Assumez simplement le grégorien pour tout.

  • La fonction doit fonctionner pour au moins la plage "0001-01-01" - "2100-01-01".

  • N'hésitez pas à utiliser les bibliothèques standard fournies par la langue de votre choix, mais n'utilisez pas de bibliothèques tierces à moins que vous ne souhaitiez inclure ce code dans votre solution.

  • Le code le plus court (le moins de caractères) l'emporte.

Exemples:

  • func("0001-01-01") -> "Sunday"
  • func("1899-12-03") -> "Monday"
  • func("1970-01-01") -> "Tuesday"
  • func("1999-07-06") -> "Tuesday"
  • func("2003-05-22") -> "Sunday"
  • func("2011-02-17") -> "Wednesday"
  • func("2100-01-01") -> "Friday"

(et non, vous n'avez pas à nommer la fonction func)

Conseils:

  • N'oubliez pas que les années se terminant par 00 qui ne sont pas divisibles par 400 ne sont pas des années bissextiles.
  • Le 1er janvier 0001 est un lundi.

Réponses:


7

Windows PowerShell, 65

Assez simple.

filter f{for($d=date $_;($d+='1').day*$d.month-58){}$d.dayofweek}

Comme d'habitude, nous pouvons raser deux octets si nous sommes prêts à attendre longtemps jusqu'à la fin:

filter f{for($d=date $_;($d+=9).day*$d.month-58){}$d.dayofweek}

Tester:

> '0001-01-01','1899-12-03','1970-01-01','1999-07-06','2003-05-22','2011-02-17','2100-01-01'|f
Sunday
Monday
Tuesday
Tuesday
Sunday
Wednesday
Friday

Histoire:

  • 2011-02-18 00:06 (65) Première tentative.

Quel chemin est nécessaire pour que cela fonctionne? J'ai la date GnuWin sur mon chemin, ce qui la brise.
Peter Taylor

@Peter: Cela pourrait entrer en conflit avec date. Supprimez simplement GNUWin32 du CHEMIN et cela devrait fonctionner. Ou passez dateà Get-Date(ce type de comportement de secours ne fonctionne que lorsqu'aucune commande n'est trouvée - pour vérifier, utilisez simplement gcm date). Quoi qu'il en soit, je ne considère pas qu'un problème particulier avec ce script comme GNUWin32 ne fait partie d'aucune installation Windows standard.
Joey

La raison pour laquelle j'ai demandé était parce que j'ai déjà essayé d'utiliser get-dateet j'ai reçu le message d'erreur. A- Method invocation failed because [System.Management.Automation.PSObject] doesn't contain a method named 'op_Addition'.t-il besoin de PS2 ou .Net 4 ou quelque chose?
Peter Taylor

@Peter: J'ai essayé PowerShell v2. .NET 4 n'y joue pas car PowerShell est lié au runtime 2.0. Dans tous les cas, aucun objet PSO ne devrait revenir Get-Datemais un System.DateTime.
Joey

C'est très bizarre. $d=Get-Date "0400-01-01"; $d++donne un message d'erreur sur le fait de ++ne pas être défini sur DateTime. Le même remplacement ++par +=1ou +="1"ou +='1'donne le message d'erreur sur PSObject. Et ça +"1"marche.
Peter Taylor

5

Ruby 1.9, 85 caractères

f=->a{require"date";d=Date.parse(a,0,0)+1;d+=1until d.day*d.month==58;d.strftime"%A"}

Solution simple. Appelez la fonction avec f[args].

  • Edit: (87 -> 97) Correction du cas de 0001-01-01test.
  • Edit 2: (97 -> 91) Date.parse permet également de spécifier la date de la réforme du calendrier.
  • Edit 3: (91 -> 87) Utilisez un lambda au lieu d'une fonction. Merci Dogbert !
  • Édition 4: (87 -> 85) Supprimez les espaces inutiles. Merci encore, Dogbert !

4
Échec du testcase pour "0001-01-01". La date de Ruby est trop puissante, elle tient compte des dates juliennes.
steenslag

@Ventero Que fait def *? Jamais vu auparavant.
steenslag

@steenslag: Merci, correction de ce testcase. def*définit juste une fonction appelée *. De cette façon, je n'ai pas besoin d'espace entre defet le nom de la fonction.
Ventero

1
Ne pourriez-vous pas simplement définir un lambda à la place? a = -> {...}
Dogbert

1
De plus, aucun espace n'est nécessaire après le temps de pause.
Dogbert

3

T-SQL 166 185 caractères

CREATE PROCEDURE f29 (@d DATETIME) AS
DECLARE @i int
SET @i=YEAR(DATEADD(M,-2,@d)+3)
SET @i=@i+(4-@i%4)
IF @i%100=0 AND @i%400<>0 SET @i=@i+4
SELECT DATENAME(W,CAST(@i AS CHAR)+'-2-29')

Je jouais déjà avec les fonctions de date T-SQL, alors j'ai pensé pourquoi pas ...

La solution d'origine était incorrecte ...

Voici ce que je dois réellement faire pour que cette stratégie fonctionne:

CREATE PROCEDURE f29 (@d DATE) AS
DECLARE @i int
SET @i = YEAR(@d)
BEGIN TRY 
SET @i=YEAR(DATEADD(D, 3, DATEADD(M,-2,@d)))
END TRY
BEGIN CATCH
END CATCH
SET @i=@i+(4-@i%4)
IF @i%100=0 AND @i%400<>0 SET @i=@i+4
SELECT DATENAME(W,CAST(@i AS CHAR)+'-2-29')

Étant donné que je crée un débordement soustrayant 2 mois du 0001-01-01 même si j'utilise le bon type de données, j'abandonne la création de quelque chose de court et valide pour cette question. O_o. Trixsy questionne.
mootinator

J'adore voir ces solutions T-SQL. :)
Steve

3

C #, 176

Func<String,String>f=(d)=>{DateTime n;for(n=DateTime.Parse(d).AddDays(307);!(DateTime.IsLeapYear(n.Year));n=n.AddYears(1)){}return new DateTime(n.Year,2,29).ToString("dddd");};

Vous pouvez économiser 8 octets en utilisant une définition de fonction normale:string f(string d){...}
Joey

.ToString("dddd")imprime la date dans les paramètres régionaux actuels, mais pas en anglais.
Joey

165 caractères => chaîne f (chaîne d) {var n = DateTime.Parse (d) .AddDays (307); while (! (DateTime.IsLeapYear (n.Year))) n = n.AddYears (1); return (nouveau DateTime (n.Année, 2,29)). DayOfWeek.ToString ();}
Stephan Schinkel

Encore amélioré à 127 caractères:string f(string d){var n=DateTime.Parse(d).AddDays(1);return DateTime.IsLeapYear(n.Year)&&n.DayOfYear==60?n.DayOfWeek+"":f(n+"");}
Patrik Westerlund

3

Bash, 96 octets

Merci Peter ... Version très golfée, 96 octets:

i=1;until [ `date -d"$1 $i days" +%m-%d` = "02-29" ];do((i++));done
date -d "${1} ${i} days" +%A

Ancienne version, 229 octets

#!/bin/bash
from=$1
i=1
while [ "$isFeb" = "" ] || [ "$is29" = "" ]
do
isFeb=`date -d "${from} ${i} days" | grep Feb`
is29=`date -d "${from} ${i} days" +%Y-%m-%d | grep "\-29"`
((i++))
done
((i--))
date -d "${from} ${i} days" +%A

EXEMPLE D'E / S

:~/aman>./29Feb.sh 0001-01-01
Sunday
:~/aman>./29Feb.sh 1899-12-03
Monday
:~/aman>./29Feb.sh 1970-01-01
Tuesday

pourrait avoir à définir TZ si aucun fuseau horaire par défaut n'est défini, j'ai appris cyberciti.biz/faq/… en faisant cela sur un IDE en ligne
Aman ZeeK Verma

1
Allez-vous jouer au golf? ; p Vous pouvez tout remplacer avant la ligne finale aveci=0;d=;until [ `date -d"$1 $i days" +%m-%d` = "02-29" ];do((i++));done
Peter Taylor

:-) comme nous avons déjà discuté de ma brutalité sur bash! ... Pour une raison quelconque, je ne joue pas beaucoup avec bash .. ils sont si sujets aux erreurs! .. Merci pour votre suggestion .. mise à jour!
Aman ZeeK Verma

1
Rawness avec bash n'est pas une excuse pour utiliser des noms de variables à quatre lettres: P
Peter Taylor

oui monsieur, j'ai compris.
Aman ZeeK Verma

2

Perl, pas de bibliothèque date: 160 159 155

sub f {($ y, $ m) = split / - /, @ _ ​​[0], 2; $ y ++ if ($ m> '02 -28 '); $ y = ($ y + 3)% 400 >> 2; $ y + = $ y &&! ($ Y% 25); @ r = (mardi, mercredi, jeudi, vendredi, samedi, dimanche, lundi); @ r [(5 * $ y - ($ y / 25 & 3))% 7]. "Jour";}

Le véritable avantage de ces bibliothèques de dates est de repousser la longueur des noms des jours à quelqu'un d'autre.

D'un autre côté, je pense que c'est la seule solution à ce jour qui fonctionne indépendamment des paramètres régionaux.


2

DATE et de la colle BASHy (90)

La fonction:

f(){ while :;do $(date -d$1+1day +'set - %F %A 1%m%d');(($3==10229))&&break;done;echo $2;}

Essai:

$ for x in 0001-01-01 1899-12-03 1970-01-01 1999-07-06 2003-05-22 2011-02-17 2100-01-01 ; do f $x ; done
Sunday
Monday
Tuesday
Tuesday
Sunday
Wednesday
Friday

1

D: 175 caractères

S f(S)(S s){auto d=Date.fromISOExtString(s)+days(1);while(d.month!=Month.feb||d.day!=29)d+=days(1);return["Sun","Mon","Tues","Wednes","Thurs","Fri","Sat"][d.dayOfWeek]~"day";}

Plus lisiblement:

S f(S)(S s)
{
    auto d = Date.fromISOExtString(s) + days(1);

    while(d.month != Month.feb || d.day != 29)
        d += days(1);

    return ["Sun", "Mon", "Tues", "Wednes", "Thurs", "Fri", "Sat"][d.dayOfWeek] ~ "day";
}

C'est très facile d'écrire en D, mais ça ne va certainement pas gagner de concours de golf de code. Pourtant, en dehors du golf de code, je préfèrerais de loin qu'il soit facile d'écrire et de comprendre, mais long que de le rendre concis mais difficile à écrire et à comprendre.


1

Java 8 - 252 caractères

Golfé:

import java.time.*;
import java.time.format.*;
public class S{public static void main(String[] a){LocalDate d=LocalDate.parse(a[0]).plusDays(1);while(d.getMonthValue()!=2||d.getDayOfMonth()!=29){d=d.plusDays(1);}System.out.println(d.getDayOfWeek());}}

Non golfé:

import java.time.*;
import java.time.format.*;
public class S {
    public static void main(String[] a) {
        LocalDate d = LocalDate.parse(a[0]).plusDays(1);

        while(d.getMonthValue()!=2 || d.getDayOfMonth()!=29) {
            d = d.plusDays(1);
        }
        System.out.println(d.getDayOfWeek());
    }
}

J'accepte les downvotes mais pouvez-vous s'il vous plaît expliquer "la nécro est réelle" et un lien vers une FAQ qui explique votre point? Je ne pensais pas que je gagnerais mais j'ai pensé qu'il serait intéressant de voir comment Java pourrait faire, en particulier. étant donné Java 8. Je considère le golf de code comme ayant des "classes de poids" par rapport à une compétition pure et simple. Java battra rarement Ruby ou Python.
Michael Easter

L'OP interdit les bibliothèques tierces, donc en 2011, une solution Java serait désagréable, car on ne pouvait pas utiliser la populaire bibliothèque Joda Time. Cependant, Java 8 (sorti en mars 2014) contient la bibliothèque JSR-310 DateTime - en.wikipedia.org/wiki/… . Ma raison est que je pensais que Java 8 serait amusant et potentiellement intéressant pour certains lecteurs. (Si vous n'êtes pas de ceux-là, très bien: il y a toujours une raison pour le poste.)
Michael Easter

1

Rebol - 78

f: func[d][system/locale/days/(until[d: d + 1 d/day * d/month = 58]d/weekday)]

Non golfé:

f: func [d] [
    system/locale/days/(
        until [
            d: d + 1
            d/day * d/month = 58
        ]
        d/weekday
    )
]

Exemple d'utilisation (dans la console Rebol):

>> f 0001-01-01
== "Sunday"

>> f 2100-01-01
== "Friday"

1

PHP, 104 octets

function f($s){for($y=$s-(substr($s,5)<"02-29");!date(L,$t=strtotime(++$y."-2-1")););return date(l,$t);}

panne

for($y=$s-;                 // "-" casts the string to int; decrement year if ...
    (substr($s,5)<"02-29")  // ... date is before feb 29
    !date(L,                        // loop while incremented $y is no leap year
        $t=strtotime(++$y."-2-1")   // $t=feb 01 in that year (same weekday, but shorter)
    );
);
return date(l,$t);          // return weekday name of that timestamp

date(L): 1pour l'année bissextile, 0sinon
date(l): représentation textuelle complète du jour de la semaine


0

GNU coreutils, 71 octets

f(){
seq -f "$1 %gday" 2921|date -f- +'%m%d%A'|sed 's/0229//;t;d;:;q'
}

Recherche linéaire des 8 prochaines années (pire cas, donné 2096-02-29). Sed trouve et sort la première ligne qui correspond au 29 février.

J'ai été surpris de constater que t;d;:;qc'était plus court que de tester pour voir si les chiffres restaient ( /[01]/d;q), bien qu'il y ait deux fois plus de commandes.

Les tests

J'ai ajouté une gamme supplémentaire de tests pour les cas d'angle difficiles:

for i in 0001-01-01.Sunday 1899-12-03.Monday \
    1970-01-01.Tuesday     1999-07-06.Tuesday \
    2003-05-22.Sunday      2011-02-17.Wednesday 2100-01-01.Friday \
    2000-02-28.Tuesday     2000-02-29.Sunday    2000-03-01.Sunday   2096-02-29.Friday
do
    printf "%s => %s (expected %s)\n" ${i%.*} $(f ${i%.*}) ${i#*.}
done
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.