Bir sonraki resmi tatil


18

Avustralyalılar resmi tatilleri ve içmeyi sever. 26 Ocak, resmi tatil olan Avustralya günü oldu. Dün işte olmama sevindim ve bir dahaki sefere resmi tatil alacağımı bilmek istekliydim! Ne yazık ki, içmek için biraz fazla şeyim vardı ve kendim için çalışamıyorum.

Girdi olarak Avustralya tarih / saat gösterimi (gg / aa) içinde bir tarih alacak bir program yazın ve bir sonraki resmi tatile kadar gün sayısını çıkarın . Bir Queensland (QLD) sakini olduğum için, sadece Queenslanders'ı etkileyen resmi tatillerle ilgileniyorum :

25/03 | İyi Cuma
26/03 | Paskalya Cumartesi
28/03 | Paskalya Pazartesi
25/04 | Anzak Günü
02/05 | İşçi Bayramı
03/10 | Kraliçenin Doğum Günü
25/12 | Noel Günü
26/12 | Boks Günü
27/12 | Noel Günü tatili

Siteden aşağıdakilere dikkat edin:

Noel Günü tatili

Yeni Yıl, Noel Günü veya Boks Günü hafta sonu düştüğünde eklenecek resmi tatil günü.

Noel günü Pazar günü olduğu için ekstra bir resmi tatil var. Noel günü hala resmi tatil.

Bir sabah insanı olduğum için, şu anki tarihi bir gün olarak eklemelisiniz (çünkü programınızı bir sonraki resmi tatil için kontrol edeceğim en olası zaman). Yani, resmi tatil günleri girilirse, çıktınız 0; resmi tatil gününden önceki gün girilirse, çıktınız olur 1.

Sadece şimdi (27/01) ile yıl sonuna kadar olan tarihlerle ilgileniyorum . Hesaplamanız gereken son tarih, çıktınızın olacağı 31/12'dir 1(Yılbaşı günü için).

Standart boşluklar yasaktır.

Giriş

  • Giriş her zaman 5 karakterden oluşur: Kısa çizgi -veya eğik çizgi ile ayrılmış 4 harf/
  • Girdi yalnızca 27/01 ve 31/12 arasında bir tarih olacak

Çıktı

  • Giris tarihi de dahil olmak üzere Queensland Avustralya'da bir sonraki resmi tatil gününe kadar geçen gün sayısı: 0ve 153(en uzun boşluk) arasında bir sayı olmalıdır
  • Yeni satır veya hata yok

Örnekler

01-05 = 1  
02-05 = 0  
03-05 = 153  
25/12 = 0
26-12 = 0
27/12 = 0
30/12 = 2
31-12 = 1

Umarım bu açıktır ve hiçbir şey kaçırılmaz; Ancak, bu benim ikinci sorum bu yüzden herhangi bir geri bildirim takdir ve ASAP sorunları çözmek için elimden geleni yapacağım.


@insertusernamehere Harika öneri için teşekkürler! Soruya tarihleri ​​ekledim
Tas

Bu tarihlerin doğru olduğundan emin misiniz? Örneklerde verilenler alıntıyla eşleşmiyor ve her ikisi de web sitesi ile eşleşmiyor.
Adam Martin

@AdamMartin Bunu işaret ettiğiniz için teşekkürler. Aralık tarihlerini yanlış koymuştum. Örnekteki olanlar resmi tatillere özgü olmayan herhangi bir tarihtir. Bunlar sadece girilebilecek tarihlere ve çıktının ne olması gerektiğine örnektir. Alıntı olanlar olmalıdır (ve umarım do) web sitesinden olanlar maç.
Tas

Queens'in Ekim ayında Kraliçenin doğum gününü kutluyor musunuz? Bu çok garip, ama bağlantıdan doğru görünüyor.
Level River St

Wow, Haziran ayından Eylül ayına kadar tatiliniz yok mu? Bu kaba.
Joe Z.

Yanıtlar:


2

Pyth , 98 84 62 67 Bayt

Güncelleme: Gün numarası hesaplaması için 12 ayın tümünde gün sayısı listesini kısaltarak 14 bayt kaydedildi. Diğer listeyi sıkıştırmak için iyi bir yol bulamadım, hala deniyorum!

Güncelleme2: Gün numaraları listesini base256 dizesi olarak kodlayarak 22 bayt daha kaydetti.

J30KhJ=Yc:z"\W"dd=N+s<[KtJKJKJKKJKJK)tseYshY-hfgTNCMc"UVXt{ĕŨũŪů"1N

Çevrimiçi deneyin!

Python cevabımdaki algoritmanın aynısı. Ve yılın gününü almak için hiçbir yerleşik, bu yüzden kendim yapmak zorundaydım. Yılın 2 günü ve tatil günleri için bu 2 listenin oluşturulması oldukça maliyetlidir ... tekrar inceleyip daha az bayt üretmeye çalışacaksınız.


Bir tire ile ayrılmış giriş gibi görünmüyor, ancak aksi halde harika
Tas

@Tas İpucu için teşekkürler, bu kısmı tamamen aştı ... 5 bayt daha maliyetle düzeltildi. Belki de test senaryolarına bazı tire işaretleri eklemelisiniz, çünkü olası her giriş varyasyonunu kapsamasını istersiniz.
Denker

5

Uygulamalar için Visual Basic, 155 veya 118 bayt

Sürüm 1 - yerel ayardan bağımsız, 155 bayt

Function h(d)
For i=0To 9
h=Array(0,1,3,31,38,192,275,276,277,282)(i)+42454-DateSerial(16,Val(Right(d,2)),Val(Left(d,2)))
If h>=0Goto 9
Next
9 End Function

Sürüm 2 - yerel ayara bağlı, 118 bayt

Function h(d)
For i=0To 9
h=Array(0,1,3,31,38,192,275,276,277,282)(i)+42454-CDate(d)
If h>=0Goto 9
Next
9 End Function

Bayt sayısı, satır besleme karakterleri dahil olmak üzere son .BAS dosyası içindir. Standart VBA editörünün dışında düzenlenmiştir (bazı anahtar kelimelerin ek boşluklarını ve ayrıntılı formlarını dayattığı için) - ancak herhangi bir Office Uygulamasını içe aktarır ve sorunsuz bir şekilde çalışır (örneğin ? h("10/08"), örneğin doğrudan pencerede veya Excel'de doğrudan bir hücre formülünde kullanımı test etmek için ).

(EDITED) Başlangıçta DateSerialişlevi yerel ayar için güvenli (sürüm 1) yapmak için kullanmayı seçtim . Brezilya'da yaşadığım için sistemim tarihler için "dd / mm / yy" biçimini kullanacak şekilde yapılandırıldığından (tıpkı Avustralya gibi) CDatebunun yerine daha küçük bir sürüm yazabilirim (sürüm 2). CDatemetni tarihe dönüştürmek için sistem yerel ayar bilgilerini kullanır. Ayrıca bu sürümde kodun sadece 2016 yılında çalıştırılacağını CDatevarsaydım (yıl atlanırsa (-6 bayt) sistem saatine göre geçerli yılı varsayar).

Üçüncü satırdaki 42454 sayısı, VBA'da 01/01/2016 sayısal gösterimi olan 42450 ve ilk tatil için yılın günü olan 844'tür. Dizi, her hane için (01/01/2017 dahil) -84 ile dengelenmiş yılın gününü içerir; çünkü bu, bazı basamakları alır. 2016 yerine 16 kullanmak DateSerialiki bayt daha alır.

Yinelemenin içinde dokuz kez özdeş bir dizi oluşturmak "kötü" koddur, ancak çalışır ve 3 bayt daha kaydeder (biri dizi adı için ve biri döngü dışında eşittir işareti için ve diğeri döngü içindeki diziye başvurmak için).

İkinci ve dördüncü satırlarda 0 ile aşağıdaki anahtar kelime arasındaki "eksik" boşluklar, modül içe aktarıldığında VBE tarafından otomatik olarak yeniden verildiği için gerekli değildir. Modası geçmiş kullanılmış ancak bayt ucuz If <...> Goto <linenumber>döngüden kırmak (hem If <...> Then Exit Forve If <...> Then Exit Functiondaha fazla karakter kullanın).

Ayrıca VBA'daki işlev adının yerel bir değişken olarak davrandığından ve değerinin yürütme sonunda işlev tarafından otomatik olarak döndürülmesinden yararlandı.


PPCG'ye Hoşgeldiniz! Burada yorumlayıcı tarafından bir programlama dili tanımladık, bu nedenle belirli bir yerel ayar gerektirmek tamamen kabul edilebilir.
lirtosiast

Teşekkürler! Yerel ayara bağlı daha küçük bir sürüm eklemek için düzenlendi.
dnep

4

JavaScript (ES6), 131 128 bayt

d=>[56,57,59,87,94,248,331,332,333,338].map(n=>r=r||(q=1454e9+n*864e5-new Date(d[3]+d[4]+`/${d[0]+d[1]}/16`))>=0&&q/864e5,r=0)|r

açıklama

DateGiriş dizesini çağdan beri birkaç milisaniyeye dönüştürmek için yerleşik JavaScript yapıcısını kullanır ve ardından bunu her resmi tatil için milisaniye sayısı ile karşılaştırır.

Bunu, resmi tatilleri bir dizide referans tarihinden itibaren geçen gün sayısı olarak saklayarak yapar. 2016-01-29Referans tarihi seçtim çünkü dönemden bu yana geçen milisaniye sayısı bu tarih için en kısa yoğunlaştırılabilir. Sonuç yuvarlanır ve sayının ortada tutulması, gün ışığından yararlanma etkilerini önler (OP'nin saat diliminde yaz saati uygulaması olmamasına rağmen), bu gün ve sonraki işler arasında herhangi bir milisaniye çalışır. Bu günün sayısı 1453986000000ve onu 1454000000000(birkaç saat ekleyerek) yuvarlamak olarak yazılabileceği anlamına gelir 1454e9.

d=>
  [56,57,59,87,94,248,331,332,333,338]             // list of day offsets from 01/29
  .map(n=>                                         // for each public holiday offset n
    r=r||                                          // if r is already set, do nothing
      (q=                                          // q = approximate difference in ms
        1454e9+n*864e5                             // time of public holiday
        -new Date(d[3]+d[4]+`/${d[0]+d[1]}/16`)    // time of input date
      )
      >=0&&                                        // if q >= 0
        q/864e5,                                   // r = q in days
    r=0                                            // r = result
  )
  |r                                               // floor and return r

Ölçek

Bu çözüm kullanıcının saat dilimine bağlıdır. Bu OP'nin (ve benim) saat diliminde (GMT +1000) çalışır. Farklı bir saat diliminde test etmek isterseniz numberOfHoursDifferentFromGMT1000 * 60 * 60 * 1000, referans tarih numarasına ekleme çalışması gerekir . (ör. GMT +0430 olurdu -5.5 * 60 * 60 * 1000 + 1454e9+n*864e5)


Tarih bir tire ile ayrıldığında her zaman 0 değerini verir. OP'den test kasetlerini ayarlamasını istedim, çünkü hepsi ayırıcı olarak eğik çizgi ile.
Denker

@DenkerAffe Oh, ayırıcı seçmekte özgür olduğumuzu düşündüm. Bu arada, ayırıcı-kararsız hale getirmek beni 3 bayt kurtardı, bu yüzden teşekkürler!
user81655

1
Kural separated with a hyphen - or slash /biraz belirsiz görünüyor. Benim için bu ikisiyle de uğraşmamız gerektiği anlamına geliyor, ama kesinlikle senin tarafını görebiliyorum. Sanırım OP bunu açıklığa kavuşturmalı.
Denker

3

T-SQL, 210 , 206 , 194 Bayt

(Buraya ilk yazı, Umarım bu tamam, ama lütfen iyi ol :)

Girdi @i, her ikisi için /ve -ayırıcı olarak girer . Avustralya'dayım, bu yüzden tarih formatım @Tas ile aynı

DECLARE @i CHAR(5)='23-09';DECLARE @c INT=DATEPART(dy,CAST(REPLACE(@i,'-','/')+'/2016' AS DATE))-1;SELECT MIN(b)-@c FROM(VALUES(84),(85),(87),(115),(122),(276),(359),(360),(361))a(b)WHERE b>=@c;

Güncelleme varchar için char3 bayt kaydeder artı bir boşluk kaldırıldı :)

Güncelleme 2 bildirimi @cve seçim olmadan atama


2

T-SQL, 296 bayt

Tablo değerli bir işlev olarak oluşturuldu

create function d(@ char(5))returns table return select min(o)o from(select datediff(day,cast('2016'+right(@,2)+left(@,2)as date),cast(right('2016'+right('0'+cast(d as varchar(4)),4),8)as datetime)+1)o from(values(324),(325),(327),(424),(501),(1002),(1224),(1225),(1226),(1231))d(d))d where 0<=o

Aşağıdaki şekilde kullanılır

SELECT *
FROM (
    VALUES
        ('01/05') --= 1  
        ,('02/05') --= 0  
        ,('03/05') --= 153  
        ,('25/12') --= 0
        ,('26/12') --= 0
        ,('27/12') --= 0
        ,('30/12') --= 2
        ,('31/12') --= 1
    )testData(i)
    CROSS APPLY (
        SELECT * FROM d(t)
    ) out

i     o
----- -----------
01/05 1
02/05 0
03/05 153
25/12 0
26/12 0
27/12 0
30/12 2
31/12 1

(8 row(s) affected)

Kısa bir açıklama

create function d(@ char(5)) returns table  -- function definition
return 
select min(o)o -- minimum set value
from(
    select datediff( -- date difference
        day, -- day units
        cast('2016'+right(@,2)+left(@,2)as date), -- convert input parameter to date
        cast(right('2016'+right('0'+cast(d as varchar(4)),4),8)as datetime)+1 -- convert int values into datetimes and add a day
        )o 
    from(
        values(324),(325),(327),(424),(501),(1002),(1224),(1225),(1226),(1231) -- integers representing the day before public holidays
        )d(d)
    )d 
where 0<=o -- only for values >= 0

2

JavaScript (ES6), 134 bayt

x=>[0,1,3,31,38,192,275,276,277,282].find(z=>z>=(q=x[0]+x[1]- -[...'20212122121'].slice(0,x[3]+x[4]-1).reduce((a,b)=>+b+a+29,0)-85))-q

user81655 beni hala 3 byte yendi, ama buradan bir şey sıkmak için başka bir yer bulamıyorum. Tarih kullanmak yerine geçmiş gün sayısını hesaplayıp, bir dizi tatil ofseti ile karşılaştırarak çalışır.


2

Python 2, 204 185 165 166 Bayt

Güncelleme: Yılın gününü kendim hesaplayarak ~ 20 Byte kadar golf. Artık uzun ithalata gerek yok :)

Güncelleme 2: Yeni yıllara 367. gün gibi davranabileceğimi ve başka küçük ayarlamalar yapabileceğimi fark ederek başka bir 20 Bayt daha azaldı.

def f(d):d=[d[:2],d[3:]];y=sum([31,29,31,30,31,30,31,31,30,31,30,31][:int(d[1])-1])+int(d[0]);return filter(lambda n:n>=y,[85,86,88,116,123,277,360,361,362,367])[0]-y

Çevrimiçi deneyin!

Ungolfed:

def f(d):
    l=[85,86,88,116,123,277,360,361,362,367]
    d=[d[:2],d[3:]]
    y=sum([31,29,31,30,31,30,31,31,30,31,30,31][:int(d[1])-1])+int(d[0])
    f=filter(lambda n:n>=y,l)
    return f[0]-y

Yılın tatil günlerini bir listede saklayarak, belirtilen tarihten önce olanları filtreleyerek, bu filtrelenmiş listedeki ilk öğeyi alarak ve yılın gününü çıkararak çalışır. girdiden hesaplanır.


1

PHP, 116 bayt

Oldukça basit bir yaklaşım. Tatil günleri için yılın günlerini depolar ve geçmişte oldukları sürece onları patlatır. Son olarak yılın talep edilen günü çıkarılır.

for($x=[366,361,360,359,276,122,115,87,85,84];($a=date(z,strtotime($argv[1].'-2016')))>$t=array_pop($x););echo$t-$a;

Tüm test senaryolarını geçmiş. Komut satırından çalışır ve aşağıdaki gibi bir tire kullanarak girişi kabul eder:

$ php holidays.php "12-05"

1

yakut 1.9.3, 155 153 bayt

Noel Günü tatilinden sonra süper özel gün 366'ya ihtiyacımız var! @DenkerAffe ile benzer durum.

require'date'
c=(Date.strptime(ARGV[0],'%d/%m')-Date.parse('01/01')).to_i
print [84,85,87,115,122,276,359,360,361,366].map{|i|(i-c)}.select{|i|i>=0}.min

Kullanımı:

$ ruby i_want_to_break_free.rb "03/05"

Ruby hakkında çok şey bilmiyorum, ama satır 1 ve 3'teki boşlukları kaldırarak 3 bayt kaydedebileceğinizi düşünüyorum. Ayrıca kodunuzda çok açık olmadığı için hangi giriş yöntemini kullandığınızı da belirtmelisiniz. Bir işlevi tanımlayarak bazı Baytlar kaydedebilirsiniz, böylece girdiyi argumen olarak alabilir ve dönüş değerini çıktı olarak kullanabilirsiniz.
Denker

@DenkerAffe Çok teşekkür ederim! 2 bayt kazandım, ancak bir fonksiyonun sayıyı artıracağını düşünüyorum. Cevabı bir kullanım örneğiyle güncelledim.
Tarod

0

05AB1E , 45 bayt

•9JRt€ª´Q®Ië•368вDI„-/S¡`•Σ₁t•ºS₂+s<£O+©@Ïн®-

Artık 2016 olmayabilir, ama her ne olursa olsun ..;) Yine de bir sıçrama yılı olması adına yılın 2016 olduğunu varsayar. 29 Şubat ayı için .

Çevrimiçi deneyin veya tüm test senaryolarını doğrulayın .

Açıklama:

9JRt€ª´Q®Ië•  # Push compressed integer 10549819042671399072072399
  368в         # Converted to base-368 as list: [85,86,88,116,123,277,360,361,362,367]
      D        # Duplicate this list
I              # Take the input
 „-/S¡         # Split it on ["-","/"]
      `        # Push both integer separated to the stack
•Σ₁t          # Push compressed integer 5354545
     º         # Mirror it without overlap: 53545455454535
      S        # Converted to a list of digits: [5,3,5,4,5,4,5,5,4,5,4,5,3,5]
       ₂+      # Add 26 to each: [31,29,31,30,31,30,31,31,30,31,30,31,29,31]
         s     # Swap to get the month-integer
          <    # Decrease it by 1
           £   # Only leave the first month-1 values from the integer-list
            O  # Sum that sublist
             + # And add it to the day-integer (so we now have the N'th day of the year)
©              # Save this in the register (without popping)
 @             # Do a >= check with each integer in the first (duplicated) list we created
  Ï            # Only leave the truthy values from the list
   н           # Then pop this sublist and only leave its first value
    ®-         # And subtract the integer we saved in the register (N'th day of the year)
               # (after which the result is output implicitly)

Bu 05AB1E ucuma bakın (neden büyük tamsayılar nasıl sıkıştırılır ? Ve tamsayı listeleri nasıl sıkıştırılır? ) Bölümlerinin neden •9JRt€ª´Q®Ië•olduğunu anlamak için 10549819042671399072072399; •9JRt€ª´Q®Ië•368вolduğu [85,86,88,116,123,277,360,361,362,367]; ve •Σ₁t•öyle 5354545.

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.