Prossimo giorno festivo


18

Gli australiani adorano le festività e il bere. Ieri, il 26 gennaio, è stato il giorno dell'Australia, che è un giorno festivo. Ero contento di non essere al lavoro ieri e desideroso di sapere la prossima volta che avrò un giorno festivo! Sfortunatamente, avevo un po 'troppo da bere e non sono in grado di risolverlo da solo.

Scrivi un programma che prenderà una data nella notazione di data / ora australiana (gg / mm) come input e fornirà il numero di giorni fino al giorno festivo successivo. Poiché sono residente nel Queensland (QLD), sono interessato solo ai giorni festivi che interessano il Queensland :

25/03 | Venerdì Santo
26/03 | Pasqua sabato
28/03 | Lunedì di Pasqua
25/04 | Anzac Day
02/05 | Festa del lavoro
03/10 | Compleanno della regina
25/12 | Giorno di Natale
26/12 | Santo Stefano
27/12 | Vacanze di Natale

Nota quanto segue dal sito:

Vacanze di Natale

Un giorno festivo aggiuntivo da aggiungere quando cade il fine settimana di Capodanno, Natale o Santo Stefano.

Perché il giorno di Natale è la Domenica, v'è un ulteriore festivo. Il giorno di Natale è ancora un giorno festivo.

Dato che sono una persona mattiniera, dovresti includere la data corrente come giorno (poiché è l'ora più probabile che controllerò il tuo programma per il prossimo giorno festivo). Cioè, se viene inserita la data di un giorno festivo, l'output dovrebbe essere 0; se viene inserito il giorno prima di un giorno festivo, l'output sarà 1.

Sono interessato solo alle date tra oggi (il 27/01) fino alla fine dell'anno. La data finale di cui dovrai tenere conto è il 31/12 dove sarà la tua uscita 1(per il giorno di Capodanno).

Sono vietate le scappatoie standard .

Ingresso

  • L'input avrà sempre 5 caratteri: 4 lettere, separate da un trattino -o una barra/
  • L'input sarà solo una data tra il 27/01 e il 31/12

Produzione

  • Il numero di giorni fino al prossimo giorno festivo nel Queensland in Australia, inclusa la data di inserimento: dovrebbe essere un numero compreso tra 0e 153(il divario più lungo)
  • Nessuna nuova riga o errore

Esempi

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

Speriamo che sia chiaro e non manchi nulla; tuttavia, questa è la mia seconda domanda, quindi apprezzerò qualsiasi feedback e farò del mio meglio per risolvere i problemi al più presto.


@inserireusernamehere Grazie per l'ottimo suggerimento! Ho aggiunto le date alla domanda
Tas,

@ Sei sicuro che quelle date siano corrette? Quelli negli esempi non corrispondono alla citazione ed entrambi non corrispondono al sito Web.
Adam Martin,

@AdamMartin Grazie per averlo sottolineato. Avevo inserito erroneamente le date di dicembre. Quelli nell'esempio sono solo tutte le date, non specifiche per i giorni festivi. Sono solo esempi di date che potrebbero essere inserite e quale dovrebbe essere l'output. I citati dovrebbero (e si spera lo facciano) corrispondere a quelli del sito Web.
Tas,

Celebri il compleanno della regina ad ottobre nel Queensland? È così strano, ma sembra corretto dal collegamento.
Level River St,

Wow, ragazzi non avete vacanze da giugno a settembre? È difficile.
Joe Z.

Risposte:


2

Pyth , 98 84 62 67 byte

Aggiornamento: 14 byte salvati accorciando l'elenco del conteggio dei giorni per tutti i 12 mesi per il calcolo del numero del giorno. Non ho ancora trovato un buon modo per comprimere l'altro elenco, ci sto ancora provando!

Update2: salvato altri 22 byte terminando la codifica dell'elenco dei numeri del giorno come stringa base256.

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

Provalo online!

Stesso algoritmo della mia risposta Python. E niente da fare per ottenere il giorno dell'anno, quindi ho dovuto farlo da solo. La creazione di questi 2 elenchi per il calcolo del giorno dell'anno e per i giorni delle vacanze è piuttosto costosa ... controlleremo di nuovo e proveremo a generarli in meno byte.


Non sembra che l'input sia separato da un trattino, ma per il resto è fantastico
Tas

@Tas Grazie per il suggerimento, ho letto completamente quella parte ... Risolto il problema al costo di altri 5 byte. Forse dovresti aggiungere alcuni trattini ai casi di test, poiché vuoi che coprano ogni possibile variazione di input.
Denker,

5

Visual Basic, Applications Edition, 155 o 118 byte

Versione 1 - indipendente dalla locale, 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

Versione 2 - dipendente dalla locale, 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

Il conteggio dei byte è per il file .BAS finale, inclusi i caratteri di avanzamento riga. Modificato al di fuori dell'editor VBA standard (in quanto impone spazi aggiuntivi e forme dettagliate di alcune parole chiave) - ma importa ed esegue senza problemi su qualsiasi applicazione di Office (per testare il tipo, ad esempio ? h("10/08")in una finestra immediata, o in Excel utilizzare direttamente in una formula di cella).

(EDITED) Inizialmente ho scelto di utilizzare DateSerialper rendere la funzione locale-sicura (versione 1). Dato che vivo in Brasile e quindi il mio sistema è configurato per utilizzare il formato "gg / mm / aa" per le date (proprio come in Australia), potrei scrivere una versione ancora più piccola usando CDateinvece (versione 2). CDateutilizza le informazioni sulla locale del sistema per convertire il testo in data. Ho anche ipotizzato in questa versione che il codice sarebbe stato eseguito solo durante il 2016 (se si omette l'anno (-6 byte) si CDateassume l'anno corrente secondo l'orologio di sistema).

Il numero 42454 sulla terza riga è la somma di 42450 che è la rappresentazione numerica del 01/01/2016 su VBA e 84 che è il giorno dell'anno per il primo giorno festivo. L'array contiene il giorno dell'anno per ogni festività (incluso il 01/01/2017) compensato di -84 poiché questo porta via alcune cifre. L'uso di 16 invece del 2016 su DateSerialporta via altri due byte.

La creazione di un array identico nove volte all'interno dell'iterazione è un codice "errato", ma funziona e salva altri 3 byte (uno per il nome dell'array e uno per il ciclo esterno uguale segno e uno in più per fare riferimento all'array all'interno del ciclo).

Gli spazi "mancanti" tra 0 e la seguente parola chiave sulla seconda e quarta riga non sono necessari in quanto vengono reintrodotti automaticamente da VBE quando il modulo viene importato. Usato obsoleto ma a basso costo If <...> Goto <linenumber>per interrompere il ciclo (entrambi If <...> Then Exit Fore If <...> Then Exit Functionutilizzare più caratteri).

Ha anche approfittato del fatto che il nome della funzione in VBA si comporta come una variabile locale e il suo valore viene restituito automaticamente dalla funzione al termine dell'esecuzione.


Benvenuti in PPCG! Qui definiamo un linguaggio di programmazione dall'interprete, quindi è perfettamente accettabile richiedere un determinato locale.
lirtosiast,

Grazie! Modificato per aggiungere una versione più piccola dipendente dalla locale.
DP

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

Spiegazione

Utilizza il Datecostruttore incorporato JavaScript per convertire la stringa di input in un numero di millisecondi dall'epoca, quindi confronta questo con il numero di millisecondi per ogni giorno festivo.

Lo fa memorizzando le festività pubbliche in un array come il numero di giorni dalla data di riferimento. Ho scelto 2016-01-29per la data di riferimento perché il numero di millisecondi dall'epoca può essere ridotto il più breve per questa data. Qualsiasi numero di millisecondi tra questo giorno e il prossimo funziona perché il risultato è arrotondato per difetto e mantenere il numero al centro evita gli effetti dell'ora legale (anche se il fuso orario del PO non ha l'ora legale). Il numero di questo giorno è 1453986000000e arrotondandolo a 1454000000000(aggiungendo un paio d'ore) significa che può essere scritto come 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

Questa soluzione dipende dal fuso orario dell'utente. Funziona nel fuso orario dell'OP (e mio) (GMT +1000). Se si desidera testarlo in un fuso orario diverso, l'aggiunta numberOfHoursDifferentFromGMT1000 * 60 * 60 * 1000al numero della data di riferimento dovrebbe funzionare. (es. GMT +0430 sarebbe -5.5 * 60 * 60 * 1000 + 1454e9+n*864e5)


Questo dà sempre 0 quando la data è separata da un trattino. Ho già chiesto all'OP di modificare i suoi test, dal momento che sono tutti separati da una barra.
Denker,

@DenkerAffe Oh, pensavo intendesse dire che eravamo liberi di scegliere un separatore. Per inciso, rendendolo separatore-ambivalente mi ha salvato 3 byte, quindi grazie!
user81655

1
Sembra che la regola separated with a hyphen - or slash /sia un po 'ambigua. Per me significa che dobbiamo occuparci di entrambi, ma posso sicuramente vedere la tua parte. Immagino che l'OP dovrebbe chiarire questo.
Denker,

3

T-SQL, 210 , 206 , 194 byte

(Primo post qui, spero che sia ok, ma per favore sii gentile :)

L'input entra in @i, si rivolge a entrambi /e -come separatore. Sono in Australia, quindi il mio formato della data è lo stesso di @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;

Aggiorna varchar per charsalvare 3 byte più rimosso uno spazio :)

L'aggiornamento 2 dichiara @ce assegna senza selezionare


2

T-SQL, 296 byte

Creato come una funzione con valori di tabella

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

Usato nel modo seguente

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)

Una breve spiegazione

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 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 mi fa ancora battere di 3 byte, ma non riesco a trovare altrove per spremere qualcosa da qui. Funziona calcolando il numero di giorni trascorsi invece di utilizzare Date, quindi confrontandolo con una matrice di offset festivi.


2

Pitone 2, 204 185 165 166 Bytes

Aggiornamento: ridotto di ~ 20 byte calcolando il giorno dell'anno da solo. Non sono più necessarie lunghe importazioni :)

Aggiornamento 2: altri 20 byte in meno rendendomi conto che posso trattare i nuovi anni come il giorno 367 e apportando alcune piccole modifiche.

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

Provalo 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

Funziona memorizzando il numero del giorno dell'anno delle festività in un elenco, filtrando quelle che sono prima della data specificata, prendendo il primo elemento in quell'elenco filtrato e sottraendo il giorno dell'anno, che ottenuto calcolato dall'input.


1

PHP, 116 byte

Approccio piuttosto diretto. Memorizza i giorni dell'anno per le festività e li fa scoppiare finché sono in passato. Viene infine sottratto il giorno richiesto dell'anno.

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;

Passato tutti i casi di test. Viene eseguito dalla riga di comando e accetta l'input utilizzando un trattino, come:

$ php holidays.php "12-05"

1

rubino 1.9.3, 155 153 byte

Dopo le vacanze di Natale, abbiamo bisogno del nostro 366 giorno super speciale! Caso simile a @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

Uso:

$ ruby i_want_to_break_free.rb "03/05"

Non so molto su Ruby, ma penso che puoi salvare 3 byte rimuovendo gli spazi bianchi nelle righe 1 e 3. Inoltre dovresti specificare quale metodo di input stai usando, dal momento che non è così ovvio nel tuo codice. È possibile salvare alcuni byte definendo una funzione, in modo da poter prendere l'input come argumen e utilizzare il valore restituito come output.
Denker,

@DenkerAffe Grazie mille! Ho salvato 2 byte, ma penso che una funzione aumenterà il numero. Ho aggiornato la risposta con un esempio di utilizzo.
Tarod,

0

05AB1E , 45 byte

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

Potrebbe non essere più il 2016, ma comunque ..;) Presuppone che l'anno sia ancora il 2016 per essere un anno bisestile con 29febbraio.

Provalo online o verifica tutti i casi di test .

Spiegazione:

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)

Vedere questo 05AB1E punta del mio (sezioni Come comprimere grandi numeri interi? E come liste di interi comprimere? ) Per capire perché •9JRt€ª´Q®Ië•è 10549819042671399072072399; •9JRt€ª´Q®Ië•368вè [85,86,88,116,123,277,360,361,362,367]; ed •Σ₁t•è 5354545.

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.