Nächster Feiertag

18

Australier lieben Feiertage und trinken gerne. Der 26. Januar war gestern in Australien ein Feiertag. Ich war froh, gestern nicht auf der Arbeit zu sein und gespannt darauf, wann ich das nächste Mal einen Feiertag habe! Leider hatte ich etwas zu viel zu trinken, und ich kann es nicht selbst herausfinden.

Schreiben Sie ein Programm, das ein Datum in australischer Datums- / Zeitnotation (TT / MM) als Eingabe verwendet und die Anzahl der Tage bis zum nächsten Feiertag ausgibt. Da ich in Queensland (QLD) wohnhaft bin, interessiere ich mich nur für Feiertage, die Queensländer betreffen :

25/03 | Karfreitag
26/03 | Ostersamstag
28/03 | Ostermontag
25/04 | Anzac Day
02/05 | Tag der Arbeit
03/10 | Geburtstag der Königin
25/12 | Weihnachtstag
26/12 | Weihnachtstag
27/12 | Weihnachtstag Urlaub

Beachten Sie auf der Website Folgendes:

Weihnachtstag Urlaub

Ein zusätzlicher Feiertag, der hinzugefügt wird, wenn der Neujahrstag, der Weihnachtstag oder der Boxtag auf ein Wochenende fallen.

Da der Weihnachtstag am Sonntag ist, gibt es einen zusätzlichen gesetzlichen Feiertag. Der Weihnachtstag ist immer noch ein Feiertag.

Da ich eine Morgenperson bin, sollten Sie das aktuelle Datum als Tag angeben (da dies die wahrscheinlichste Zeit ist, an der ich Ihr Programm für den nächsten Feiertag überprüfe). Das heißt, wenn das Datum eines Feiertags eingegeben wird, sollte Ihre Ausgabe sein 0; Wenn der Tag vor einem Feiertag eingegeben wird, wird Ihre Ausgabe sein 1.

Ich interessiere mich nur für Daten zwischen jetzt (dem 27/01) bis zum Ende des Jahres. Das letzte Datum, das Sie berücksichtigen müssen, ist der 31.12., An dem Ihre Ausgabe erfolgt 1(für den Neujahrstag).

Standardlücken sind verboten.

Eingang

  • Die Eingabe erfolgt immer aus 5 Zeichen: 4 Buchstaben, die durch einen Bindestrich -oder einen Schrägstrich getrennt sind/
  • Die Eingabe erfolgt nur zwischen dem 27.01. Und dem 31.12

Ausgabe

  • Die Anzahl der Tage bis zum nächsten Feiertag in Queensland, Australien, einschließlich des Eingabedatums: sollte eine Zahl zwischen 0und sein 153(die längste Lücke).
  • Keine neuen Zeilen oder Fehler

Beispiele

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

Hoffentlich ist das klar und nichts wird vermisst; Dies ist jedoch meine zweite Frage. Ich freue mich über jegliches Feedback und werde mein Bestes tun, um Probleme so schnell wie möglich zu beheben.

Tas
quelle
@insertusernamehere Danke für den tollen Vorschlag! Ich habe die Daten in der Frage hinzugefügt
Tas
@Sind Sie sicher, dass diese Daten korrekt sind? Die Beispiele stimmen nicht mit dem Zitat überein, und beide stimmen nicht mit der Website überein.
Adam Martin
@AdamMartin Danke für den Hinweis. Ich hatte die Dezember-Daten falsch eingegeben. In diesem Beispiel handelt es sich nur um beliebige Daten, die sich nicht auf Feiertage beziehen. Dies sind nur Beispiele für Daten, die eingegeben werden können und wie die Ausgabe aussehen soll. Die zitierten sollten (und sollten es hoffentlich tun) mit denen von der Website übereinstimmen.
Tas
Sie feiern den Geburtstag der Königin im Oktober in Queensland? Das ist so komisch, scheint aber aus dem Link richtig.
Level River St
Wow, ihr habt von Juni bis September keine Feiertage? Das ist rau.
Joe Z.

Antworten:

2

Pyth , 98 84 62 67 Bytes

Update: 14 Bytes wurden gespeichert, indem die Liste der Tageszählung für alle 12 Monate für die Berechnung der Tagesanzahl gekürzt wurde. Habe noch keine gute Möglichkeit gefunden, die andere Liste zu komprimieren!

Update2: Weitere 22 Bytes wurden gespeichert, indem die Liste der Tageszahlen als base256-Zeichenfolge endcodiert wurde.

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

Probieren Sie es online!

Gleicher Algorithmus wie in meiner Python-Antwort. Und kein eingebautes Gerät, um den Tag des Jahres zu bekommen, also musste ich es selbst machen. Das Erstellen dieser 2 Listen für die Berechnung des Tages des Jahres und für die Tage der Feiertage ist ziemlich kostspielig. Schauen Sie sich das noch einmal an und versuchen Sie, sie in weniger Bytes zu generieren.

Denker
quelle
Es scheint keine Eingabe zu mögen, die durch einen Bindestrich getrennt ist, aber ansonsten ist es großartig
Tas
@Tas Danke für den Hinweis, diesen Teil komplett überlesen ... Behebung auf Kosten von 5 weiteren Bytes. Vielleicht sollten Sie den Testfällen einige Bindestriche hinzufügen, da diese alle möglichen Eingabevariationen abdecken sollen.
Denker
5

Visual Basic für Applikationen, 155 oder 118 Bytes

Version 1 - Gebietsschemaunabhängig, 155 Byte

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

Version 2 - abhängig vom Gebietsschema, 118 Byte

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

Die Byteanzahl gilt für die endgültige .BAS-Datei, einschließlich der Zeilenvorschubzeichen. Wird außerhalb des Standard-VBA-Editors bearbeitet (da zusätzliche Leerzeichen und ausführliche Formulare einiger Schlüsselwörter erforderlich sind). Importiert und funktioniert jedoch problemlos in jeder Office-Anwendung (zum Testen von Text, z. B. ? h("10/08")in einem unmittelbaren Fenster oder in Excel, direkt in einer Zellenformel).

(BEARBEITET) Ursprünglich habe ich mich dafür entschieden DateSerial, die Funktion für das Gebietsschema sicher zu machen (Version 1). Da ich in Brasilien lebe und mein System so konfiguriert ist, dass es das Format "TT / MM / JJ" für Datumsangaben verwendet (genau wie in Australien), könnte ich CDatestattdessen eine noch kleinere Version schreiben (Version 2). CDateVerwendet Informationen zum Systemgebietsschema, um Text in Datum zu konvertieren. Ich habe in dieser Version auch angenommen, dass der Code nur im Jahr 2016 ausgeführt wird (wenn das Jahr weggelassen wird (-6 Byte) CDate, wird das aktuelle Jahr gemäß der Systemuhr angenommen).

Die Nummer 42454 in der dritten Zeile ist die Summe von 42450, die die numerische Darstellung von 01/01/2016 in VBA darstellt, und 84, die den Tag des Jahres für den ersten Feiertag darstellt. Das Array enthält den Tag des Jahres für jeden Feiertag (einschließlich 01.01.2017), versetzt um -84, da dies einige Stellen kostet. Bei Verwendung von 16 anstelle von 2016 werden DateSerialzwei weitere Bytes entfernt.

Neunmaliges Erstellen eines identischen Arrays innerhalb der Iteration ist "fehlerhafter" Code, funktioniert jedoch und speichert 3 weitere Bytes (eines für den Arraynamen und eines für das Gleichheitszeichen außerhalb der Schleife und eines für den Verweis auf das Array innerhalb der Schleife).

Die "fehlenden" Leerzeichen zwischen 0 und dem folgenden Schlüsselwort in der zweiten und vierten Zeile sind nicht erforderlich, da sie von VBE beim Import des Moduls automatisch wieder eingefügt werden. Verwendet veraltet, aber bytegünstig If <...> Goto <linenumber>, um die Schleife zu verlassen (beides If <...> Then Exit Forund If <...> Then Exit Functionmehr Zeichen).

Es wurde auch die Tatsache ausgenutzt, dass sich der Funktionsname in VBA als lokale Variable verhält und sein Wert am Ende der Ausführung automatisch von der Funktion zurückgegeben wird.

dnep
quelle
Willkommen bei PPCG! Hier definieren wir eine Programmiersprache durch den Interpreter, so dass es durchaus akzeptabel ist, ein bestimmtes Gebietsschema zu fordern.
Lirtosiast
Vielen Dank! Bearbeitet, um eine kleinere vom Gebietsschema abhängige Version hinzuzufügen.
27.
4

JavaScript (ES6), 131 128 Byte

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

Erläuterung

Verwendet den integrierten JavaScript- DateKonstruktor, um die Eingabezeichenfolge in eine Anzahl von Millisekunden seit der Epoche zu konvertieren, und vergleicht diese dann mit der Anzahl von Millisekunden für jeden Feiertag.

Dazu werden die Feiertage in einem Array als Anzahl der Tage seit einem Bezugsdatum gespeichert. Ich habe mich 2016-01-29für das Referenzdatum entschieden, da die Anzahl der Millisekunden seit der Epoche für dieses Datum am kürzesten ist. Eine beliebige Anzahl von Millisekunden zwischen diesem und dem nächsten Tag funktioniert, da das Ergebnis abgerundet ist und die mittlere Zahl keine Sommerzeiteffekte verursacht (obwohl die Zeitzone des OP keine Sommerzeit hat). Die Zahl dieses Tages ist 1453986000000und aufrunden 1454000000000(Hinzufügen von ein paar Stunden) bedeutet, dass es als geschrieben werden kann 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

Prüfung

Diese Lösung ist abhängig von der Zeitzone des Benutzers. Dies funktioniert in der Zeitzone des OP (und meiner) (GMT +1000). Wenn Sie wollen , dass es in einer anderen Zeitzone zu testen, das Hinzufügen numberOfHoursDifferentFromGMT1000 * 60 * 60 * 1000zum Stichtag Nummer sollte funktionieren. (zB GMT + 0430 wäre -5.5 * 60 * 60 * 1000 + 1454e9+n*864e5)

user81655
quelle
Dies ergibt immer 0, wenn das Datum durch einen Bindestrich getrennt ist. Ich habe das OP bereits gebeten, seine Testfälle anzupassen, da sie alle als Trennzeichen mit einem Schrägstrich versehen sind.
Denker
@DenkerAffe Oh, ich dachte, er meinte, wir könnten ein Trennzeichen frei wählen. Im Übrigen hat es mir 3 Bytes gespart, also danke!
user81655
1
Scheint, als ob die Regel separated with a hyphen - or slash /ein bisschen ambitioniert ist. Für mich bedeutet das, dass wir uns um beides kümmern müssen, aber ich kann definitiv Ihre Seite sehen. Ich denke, das OP sollte das klarstellen.
Denker
3

T-SQL, 210 , 206 , 194 Bytes

(Erster Beitrag hier, hoffe das ist ok, aber bitte sei nett :)

Die Eingabe @ierfolgt für beide /und -als Trennzeichen. Ich bin in Australien und habe das gleiche Datumsformat wie @Tas

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;

Update varchar zu charsparen 3 Byte plus entfernt , um einen Raum :)

Update 2 deklarieren @cund ohne Auswahl zuweisen

Liesel
quelle
2

T-SQL, 296 Bytes

Erstellt als Tabellenwertfunktion

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

Wird auf folgende Weise verwendet

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)

Eine kurze Erklärung

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
MickyT
quelle
2

JavaScript (ES6), 134 Byte

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 hat mich immer noch um 3 Bytes geschlagen, aber ich kann nirgendwo anders etwas finden, um hier rauszuquetschen. Berechnet die Anzahl der verstrichenen Tage, anstatt das Datum zu verwenden, und vergleicht es dann mit einer Reihe von Urlaubsversätzen.

Mwr247
quelle
2

Python 2, 204 185 165 166 Bytes

Update: Ich habe es um ~ 20 Bytes reduziert, indem ich den Tag des Jahres selbst berechnet habe. Keine Notwendigkeit für die langen Importe mehr :)

Update 2: Weitere 20 Bytes weniger, wenn ich feststelle, dass ich Silvester genauso wie Tag 367 behandeln und einige andere kleine Anpassungen vornehmen kann.

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

Probieren Sie es online!

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

Speichert die Anzahl der Feiertage am Tag des Jahres in einer Liste, filtert diejenigen heraus, die vor dem angegebenen Datum liegen, nimmt das erste Element in dieser gefilterten Liste und subtrahiert den Tag des Jahres, der wurde aus der Eingabe berechnet.

Denker
quelle
1

PHP, 116 Bytes

Ziemlich direkter Ansatz. Es speichert die Tage des Jahres für die Feiertage und zeigt sie an, solange sie in der Vergangenheit liegen. Schließlich wird der gewünschte Tag des Jahres abgezogen.

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;

Hinter allen Testfällen. Wird über die Befehlszeile ausgeführt und akzeptiert die Eingabe mit einem Bindestrich wie folgt:

$ php holidays.php "12-05"
insertusernamehere
quelle
1

Ruby 1.9.3, 155 153 Bytes

Nach den Weihnachtsferien brauchen wir unseren Super-Spezial-Tag 366! Ähnlich wie bei @DenkerAffe.

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

Verwendung:

$ ruby i_want_to_break_free.rb "03/05"
Tarod
quelle
Ich weiß nicht viel über Ruby, aber ich denke, Sie können 3 Bytes sparen, indem Sie Leerzeichen in Zeile 1 und 3 entfernen. Außerdem sollten Sie angeben, welche Eingabemethode Sie verwenden, da dies in Ihrem Code nicht so offensichtlich ist. Sie können einige Bytes einsparen, indem Sie eine Funktion definieren, sodass Sie die Eingabe als Argument und den Rückgabewert als Ausgabe verwenden können.
Denker
@DenkerAffe Vielen Dank! Ich habe 2 Bytes gespeichert, aber ich denke, dass eine Funktion die Zahl erhöht. Ich habe die Antwort mit einem Verwendungsbeispiel aktualisiert.
Tarod
0

05AB1E , 45 Bytes

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

Es ist vielleicht nicht mehr 2016, aber wie auch immer.;) Ich gehe immer noch davon aus, dass das Jahr 2016 ist, um ein Schaltjahr 29für den Februar zu werden.

Probieren Sie es online aus oder überprüfen Sie alle Testfälle .

Erläuterung:

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)

Sehen Sie sich meinen Tipp 05AB1E an (Abschnitte Wie komprimiere ich große Ganzzahlen? Und Wie komprimiere ich Ganzzahlenlisten? ) , Um zu verstehen, warum dies so •9JRt€ª´Q®Ië•ist 10549819042671399072072399; •9JRt€ª´Q®Ië•368вist [85,86,88,116,123,277,360,361,362,367]; und •Σ₁t•ist 5354545.

Kevin Cruijssen
quelle