Giorno della settimana del prossimo 29 febbraio


14

Scrivi una funzione che accetta una data e restituisce il giorno della settimana del prossimo 29 febbraio successivo a quella data.

  • L'input è una stringa nel formato ISO esteso: AAAA-MM-GG (ad es. 27 maggio 2010 sarebbe "2010-05-27").

  • L'output è una stringa che è il nome del giorno della settimana (ad es. "Lunedì"). Le maiuscole non contano, ma danno il nome completo in inglese.

  • Se la data specificata è il 29 febbraio, restituisci il giorno della settimana del 29 febbraio successivo .

  • Usa i calcoli per il Calendario Gregoriano Prolettico (quindi usa i calcoli dell'anno bisestile Gregoriano per la sua intera lunghezza). Non preoccuparti per il calendario giuliano o quando si è verificato il passaggio da Giuliano a Gregoriano. Supponi solo Gregoriano per tutto.

  • La funzione dovrebbe funzionare almeno per l'intervallo "0001-01-01" - "2100-01-01".

  • Sentiti libero di usare qualunque libreria standard fornita dalla tua lingua preferita, ma non utilizzare librerie di terze parti a meno che tu non voglia includere quel codice come parte della tua soluzione.

  • Vince il codice più breve (il minor numero di caratteri).

Esempi:

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

(e no, non devi nominare la funzione func)

suggerimenti:

  • Ricorda che gli anni che terminano con 00 che non sono divisibili per 400 non sono anni bisestili.
  • 1 gennaio 0001 è un lunedì.

Risposte:


7

Windows PowerShell, 65

Abbastanza semplice.

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

Come al solito, possiamo radere due byte se siamo disposti ad aspettare molto tempo fino al completamento:

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

Storia:

  • 18/02/2011 00:06 (65) Primo tentativo.

Quale percorso è necessario affinché questo funzioni? Ho un appuntamento con GnuWin sul mio percorso, che lo sta rompendo.
Peter Taylor,

@Peter: potrebbe scontrarsi con date. Rimuovi GNUWin32 dal PERCORSO e dovrebbe funzionare. O passare datea Get-Date(quel tipo di comportamento di fallback funziona solo quando non viene trovato alcun comando - per controllare, basta usare gcm date). Comunque, non ritengo che un particolare problema con questo script come GNUWin32 non faccia parte di alcuna installazione standard di Windows.
Joey,

Il motivo per cui l'ho chiesto è perché ho già provato a utilizzare get-datee ho ricevuto il messaggio di errore Method invocation failed because [System.Management.Automation.PSObject] doesn't contain a method named 'op_Addition'.È necessario PS2 o .Net 4 o qualcosa del genere?
Peter Taylor,

@Peter: ho provato PowerShell v2. .NET 4 non ci gioca perché PowerShell è collegato al runtime 2.0. In ogni caso, non dovrebbe esserci un oggetto PSO di ritorno Get-Datema a System.DateTime.
Joey,

È molto strano. $d=Get-Date "0400-01-01"; $d++fornisce un messaggio di errore per ++non essere definito in DateTime. Lo stesso sostituisce ++con +=1o +="1"o +='1'dà il messaggio di errore su PSObject. E +"1"funziona e basta .
Peter Taylor,

5

Ruby 1.9, 85 caratteri

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

Soluzione semplice. Chiamare la funzione con f[args].

  • Modifica: (87 -> 97) Risolto il 0001-01-01testcase.
  • Modifica 2: (97 -> 91) Date.parse consente di specificare anche la data della riforma del calendario.
  • Modifica 3: (91 -> 87) Usa una lambda invece di una funzione. Grazie Dogbert !
  • Modifica 4: (87 -> 85) Rimuovi gli spazi non necessari. Grazie ancora, Dogbert !

4
Non riesce la testcase per "0001-01-01". La data di Ruby è troppo potente, prende in considerazione le date di Julian.
steenslag,

@Ventero Cosa fa def *? Non l'ho mai visto prima.
steenslag,

@steenslag: Grazie, risolto quel testcase. def*definisce solo una funzione chiamata *. In questo modo non ho bisogno di uno spazio tra defe il nome della funzione.
Ventero,

1
Non potresti semplicemente definire un lambda invece? a = -> {...}
Dogbert,

1
Inoltre, non è necessario alcuno spazio dopo lo Strftime.
Dogbert,

3

T-SQL 166 185 caratteri

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

Stavo già scherzando con le funzioni di data T-SQL, quindi ho pensato perché no ...

La soluzione originale non era corretta ...

Ecco cosa devo effettivamente fare per far funzionare quella strategia:

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

Dato che creo un overflow sottraendo 2 mesi da 0001-01-01 anche se utilizzo il tipo di dati corretto, rinuncio a creare qualcosa di breve e valido per questa domanda. O_o. Trixsy interroga.
Mootinator

Adoro vedere queste soluzioni 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");};

Puoi salvare 8 byte usando una normale definizione di funzione:string f(string d){...}
Joey,

.ToString("dddd")stampa la data nella locale corrente, tuttavia, non in inglese.
Joey,

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

Migliorato ulteriormente a 127 caratteri: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 byte

Grazie Peter ... Versione altamente giocata, 96 byte:

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

Vecchia versione, 229 byte

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

I / O CAMPIONE

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

potrebbe essere necessario impostare TZ se non è impostato alcun fuso orario predefinito, ho imparato cyberciti.biz/faq/… mentre lo facevo su alcuni IDE online
Aman ZeeK Verma,

1
Hai intenzione di giocare a golf? ; p Puoi sostituire tutto prima della riga finale coni=0;d=;until [ `date -d"$1 $i days" +%m-%d` = "02-29" ];do((i++));done
Peter Taylor,

:-) come abbiamo già discusso della mia crudeltà sulla bash! ... Per qualche ragione, non giocherò molto con bash .. sono così inclini all'errore! .. Grazie per il tuo suggerimento .. aggiornato!
Aman ZeeK Verma,

1
Rawness with bash non è una scusa per usare nomi di variabili di quattro lettere: P
Peter Taylor

si signore, ho capito bene.
Aman ZeeK Verma,

2

Perl, nessuna biblioteca di 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 = (martedì, Wednes, Gio, ven, Sab, dom, lun);! @ r [(5 * $ y - ($ y / 25 e 3))% 7] "giorno";.}

Il vero vantaggio di queste librerie di date è spingere la lunghezza dei nomi dei giorni a qualcun altro.

D'altra parte, penso che questa sia l'unica soluzione finora che funziona indipendentemente dalle impostazioni locali.


2

DATA e alcuni BASHy colla (90)

La funzione:

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

test:

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

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

Più leggibilmente:

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

Scrivere in D è molto semplice, ma sicuramente non vincerà nessun concorso di golf. Tuttavia, al di fuori del golf del codice, preferirei che fosse facile scrivere e capire, ma a lungo piuttosto che essere conciso ma difficile da scrivere e capire.


1

Java 8 - 252 caratteri

golfed:

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

Accetto i voti negativi, ma puoi spiegare "il necro è reale" e linkare a una FAQ che spiega il tuo punto? Non pensavo che avrei vinto, ma ho pensato che sarebbe stato interessante vedere come Java avrebbe potuto fare, esp. dato Java 8. Vedo il codice golf come "classi di peso" rispetto a una vera e propria competizione. Java raramente batterà completamente Ruby o Python.
Michael Easter,

L'OP vieta le librerie di terze parti, quindi nel 2011 una soluzione Java sarebbe sgradevole, dal momento che non si potrebbe usare la famosa libreria Joda Time. Tuttavia, Java 8 (rilasciato a marzo 2014) contiene la libreria DateSime JSR-310 - en.wikipedia.org/wiki/… . La mia ragione è che pensavo che Java 8 sarebbe stato divertente e potenzialmente interessante per alcuni lettori. (Se non sei uno di quelli, va bene: c'è ancora una ragione per il post.)
Michael Easter,

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

Esempio di utilizzo (nella console di Rebol):

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

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

1

PHP, 104 byte

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

abbattersi

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): 1per l'anno bisestile, 0altrimenti
date(l): rappresentazione testuale completa del giorno della settimana


0

Coreutils GNU, 71 byte

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

Ricerca lineare dei prossimi 8 anni (caso peggiore, dato 2096-02-29). Sed trova e produce la prima riga che corrisponde al 29 febbraio.

Sono stato sorpreso di scoprire che t;d;:;qera più breve dei test per vedere se le cifre rimanevano ( /[01]/d;q), nonostante fossero due volte più comandi.

test

Ho aggiunto una linea extra di test per casi angolari difficili:

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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.