Wochentag des nächsten 29. Februar


14

Schreiben Sie eine Funktion, die ein Datum annimmt und den Wochentag des nächsten 29. Februar nach diesem Datum zurückgibt.

  • Die Eingabe ist eine Zeichenfolge im erweiterten ISO-Format: JJJJ-MM-TT (z. B. 27. Mai 2010 wäre "2010-05-27").

  • Die Ausgabe ist eine Zeichenfolge, die den Namen des Wochentags enthält (z. B. "Montag"). Die Groß- und Kleinschreibung spielt keine Rolle, aber geben Sie den vollständigen Namen auf Englisch an.

  • Wenn das angegebene Datum der 29. Februar ist, geben Sie den Wochentag des nächsten 29. Februar zurück.

  • Verwenden Sie die Berechnungen für den proleptischen Gregorianischen Kalender (also verwendet er die Gregorianischen Schaltjahrberechnungen für die gesamte Länge). Machen Sie sich keine Sorgen um den Julianischen Kalender oder wann der Wechsel von Julianisch zu Gregorisch stattgefunden hat. Nehmen Sie einfach Gregorian für alles an.

  • Die Funktion sollte für mindestens den Bereich "0001-01-01" - "2100-01-01" funktionieren.

  • Sie können alle Standardbibliotheken verwenden, die in der Sprache Ihrer Wahl verfügbar sind. Verwenden Sie jedoch keine Bibliotheken von Drittanbietern, es sei denn, Sie möchten diesen Code als Teil Ihrer Lösung verwenden.

  • Kürzester Code (wenigste Zeichen) gewinnt.

Beispiele:

  • 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"

(und nein, Sie müssen die Funktion nicht benennen func)

Hinweise:

  • Denken Sie daran, dass Jahre, die mit 00 enden und nicht durch 400 teilbar sind, keine Schaltjahre sind.
  • Der 1. Januar 0001 ist ein Montag.

Antworten:


7

Windows PowerShell, 65

Ziemliech direkt.

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

Wie üblich können wir zwei Bytes abschneiden, wenn wir bereit sind, lange bis zur Fertigstellung zu warten:

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

Prüfung:

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

Geschichte:

  • 2011-02-18 00:06 (65) Erster Versuch.

Welcher Weg ist notwendig, damit dies funktioniert? Ich habe GnuWin-Date in meinem Pfad, was es bricht.
Peter Taylor

@ Peter: Es könnte mit kollidieren date. Entfernen Sie einfach GNUWin32 aus dem PATH und es sollte funktionieren. Oder ändern Sie datezu Get-Date(diese Art von Fallback-Verhalten funktioniert nur, wenn kein Befehl gefunden wird - zum Überprüfen einfach verwenden gcm date). Wie auch immer, ich denke nicht, dass dieses Skript ein besonderes Problem darstellt, da GNUWin32 nicht Teil einer Windows-Standardinstallation ist.
Joey

Der Grund, warum ich gefragt habe, war, dass ich bereits versucht habe, PS2 oder .Net 4 zu verwenden get-dateund die Fehlermeldung erhalten Method invocation failed because [System.Management.Automation.PSObject] doesn't contain a method named 'op_Addition'.habe.
Peter Taylor

@ Peter: Ich habe PowerShell v2 ausprobiert. .NET 4 spielt nicht darauf ab, da PowerShell mit der 2.0-Laufzeitumgebung verknüpft ist. Auf jeden Fall sollte es kein PSObject geben, das zurückkommt, Get-Datesondern ein System.DateTime.
Joey

Es ist sehr komisch. $d=Get-Date "0400-01-01"; $d++gibt eine Fehlermeldung darüber aus ++, dass sie bei DateTime nicht definiert wurde. Das gleiche Ersetzen ++mit +=1oder +="1"oder +='1'gibt die Fehlermeldung über PSObject. Und +"1"funktioniert einfach .
Peter Taylor

5

Ruby 1.9, 85 Zeichen

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

Einfache Lösung. Rufen Sie die Funktion mit auf f[args].

  • Bearbeiten: (87 -> 97) Der 0001-01-01Testfall wurde behoben.
  • Bearbeiten 2: (97 -> 91) Mit Date.parse können Sie auch das Datum der Kalenderreform angeben.
  • Edit 3: (91 -> 87) Verwenden Sie ein Lambda anstelle einer Funktion. Danke Dogbert !
  • Edit 4: (87 -> 85) Entferne unnötige Leerzeichen. Nochmals vielen Dank, Dogbert !

4
Schlägt den Testfall für "0001-01-01" fehl. Ruby's Date ist zu mächtig, es berücksichtigt julianische Daten.
Steenslag

@Ventero Was macht def *? Ich habe es noch nie gesehen.
Steenslag

@steenslag: Danke, das Problem wurde behoben. def*definiert nur eine aufgerufene Funktion *. Auf diese Weise brauche ich kein Leerzeichen zwischen defund dem Funktionsnamen.
Ventero

1
Könnten Sie nicht stattdessen einfach ein Lambda definieren? a = -> {...}
Dogbert

1
Auch nach Feierabend wird kein Platz mehr benötigt.
Dogbert

3

T-SQL 166 185 Zeichen

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

Ich habe bereits mit T-SQL-Datumsfunktionen rumgespielt und mir überlegt, warum nicht ...

Die ursprüngliche Lösung war falsch ...

Folgendes muss ich tatsächlich tun, damit diese Strategie funktioniert:

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

Da ich einen Überlauf von 2 Monaten von 0001-01-01 erstelle, auch wenn ich den richtigen Datentyp verwende, gebe ich es auf, etwas Kurzes und Gültiges für diese Frage zu erstellen . O_o. Trixsy befragt.
mootinator

Ich mag es, diese T-SQL-Lösungen zu sehen. :)
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");};

Mit einer normalen Funktionsdefinition können Sie 8 Bytes einsparen:string f(string d){...}
Joey

.ToString("dddd")gibt das Datum in der aktuellen Ländereinstellung aus, jedoch nicht in Englisch.
Joey

165 Zeichen => Zeichenfolge f (Zeichenfolge d) {var n = DateTime.Parse (d) .AddDays (307); while (! (DateTime.IsLeapYear (n.Year))) n = n.AddYears (1); return (new DateTime (n.Year, 2,29)). DayOfWeek.ToString ();}
Stephan Schinkel

Weiter verbessert auf 127 Zeichen: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 Bytes

Danke Peter ... Sehr gute Version, 96 Bytes:

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

Alte Version, 229 Bytes

#!/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

BEISPIEL E / A

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

Möglicherweise müssen TZ einzustellen , wenn keine Standard - Zeitzone eingestellt ist, habe ich gelernt , cyberciti.biz/faq/... während diese auf einigen Online - IDE zu tun
Aman zeek Verma

1
Wirst du das Golf spielen? ; p Sie können alles vor der letzten Zeile durchi=0;d=;until [ `date -d"$1 $i days" +%m-%d` = "02-29" ];do((i++));done
Peter Taylor

:-) Wie wir bereits über meine Rohheit bei Bash gesprochen haben! ... Aus irgendeinem Grund spiele ich nicht viel mit Bash. Sie sind so fehleranfällig! .. Vielen Dank für Ihren Vorschlag. Aktualisiert!
Aman ZeeK Verma

1
Rawness with bash ist keine Entschuldigung für die Verwendung von Variablennamen mit vier Buchstaben: P
Peter Taylor

Ja, Sir, ich habe verstanden, worum es geht.
Aman ZeeK Verma

2

Perl, keine Datumsbibliothek: 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 = (Dienstag, Mittwoch, Donnerstag, Freitag, Samstag, Sonntag, Montag); @ r [(5 * $ y - ($ y / 25 & 3))% 7]. "Tag";}

Der eigentliche Vorteil dieser Datumsbibliotheken besteht darin, dass die Länge der Namen der Tage an andere weitergegeben wird.

Andererseits denke ich, dass dies die einzige Lösung ist, die bisher funktioniert, unabhängig vom Gebietsschema.


2

DATUM und etwas BASHY-Kleber (90)

Die Funktion:

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

Testen:

$ 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 Zeichen

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

Mehr leserlich:

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

Es ist sehr einfach, in D zu schreiben, aber es wird definitiv keinen Code-Golfwettbewerb gewinnen. Abgesehen vom Code-Golfen wäre es mir viel lieber, wenn ich es einfach schreiben und verstehen könnte, aber lange nicht knapp, aber schwer zu schreiben und zu verstehen.


1

Java 8 - 252 Zeichen

Golf gespielt:

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());}}

Ungolfed:

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());
    }
}

Ich akzeptiere Downvotes, aber kannst du bitte erklären, dass "der Necro echt ist" und einen Link zu einer FAQ erstellen, die deinen Standpunkt erklärt? Ich hätte nicht gedacht, dass ich gewinnen würde, aber ich dachte, es wäre interessant zu sehen, wie Java funktionieren könnte, vor allem. Angesichts von Java 8. Ich betrachte Codegolf als "Gewichtsklasse" im Vergleich zu einer regelrechten Konkurrenz. Java wird Ruby oder Python selten schlagen.
Michael Ostern

Das OP verbietet Bibliotheken von Drittanbietern, daher wäre eine Java-Lösung im Jahr 2011 unangenehm, da die beliebte Joda Time-Bibliothek nicht verwendet werden konnte. Java 8 (veröffentlicht im März 2014) enthält jedoch die JSR-310 DateTime-Bibliothek - en.wikipedia.org/wiki/… . Mein Grund ist, dass ich dachte, Java 8 würde Spaß machen und möglicherweise für einige Leser interessant sein. (Wenn Sie nicht einer von denen sind, fein: es gibt noch einen Grund für den Pfosten.)
Michael Ostern

1

Rebol - 78

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

Ungolfed:

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

Anwendungsbeispiel (in der Rebol-Konsole):

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

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

1

PHP, 104 Bytes

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

Nervenzusammenbruch

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): 1für Schaltjahr, 0sonst
date(l): vollständige Textdarstellung des Wochentags


0

GNU Coreutils, 71 Bytes

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

Lineare Suche der nächsten 8 Jahre (schlimmster Fall, gegeben am 29.02.2096). Sed findet und gibt die erste Zeile aus, die dem 29. Februar entspricht.

Ich war überrascht festzustellen, dass dies t;d;:;qkürzer war als das Testen, um festzustellen, ob die Ziffern ( /[01]/d;q) blieben , obwohl es doppelt so viele Befehle gab.

Tests

Ich habe eine zusätzliche Reihe von Tests für schwierige Eckfälle hinzugefügt:

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
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.