Dzień tygodnia następnego 29 lutego

14

Napisz funkcję, która pobiera datę i zwraca dzień tygodnia 29 lutego po tej dacie.

  • Dane wejściowe to ciąg znaków w rozszerzonym formacie ISO: RRRR-MM-DD (np. 27 maja 2010 r. To „2010-05-27”).

  • Dane wyjściowe to ciąg znaków, który jest nazwą dnia tygodnia (np. „Poniedziałek”). Wielkie litery nie mają znaczenia, ale podaj pełną nazwę w języku angielskim.

  • Jeśli podana data to 29 lutego, zwróć dzień tygodnia następnego 29 lutego .

  • Skorzystaj z obliczeń dla Proleptycznego kalendarza gregoriańskiego (więc korzysta z obliczeń gregoriańskiego roku przestępnego na całej długości). Nie martw się kalendarzem juliańskim lub kiedy nastąpiła zmiana z Juliana na gregoriański. Wystarczy założyć Gregorian za wszystko.

  • Funkcja powinna działać co najmniej w zakresie „0001-01-01” - „2100-01-01”.

  • Możesz swobodnie korzystać ze wszystkich standardowych bibliotek dostępnych w wybranym języku, ale nie używaj bibliotek innych firm, chyba że chcesz uwzględnić ten kod jako część swojego rozwiązania.

  • Najkrótszy kod (najmniej znaków) wygrywa.

Przykłady:

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

(i nie, nie musisz nazywać funkcji func)

Poradnik:

  • Pamiętaj, że lata kończące się na 00, których nie można podzielić przez 400, nie są latami przestępnymi.
  • 1 stycznia 0001 to poniedziałek.
Jonathan M. Davis
źródło

Odpowiedzi:

7

Windows PowerShell, 65

Dość bezpośredni.

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

Jak zwykle możemy zgolić dwa bajty, jeśli chcemy długo czekać na zakończenie:

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

Test:

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

Historia:

  • 2011-02-18 00:06 (65) Pierwsza próba.
Joey
źródło
Jaka ścieżka jest niezbędna, aby to zadziałało? Mam datę GnuWin na mojej ścieżce, która ją łamie.
Peter Taylor
@Peter: Może się kolidować date. Po prostu usuń GNUWin32 ze ŚCIEŻKI i powinno działać. Lub zmień datena Get-Date(tego rodzaju zachowanie rezerwowe działa tylko wtedy, gdy nie zostanie znalezione polecenie - sprawdź, po prostu użyj gcm date). W każdym razie nie uważam tego za szczególny problem z tym skryptem, ponieważ GNUWin32 nie jest częścią żadnej standardowej instalacji Windows.
Joey
Powodem, dla którego zapytałem, było to, że już próbowałem użyć get-datei dostałem komunikat o błędzie Method invocation failed because [System.Management.Automation.PSObject] doesn't contain a method named 'op_Addition'.Czy to wymaga PS2 lub .Net 4 czy coś takiego?
Peter Taylor
@Peter: Próbowałem PowerShell v2. .NET 4 nie działa, ponieważ PowerShell jest połączony z środowiskiem wykonawczym 2.0. W każdym razie nie powinien wracać obiekt PSObject, Get-Dateale System.DateTime.
Joey,
To bardzo dziwne. $d=Get-Date "0400-01-01"; $d++wyświetla komunikat o błędzie dotyczący ++braku definicji w DateTime. To samo zastąpienie ++z +=1lub +="1"czy +='1'daje komunikat o błędzie o PSObject. I po prostu +"1"działa.
Peter Taylor
5

Ruby 1.9, 85 znaków

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

Proste rozwiązanie. Wywołaj funkcję za pomocą f[args].

  • Edycja: (87 -> 97) Naprawiono 0001-01-01testcase.
  • Edycja 2: (97 -> 91) Date.parse pozwala również określić datę reformy kalendarza.
  • Edycja 3: (91 -> 87) Użyj lambda zamiast funkcji. Dzięki Dogbert !
  • Edycja 4: (87 -> 85) Usuń niepotrzebne spacje. Dzięki jeszcze raz,Jeszcze Dogbert !
Ventero
źródło
4
Nie udaje się test „0001-01-01”. Data Ruby jest zbyt potężna, bierze pod uwagę daty Juliana.
steenslag
@Ventero Co robi def *? Nigdy wcześniej tego nie widziałem.
steenslag
@steenslag: Dzięki, naprawiłem tę skrzynkę testową. def*po prostu definiuje funkcję o nazwie *. W ten sposób nie potrzebuję spacji między defnazwą funkcji.
Ventero
1
Czy zamiast tego nie możesz po prostu zdefiniować lambda? a = -> {...}
Wile E. Coyote
1
Poza tym po strftime nie jest potrzebne miejsce.
Wile E. Coyote
3

T-SQL 166 185 znaków

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

Już miałem problemy z funkcjami daty T-SQL, więc pomyślałem, dlaczego nie ...

Oryginalne rozwiązanie było niepoprawne ...

Oto, co właściwie muszę zrobić, aby ta strategia zadziałała:

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')
mootinator
źródło
Biorąc pod uwagę, że tworzę przepełnienie odejmując 2 miesiące od 0001-01-01, nawet jeśli używam poprawnego typu danych, rezygnuję z tworzenia czegoś krótkiego i ważnego dla tego pytania. O_o. Trixsy zadaje pytania.
mootinator
Uwielbiam widzieć te rozwiązania 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");};
Kris Iwanow
źródło
Możesz zapisać 8 bajtów, używając normalnej definicji funkcji:string f(string d){...}
Joey
.ToString("dddd")drukuje datę w bieżącym języku, ale nie w języku angielskim.
Joey
165 znaków => ciąg f (ciąg 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
Dalsza poprawa do 127 znaków: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 bajtów

Dzięki Peter ... Wersja z golfem, 96 bajtów:

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

Stara wersja, 229 bajtów

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

PRZYKŁADOWE I / O

:~/aman>./29Feb.sh 0001-01-01
Sunday
:~/aman>./29Feb.sh 1899-12-03
Monday
:~/aman>./29Feb.sh 1970-01-01
Tuesday
Aman ZeeK Verma
źródło
być może będę musiał ustawić TZ, jeśli nie zostanie ustawiona domyślna strefa czasowa, nauczyłem się cyberciti.biz/faq/… , robiąc to na IDE online
Aman ZeeK Verma
1
Idziesz w golfa? ; p Możesz zamienić wszystko przed ostatnią linią nai=0;d=;until [ `date -d"$1 $i days" +%m-%d` = "02-29" ];do((i++));done
Peter Taylor
:-) jak już rozmawialiśmy o mojej surowości nad bash! ... Z jakiegoś powodu nie bawię się zbytnio w bash .. są tacy podatni na błędy! .. Dziękujemy za sugestie .. zaktualizowane!
Aman ZeeK Verma
1
Surowość z bash nie jest usprawiedliwieniem używania czteroliterowych nazw zmiennych: P
Peter Taylor
tak proszę pana, mam rację.
Aman ZeeK Verma
2

Perl, bez biblioteki dat: 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 = (Wt, Wednes, Czw, Pt, Satur, Słońce, Pon); @ r [(5 * $ y - ($ r / 25 i 3))% 7]. „Dzień”;}

Prawdziwą zaletą tych bibliotek dat jest przekazywanie komuś nazwy nazw dni.

Z drugiej strony myślę, że jest to jedyne jak dotąd rozwiązanie, które działa niezależnie od ustawień regionalnych.

Peter Taylor
źródło
2

DATA i trochę BASHY klej (90)

Funkcja:

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

Testowanie:

$ 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

źródło
1

D: 175 znaków

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

Bardziej czytelnie:

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

Pisanie w języku D jest bardzo łatwe, ale na pewno nie wygra żadnych konkursów golfowych. Mimo to, poza golfem kodowym, wolałbym, aby pisanie i rozumienie było łatwiejsze, ale dłuższe niż zwięzłe, ale trudne do napisania i zrozumienia.

Jonathan M. Davis
źródło
1

Java 8 - 252 znaków

Gra w golfa:

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

Nie golfowany:

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());
    }
}
Michael Easter
źródło
Akceptuję opinie negatywne, ale czy możesz wyjaśnić, że „nekro jest prawdziwe” i link do często zadawanych pytań, które wyjaśniają Twój punkt widzenia? Nie sądziłem, że wygram, ale pomyślałem, że byłoby ciekawe zobaczyć, jak Java może sobie poradzić, szczególnie. biorąc pod uwagę Javę 8. Uważam, że kod golfowy ma „klasy wagowe” w porównaniu do bezpośredniej konkurencji. Java rzadko pokonuje Ruby lub Python wprost.
Michael Easter
OP zabrania bibliotek stron trzecich, więc w 2011 r. Rozwiązanie Java byłoby nieprzyjemne, ponieważ nie można było korzystać z popularnej biblioteki Joda Time. Jednak Java 8 (wydana w marcu 2014 r.) Zawiera bibliotekę DateTime JSR-310 - en.wikipedia.org/wiki/… . Moim powodem jest to, że myślałem, że Java 8 będzie fajna i potencjalnie interesująca dla niektórych czytelników. (Jeśli nie jesteś jednym z nich, w porządku: wciąż jest powód do tego postu.)
Michael Easter
1

Rebol - 78

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

Nie golfowany:

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

Przykładowe użycie (w konsoli Rebol):

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

>> f 2100-01-01
== "Friday"
draegtun
źródło
1

PHP, 104 bajty

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

awaria

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): 1dla roku przestępnego, w 0innym przypadku
date(l): pełna reprezentacja tekstowa dnia tygodnia

Tytus
źródło
0

Coreutils GNU, 71 bajtów

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

Wyszukiwanie liniowe przez następne 8 lat (najgorszy przypadek, podany 2096–02–29). Sed znajduje i wysyła pierwszą linię, która pasuje do 29 lutego.

Byłem zaskoczony, gdy stwierdziłem, że t;d;:;qbyło to krócej niż testowanie, czy cyfry pozostały (/[01]/d;q ), mimo że dwukrotnie więcej poleceń.

Testy

Dodałem dodatkową linię testów do trudnych przypadków narożnych:

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
Toby Speight
źródło