Następne święto państwowe

18

Australijczycy uwielbiają święta i picie. Wczoraj, 26 stycznia, był dzień Australii, który jest świętem państwowym. Cieszyłem się, że nie byłem wczoraj w pracy i chętnie się dowiem, kiedy następnym razem będę mieć święto! Niestety, wypiłem trochę za dużo i nie jestem w stanie samodzielnie tego wypracować.

Napisz program, który jako dane przyjmie datę w australijskim zapisie daty / godziny (dd / mm) i wyśle ​​liczbę dni do następnego święta. Ponieważ jestem mieszkańcem Queensland (QLD), interesują mnie tylko święta, które mają wpływ na Queenslanders :

25/03 | Wielki Piątek
26/03 | Wielkanocna sobota
28.03 Poniedziałek Wielkanocny
25/04 | Anzac Dzień
02/05 | Święto Pracy
03/10 | Urodziny Królowej
25/12 | Boże Narodzenie
26.12
Drugi dzień świąt 27/12 | Święta Bożego Narodzenia

Zwróć uwagę na następujące strony:

Święta Bożego Narodzenia

Dodatkowe święto państwowe, które należy dodać, gdy Nowy Rok, Boże Narodzenie lub drugi dzień świąt przypada w weekend.

Ponieważ dzień Bożego Narodzenia przypada w niedzielę, jest dodatkowe święto państwowe. Boże Narodzenie jest wciąż świętem państwowym.

Ponieważ jestem poranną osobą, powinieneś podać aktualną datę jako dzień (ponieważ jest to najbardziej prawdopodobny czas, kiedy sprawdzę twój program na następne święto państwowe). Oznacza to, że jeśli zostanie podana data święta państwowego, wynik powinien być 0; jeśli dzień przed świętem państwowym jest wprowadzony, twoja produkcja będzie 1.

Interesują mnie tylko daty od teraz (27/01) do końca roku. Ostateczna data, którą musisz wziąć pod uwagę, to 31.12, w którym będzie twoja produkcja 1(na Nowy Rok).

Standardowe luki są zabronione.

Wejście

  • Wpis zawsze będzie składał się z 5 znaków: 4 liter, oddzielonych łącznikiem -lub ukośnikiem/
  • Dane wejściowe będą datą między 27/01 a 31/12

Wynik

  • Liczba dni do następnego święta w Queensland Australia, w tym data wprowadzenia: powinna być liczbą pomiędzy 0i 153(najdłuższa przerwa)
  • Brak nowych linii lub błędów

Przykłady

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

Mam nadzieję, że jest to jasne i nic nie umknie; jest to jednak moje drugie pytanie, więc docenię wszelkie opinie i postaram się jak najszybciej naprawić problemy.

Tas
źródło
@insertusernamehere Dziękujemy za wspaniałą sugestię! Dodałem daty do pytania
Tas
@Czy na pewno te daty są prawidłowe? Te w przykładach nie pasują do cytatu i oba nie pasują do witryny.
Adam Martin
@AdamMartin Dziękujemy za zwrócenie na to uwagi. Niepoprawnie wpisałem daty grudniowe. Te w tym przykładzie to tylko dowolne daty, nieokreślone w święta. Są to tylko przykłady dat, które można wprowadzić, i jaki powinien być wynik. Cytowane powinny (i mam nadzieję) pasować do tych ze strony internetowej.
Tas
Świętujesz urodziny królowej w październiku w Queensland? To takie dziwne, ale wydaje się poprawne z linku.
Level River St
Wow, nie macie wakacji od czerwca do września? To szorstkie.
Joe Z.

Odpowiedzi:

2

Pyth , 98 84 62 67 bajtów

Aktualizacja: Zapisano 14 bajtów, skracając listę liczby dni dla wszystkich 12 miesięcy do obliczenia liczby dni. Nie znalazłem dobrego sposobu na skompresowanie drugiej listy, wciąż próbując!

Aktualizacja 2: Zapisano kolejne 22 bajty, kończąc kodowanie listy liczb dziennych jako ciąg base256.

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

Wypróbuj online!

Ten sam algorytm jak w mojej odpowiedzi w języku Python. I nie ma wbudowanego, aby uzyskać dzień roku, więc musiałem to zrobić sam. Utworzenie tych dwóch list do obliczeń w ciągu roku i dni świątecznych jest dość kosztowne ... przejrzę je ponownie i spróbuję wygenerować je w mniejszej liczbie bajtów.

Denker
źródło
Wydaje się, że nie lubi danych wejściowych oddzielonych łącznikiem, ale poza tym jest świetny
Tas
@Tas Dzięki za podpowiedź, całkowicie przejrzałem tę część ... Naprawiono to kosztem 5 dodatkowych bajtów. Być może powinieneś dodać myślniki do skrzynek testowych, ponieważ chcesz, aby obejmowały każdą możliwą odmianę wejściową.
Denker
5

Visual Basic for Applications, 155 lub 118 bajtów

Wersja 1 - niezależna od ustawień regionalnych, 155 bajtów

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

Wersja 2 - zależna od ustawień regionalnych, 118 bajtów

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

Liczba bajtów dotyczy końcowego pliku .BAS, w tym znaków wiersza. Edytowany poza standardowym edytorem VBA (ponieważ nakłada dodatkowe spacje i pełne formy niektórych słów kluczowych) - ale importuje się i działa płynnie na dowolnej aplikacji Office (do testowania typu np. ? h("10/08")W bezpośrednim oknie lub w programie Excel bezpośrednio w formule komórkowej).

(ZMIENIONO) Początkowo zdecydowałem się użyć DateSerialfunkcji, aby funkcja była bezpieczna dla ustawień regionalnych (wersja 1). Ponieważ mieszkam w Brazylii i dlatego mój system jest skonfigurowany do używania formatu „dd / mm / rr” dla dat (podobnie jak w Australii), mógłbym napisać jeszcze mniejszą wersję, używając CDatezamiast tego (wersja 2). CDatewykorzystuje informacje o ustawieniach regionalnych systemu do konwersji tekstu na datę. W tej wersji założyłem również, że kod będzie uruchamiany tylko w 2016 r. (Jeśli rok zostanie pominięty (-6 bajtów) CDatezakłada bieżący rok według zegara systemowego).

Liczba 42454 w trzecim wierszu jest sumą 42450, która jest liczbową reprezentacją 01.01.2016 na VBA, i 84, która jest dniem roku na pierwsze wakacje. Tablica zawiera datę roku dla każdego święta (w tym 01.01.2017) przesuniętą o -84, ponieważ zabiera to kilka cyfr. Użycie 16 zamiast 2016 na DateSerialzabiera dwa kolejne bajty.

Tworzenie identycznej tablicy dziewięć razy w iteracji jest „złym” kodem, ale działa i zapisuje 3 kolejne bajty (jeden dla nazwy tablicy i jeden dla zewnętrznej pętli znaku równości, a drugi dla odniesienia do tablicy wewnątrz pętli).

„Brakujące” spacje między 0 a następującym słowem kluczowym w drugim i czwartym wierszu nie są konieczne, ponieważ są one ponownie wprowadzane automatycznie przez VBE podczas importowania modułu. Używany jako przestarzały, ale tani bajtowo, If <...> Goto <linenumber>aby zerwać z pętli ( If <...> Then Exit Fori If <...> Then Exit Functionużyć więcej znaków).

Skorzystano również z faktu, że nazwa funkcji w VBA zachowuje się jak zmienna lokalna, a jej wartość jest automatycznie zwracana przez funkcję pod koniec wykonywania.

dnep
źródło
Witamy w PPCG! Tutaj definiujemy język programowania przez tłumacza, więc wymaganie określonego ustawienia narodowego jest całkowicie dopuszczalne.
lirtosiast
Dzięki! Edytowano, aby dodać mniejszą wersję zależną od ustawień regionalnych.
dnep
4

JavaScript (ES6), 131 128 bajtów

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

Wyjaśnienie

Używa wbudowanego Datekonstruktora JavaScript do konwersji ciągu wejściowego na liczbę milisekund od epoki, a następnie porównuje to z liczbą milisekund dla każdego święta.

Odbywa się to poprzez przechowywanie dni ustawowo wolnych od pracy w tablicy jako liczby dni od daty odniesienia. Wybrałem 2016-01-29datę referencyjną, ponieważ liczbę milisekund od epoki można skrócić najkrótszą dla tej daty. Dowolna liczba milisekund między tym dniem a następnym działa, ponieważ wynik jest zaokrąglany w dół, a utrzymywanie liczby na środku pozwala uniknąć efektów związanych z czasem letnim (chociaż strefa czasowa PO nie ma czasu letniego). Liczba tego dnia to 1453986000000i zaokrąglenie do 1454000000000(dodanie kilku godzin) oznacza, że ​​można go zapisać jako 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

Test

To rozwiązanie zależy od strefy czasowej użytkownika. Działa to w strefie czasowej PO (i mojej) (GMT +1000). Jeśli chcesz go przetestować w innej strefie czasowej, dodanie numberOfHoursDifferentFromGMT1000 * 60 * 60 * 1000numeru daty odniesienia powinno działać. (np. GMT +0430 byłoby -5.5 * 60 * 60 * 1000 + 1454e9+n*864e5)

użytkownik 81655
źródło
Daje to zawsze 0, gdy data jest oddzielona łącznikiem. Poprosiłem już OP o dostosowanie jego skrzynek testowych, ponieważ wszystkie one mają znak dzielący.
Denker
@DenkerAffe Oh, myślałem, że miał na myśli, że możemy wybrać separator. Nawiasem mówiąc, uczynienie go separatorem-ambiwalentnym pozwoliło mi zaoszczędzić 3 bajty, więc dzięki!
user81655
1
Wydaje się, że reguła separated with a hyphen - or slash /jest nieco niejednoznaczna. Dla mnie oznacza to, że mamy do czynienia z obydwoma, ale zdecydowanie mogę zobaczyć twoją stronę. Zgadnij, że PO powinien to wyjaśnić.
Denker
3

T-SQL, 210 , 206 , 194 bajtów

(Pierwszy post tutaj, mam nadzieję, że jest ok, ale proszę bądź miły :)

Wejście wchodzi w @i, służy zarówno /i -jako separator. Jestem w Australii, więc mój format daty jest taki sam jak @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;

Zaktualizuj, varchar aby charzapisać 3 bajty plus usunięto spację :)

Aktualizacja 2 deklaruje @ci przypisuje bez wyboru

Liesel
źródło
2

T-SQL, 296 bajtów

Utworzono jako funkcję wycenioną w tabeli

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

Używany w następujący sposób

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)

Krótkie wyjaśnienie

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

JavaScript (ES6), 134 bajty

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 wciąż mnie pobił o 3 bajty, ale nie mogę znaleźć nigdzie indziej, żeby coś z tego wycisnąć. Działa, obliczając liczbę dni, które minęły, zamiast używać daty, a następnie porównując ją z szeregiem świątecznych przesunięć.

Mwr247
źródło
2

Python 2, 204 185 165 166 bajtów

Aktualizacja: Grałem w golfa o około 20 bajtów, obliczając osobno dzień roku. Nie ma już potrzeby długiego importu :)

Aktualizacja 2: Kolejne 20 Bajtów w dół, uświadamiając sobie, że mogę traktować nowy rok jak dzień 367 i wprowadzając inne drobne poprawki.

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

Wypróbuj online!

Nie golfowany:

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

Działa poprzez zapisanie liczby dni świątecznych na liście, odfiltrowanie dni poprzedzających podaną datę, pobranie pierwszego elementu z tej filtrowanej listy i odjęcie dnia roku, który został obliczony na podstawie danych wejściowych.

Denker
źródło
1

PHP, 116 bajtów

Całkiem proste podejście. Przechowuje dni roku na święta i wyskakuje tak długo, jak są w przeszłości. Na koniec odejmuje się żądany dzień roku.

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;

Pomiń wszystkie przypadki testowe. Działa z wiersza poleceń i akceptuje dane wejściowe przy użyciu łącznika, na przykład:

$ php holidays.php "12-05"
wstawić nazwę tutaj
źródło
1

ruby 1.9.3, 155 153 bajtów

Po świętach Bożego Narodzenia potrzebujemy naszego specjalnego dnia 366! Podobny przypadek jak @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

Stosowanie:

$ ruby i_want_to_break_free.rb "03/05"
Tarod
źródło
Nie wiem dużo o Ruby, ale myślę, że możesz zapisać 3 bajty, usuwając białe spacje w liniach 1 i 3. Powinieneś także określić, jakiej metody wprowadzania używasz, ponieważ nie jest to tak oczywiste w kodzie. Możesz zapisać niektóre bajty, definiując funkcję, dzięki czemu możesz wziąć dane wejściowe jako argumen i użyć wartości zwracanej jako danych wyjściowych.
Denker
@DenkerAffe Dziękuję bardzo! Zapisałem 2 bajty, ale myślę, że funkcja zwiększy liczbę. Zaktualizowałem odpowiedź za pomocą przykładu użycia.
Tarod
0

05AB1E , 45 bajtów

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

To może już nie być rok 2016, ale cokolwiek ...;) Nadal zakładamy, że rok 2016 jest rokiem przestępnym 29 w lutym.

Wypróbuj online lub sprawdź wszystkie przypadki testowe .

Wyjaśnienie:

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)

Zobacz ten 05AB1E końcówki kopalni (sekcje Jak skompresować dużych liczb całkowitych? I jak skompresować list całkowitych? ) , Aby zrozumieć, dlaczego •9JRt€ª´Q®Ië•jest 10549819042671399072072399; •9JRt€ª´Q®Ië•368вjest [85,86,88,116,123,277,360,361,362,367]; i •Σ₁t•jest 5354545.

Kevin Cruijssen
źródło