Önümüzdeki 29 Şubat haftasının günü


14

Tarih alan ve bu tarihten sonraki 29 Şubat tarihinin haftasını döndüren bir işlev yazın.

  • Giriş, ISO Genişletilmiş biçiminde bir dizedir: YYYY-AA-GG (örn. 27 Mayıs 2010, "2010-05-27" olacaktır).

  • Çıktı, haftanın gününün adı olan bir dizedir (örneğin, "Pazartesi"). Büyük harf kullanımı önemli değildir, ancak tam adını İngilizce olarak verin.

  • Belirtilen tarih 29 Şubat ise, bir sonraki 29 Şubat'ın haftasının gününü döndürün.

  • Proleptik Gregoryen Takvimi için hesaplamaları kullanın (bu nedenle, tüm uzunluğu için Gregoryen sıçrama yılı hesaplarını kullanır). Julian Takvimi veya Julian'dan Gregorian'a geçiş olduğunda endişelenmeyin. Sadece herţey için Gregoryen varsay.

  • İşlev en azından "0001-01-01" - "2100-01-01" aralığında çalışmalıdır.

  • Seçtiğiniz dilin sağladığı standart kitaplıkları kullanmaktan çekinmeyin, ancak bu kodu çözümünüzün bir parçası olarak eklemek istemiyorsanız 3. taraf kitaplıkları kullanmayın.

  • En kısa kod (en az karakter) kazanır.

Örnekler:

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

(ve hayır, işlevi adlandırmanız gerekmez func)

İpuçları:

  • 00 ile biten ve 400 ile bölünemeyen yılların artık yıl olmadığını unutmayın.
  • 1 Ocak, 0001 Pazartesi.

Yanıtlar:


7

Windows PowerShell, 65

Yeterince açıksözlü.

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

Her zamanki gibi, tamamlanana kadar uzun süre beklemek istiyorsak, iki bayt tıraş edebiliriz:

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

Ölçek:

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

Tarih:

  • 2011-02-18 00:06 (65) İlk deneme.

Bunun çalışması için hangi yol gereklidir? Yolumda GnuWin tarihi var, ki bu onu kırıyor.
Peter Taylor

@Peter: Çatışabilir date. Sadece GNUWin32'yi PATH'den çıkarın ve çalışması gerekir. Ya değişim dateiçin Get-Date(- sadece kullanımını kontrol etmek yedek davranış bu tür yalnızca hiçbir komut bulunduğunda çalışır gcm date). Her neyse, GNUWin32 herhangi bir standart Windows kurulumunun bir parçası olmadığı için bu komut dosyasında belirli bir sorun olduğunu düşünmüyorum.
Joey

Sormamın nedeni zaten kullanmayı denedim get-dateve hata mesajını aldım çünkü Method invocation failed because [System.Management.Automation.PSObject] doesn't contain a method named 'op_Addition'.PS2 veya .Net 4 veya daha fazlasına ihtiyaç var mı?
Peter Taylor

@Peter: PowerShell v2'yi denedim. PowerShell 2.0 çalışma zamanına bağlı olduğundan .NET 4 oynatmıyor. Her durumda, geri dönen bir PSObject olmamalı Get-Dateama a System.DateTime.
Joey

Çok garip. DateTime'da tanımlanmama konusunda $d=Get-Date "0400-01-01"; $d++bir hata mesajı veriyor ++. PSObject ++ile aynı +=1veya +="1"veya ile +='1'ilgili hata mesajı verir. Ve sadece +"1"çalışıyor.
Peter Taylor

5

Yakut 1.9, 85 karakter

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

Kolay çözüm. İşlevi ile çağırın f[args].

  • Düzenleme: (87 -> 97) 0001-01-01Test çantası düzeltildi .
  • Düzenleme 2: (97 -> 91) Date.parse, takvim reformunun tarihinin de belirtilmesine izin verir.
  • Düzenleme 3: (91 -> 87) İşlev yerine lambda kullanın. Teşekkürler Dogbert !
  • Düzenleme 4: (87 -> 85) Gereksiz alanları kaldırın. Tekrar teşekkürler, Dogbert !

4
"0001-01-01" için testcase başarısız olur. Ruby'nin Tarihi çok güçlü, Julian tarihlerini hesaba katıyor.
steenslag

@Ventero def * ne yapar? Daha önce hiç görmedim.
steenslag

@steenslag: Teşekkürler, o test çantasını düzeltti. def*sadece denilen bir işlevi tanımlar *. Bu yolla defişlev adı arasında boşluk bırakmam gerekmiyor .
Ventero

1
Bunun yerine sadece bir lambda tanımlayamaz mısın? a = -> {...}
Wile E. Coyote

1
Ayrıca, strftime sonrası herhangi bir yere ihtiyaç yoktur.
Wile E. Coyote

3

T-SQL 166185 Karakterler

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

Zaten T-SQL tarih fonksiyonları ile karışıklık yapıyordum, bu yüzden neden olmasın ...

Orijinal çözüm yanlıştı ...

İşte ne aslında işin bu stratejiyi almak için yapmanız gereken:

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

Doğru veri tipini kullansam bile , bu soru için kısa ve geçerli bir şey yaratmaktan vazgeçtim . O_o. Trixsy soruları.
mootinator

Bu T-SQL çözümlerini görmeyi seviyorum. :)
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");};

Normal bir işlev tanımı kullanarak 8 bayt kaydedebilirsiniz:string f(string d){...}
Joey

.ToString("dddd")tarihi, İngilizce değil, geçerli yerel ayarda yazdırır.
Joey

165 karakter => string f (string d) {var n = DateTime.Parse (d) .AddDays (307); while (! (DateTime.IsLeapYear (n.Year))) n = n.AddYears (1); döndür (yeni DateTime (n.Year, 2,29)). DayOfWeek.ToString ();}
Stephan Schinkel

127 karakter daha geliştirildi: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 bayt

Teşekkürler Peter ... Yüksek golf versiyonu, 96 bayt:

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

Eski versiyon, 229 bayt

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

ÖRNEK G ​​/ Ç

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

Herhangi bir varsayılan saat dilimi ayarlanmamışsa TZ'yi ayarlamanız gerekebilir , bunu bazı çevrimiçi IDE'de yaparken
cyberciti.biz/faq/…

1
Bunu golf oynayacak mısın? ; p Son çizgiden önce her şeyi değiştirebilirsinizi=0;d=;until [ `date -d"$1 $i days" +%m-%d` = "02-29" ];do((i++));done
Peter Taylor

:-) zaten tartıştığımız gibi ham-neşem bash üzerinde! ... Nedense, bash ile çok fazla uğraşmayın .. onlar çok hata eğilimli! .. ur öneri için teşekkürler .. güncellendi!
Aman ZeeK Verma

1
Bash ile Rawness dört harfli değişken adları kullanmak için bir mazeret değildir: P
Peter Taylor

evet efendim, anladım.
Aman ZeeK Verma

2

Perl, hiçbir tarih kütüphanesi: 160 159 155

sub f {($ y, $ m) = bölünmüş / - /, @ _ ​​[0], 2; ($ m> '02 -28 ') ise; $ y = ($ y + 3)% 400 >> 2, $ y + = $ y && ($ y% 25); '(r = Salı, Çarş, Perşembe, Cu, Satur, güneş, Pt),! @ r [(5 x $ y - ($ y / 25 ve 3))% 7] "günlük";.}

Bu tarih kütüphanelerinin asıl yararı, günlerin adlarının uzunluğunu başka birine iletmektir.

Öte yandan, bence bu bölge ne olursa olsun işe yarayan tek çözüm.


2

DATE ve bazı BASHy tutkalları (90)

İşlev:

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

Test yapmak:

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

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

Daha okunaklı:

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

D'de yazmak çok kolay, ama kesinlikle herhangi bir kod golf yarışmasını kazanmayacak. Yine de, kod golf dışında, yazmayı ve anlamayı çok daha kolay olurdu ama uzun ama kısa yazmak ve anlamak zor.


1

Java 8-252 karakter

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

Downvotes kabul ediyorum ama lütfen "necro gerçek" i açıklayabilir ve amacınızı açıklayan bir SSS'ye bağlantı verebilir misiniz? Kazanacağımı düşünmedim ama Java'nın nasıl yapabileceğini görmenin ilginç olacağını düşündüm, esp. Java 8. kod golf açık bir rekabet karşı "ağırlık sınıfları" olarak görüyorum. Java, Ruby veya Python'u nadiren yener.
Michael Easter

OP üçüncü taraf kütüphanelerini yasaklar, bu nedenle 2011'de popüler bir Joda Time kütüphanesini kullanamadığından bir Java çözümü hoş olmazdı. Ancak, Java 8 (Mart 2014'te piyasaya sürüldü) JSR-310 DateTime kütüphanesini içerir - en.wikipedia.org/wiki/… . Benim nedenim, Java 8'in eğlenceli ve potansiyel olarak bazı okuyucular için ilginç olacağını düşündüm. (Bunlardan biri değilseniz, iyi: hala görevin bir nedeni var.)
Michael Easter

1

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

Örnek kullanım (Rebol konsolunda):

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

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

1

PHP, 104 bayt

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

Yıkmak

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): 1artık yıl için, 0aksi takdirde
date(l): haftanın gününün tam metin temsili


0

GNU çekirdek dosyaları, 71 bayt

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

Önümüzdeki 8 yılın doğrusal araştırması (en kötü durum, 2096-02-29 verildi). Sed, 29 Şubat ile eşleşen ilk satırı bulur ve çıkarır.

İki kat t;d;:;qdaha fazla /[01]/d;qkomut olmasına rağmen basamakların ( ) olup olmadığını görmek için testten daha kısa olduğunu görünce şaşırdım .

Testler

Zor köşe vakaları için ekstra bir test satırı ekledim:

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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.