Próximo día festivo

18

Los australianos adoran los días festivos y la bebida. Ayer, 26 de enero, fue el día de Australia, que es un día festivo. ¡Me alegré de no estar en el trabajo ayer, y ansioso por saber la próxima vez que tenga un día festivo! Desafortunadamente, bebí demasiado y no puedo resolverlo por mí mismo.

Escriba un programa que tome una fecha en notación de fecha / hora australiana (dd / mm) como entrada, y envíe la cantidad de días hasta el próximo día festivo. Como soy residente de Queensland (QLD), solo me interesan los días festivos que afecten a Queenslanders :

25/03 | Viernes Santo
26/03 | Sábado de Pascua
28/03 | Lunes de Pascua
25/04 | Anzac Day
02/05 | Día del Trabajo
03/10 | Cumpleaños de la Reina
25/12 | Día de Navidad
26/12 | Boxing Day
27/12 | Vacaciones de navidad

Tenga en cuenta lo siguiente del sitio:

Vacaciones de navidad

Se agregará un feriado público adicional cuando el día de Año Nuevo, el día de Navidad o el día del boxeo caigan en un fin de semana.

Debido a que el día de Navidad es el domingo, hay un feriado público adicional . El día de Navidad sigue siendo un día festivo.

Como soy una persona madrugadora, debe incluir la fecha actual como un día (ya que esa es la hora más probable que verifique su programa para el próximo día festivo). Es decir, si se ingresa la fecha de un día festivo, su salida debería ser 0; Si el día anterior a un feriado público se ingresa, su salida será 1.

Solo me interesan las fechas entre ahora (el 27/01) hasta fin de año. La fecha final que deberá tener en cuenta es el 31/12, donde será su salida 1(para el día de Año Nuevo).

Las lagunas estándar están prohibidas.

Entrada

  • La entrada siempre tendrá 5 caracteres: 4 letras, separadas por un guión -o una barra inclinada/
  • La entrada solo será una fecha entre el 27/01 y el 31/12

Salida

  • El número de días hasta el próximo día festivo en Queensland, Australia, incluida la fecha de entrada: debe ser un número entre 0y 153(el intervalo más largo)
  • No hay nuevas líneas ni errores.

Ejemplos

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

Esperemos que esto esté claro y no se pierda nada; Sin embargo, esta es mi segunda pregunta, así que agradeceré cualquier comentario y haré todo lo posible para solucionar los problemas lo antes posible.

Tas
fuente
@ inserciónusernamehere Gracias por la gran sugerencia! He agregado las fechas a la pregunta
Tas
@ ¿Estás seguro de que esas fechas son correctas? Los de los ejemplos no coinciden con la cita y ambos no coinciden con el sitio web.
Adam Martin
@ AdamMartin Gracias por señalar eso. Había puesto incorrectamente las fechas de diciembre. Las del ejemplo son solo fechas, no específicas de días festivos. Son solo ejemplos de fechas que podrían ingresarse y cuál debería ser la salida. Los citados deben (y con suerte coinciden) con los del sitio web.
Tas
¿Celebras el cumpleaños de la reina en octubre en Queensland? Eso es muy extraño, pero parece correcto desde el enlace.
Level River St el
Vaya, ¿no tienen vacaciones de junio a septiembre? Eso es rudo.
Joe Z.

Respuestas:

2

Pyth , 98 84 62 67 Bytes

Actualización: se guardaron 14 bytes acortando la lista del recuento de días para los 12 meses para el cálculo del número de días. No he encontrado una buena manera de comprimir la otra lista, ¡aún lo intento!

Actualización2: guardó otros 22 bytes al codificar la lista de los números de día como una cadena base256.

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

Pruébalo en línea!

Mismo algoritmo que en mi respuesta de Python. Y no tenía que hacer el día del año, así que tuve que hacerlo yo mismo. Crear esas 2 listas para el cálculo del día del año y para los días de vacaciones es bastante costoso ... voy a echarle un vistazo nuevamente e intentar generarlas en menos bytes.

Denker
fuente
No parece que le guste la entrada separada con un guión, pero por lo demás es genial
Tas
@Tas Gracias por la pista, leí completamente esa parte ... Lo arreglé al costo de 5 bytes más. Tal vez debería agregar algunos guiones a los casos de prueba, ya que desea que cubran todas las variaciones de entrada posibles.
Denker
5

Visual Basic para aplicaciones, 155 o 118 bytes

Versión 1: independiente del entorno local, 155 bytes

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

Versión 2: dependiente del entorno local, 118 bytes

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

El recuento de bytes es para el archivo final .BAS, incluidos los caracteres de salto de línea. Editado fuera del editor estándar de VBA (ya que impone espacios adicionales y formas detalladas de algunas palabras clave), pero importa y funciona sin problemas en cualquier aplicación de Office (para probar el tipo, por ejemplo? h("10/08") en una ventana inmediata, o en Excel, usar directamente en una fórmula de celda).

(EDITADO) Inicialmente elegí usar DateSerialpara hacer que la función fuera segura localmente (versión 1). Como vivo en Brasil y, por lo tanto, mi sistema está configurado para usar el formato "dd / mm / aa" para las fechas (al igual que Australia), podría escribir una versión aún más pequeña usando en su CDatelugar (versión 2).CDateutiliza la información del sistema local para convertir el texto en fecha. También asumí en esta versión que el código solo se ejecutaría durante 2016 (si se omite el año (-6 bytes)CDate supone el año actual según el reloj del sistema).

El número 42454 en la tercera línea es la suma de 42450 que es la representación numérica del 01/01/2016 en VBA, y 84 que es el día del año para las primeras vacaciones. La matriz contiene el día del año para cada día festivo (incluido 01/01/2017) compensado por -84, ya que esto elimina algunos dígitos. Usando 16 en lugar de 2016 enDateSerial quita dos bytes más.

Crear una matriz idéntica nueve veces dentro de la iteración es un código "incorrecto", pero funciona y guarda 3 bytes más (uno para el nombre de la matriz y otro para el signo igual fuera del bucle, y uno más para hacer referencia a la matriz dentro del bucle).

Los espacios "faltantes" entre 0 y la siguiente palabra clave en la segunda y cuarta líneas no son necesarios, ya que VBE los reintroduce automáticamente cuando se importa el módulo. Usado desactualizado pero barato If <...> Goto <linenumber>para romper el bucle (ambos If <...> Then Exit Fory If <...> Then Exit Functionusar más caracteres).

También aprovechó el hecho de que el nombre de la función en VBA se comporta como una variable local, y su valor es devuelto automáticamente por la función al final de la ejecución.

dnep
fuente
Bienvenido a PPCG! Aquí definimos un lenguaje de programación por el intérprete, por lo que es perfectamente aceptable requerir un determinado entorno local.
lirtosiast
¡Gracias! Editado para agregar una versión más pequeña dependiente de la configuración regional.
dnep
4

JavaScript (ES6), 131128 bytes

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

Explicación

Utiliza el JavaScript incorporado Date constructor para convertir la cadena de entrada en varios milisegundos desde la época, luego compara esto con el número de milisegundos para cada día festivo.

Lo hace almacenando los días festivos en una matriz como el número de días desde una fecha de referencia. Elegí 2016-01-29la fecha de referencia porque el número de milisegundos desde la época se puede condensar más corto para esta fecha. Cualquier número de milisegundos entre este día y el siguiente funciona porque el resultado se redondea hacia abajo y mantener el número en el medio evita los efectos del horario de verano (aunque la zona horaria del OP no tiene horario de verano). El número de este día es 1453986000000y redondeándolo a 1454000000000(sumando un par de horas) significa que se puede escribir como 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

Prueba

Esta solución depende de la zona horaria del usuario. Esto funciona en la zona horaria del OP (y mi) (GMT +1000). Si desea probarlo en una zona horaria diferente, añadiendo numberOfHoursDifferentFromGMT1000 * 60 * 60 * 1000a la referencia de número de fecha debe trabajar. (por ejemplo, GMT +0430 sería -5.5 * 60 * 60 * 1000 + 1454e9+n*864e5)

usuario81655
fuente
Esto siempre da 0 cuando la fecha está separada por un guión. Ya le pedí al OP que ajustara sus casos de prueba, ya que todos tienen una barra como separador.
Denker
@DenkerAffe Oh, pensé que quería decir que éramos libres de elegir un separador. Por cierto, hacerlo separador-ambivalente me ahorró 3 bytes, ¡así que gracias!
user81655
1
Parece que la regla separated with a hyphen - or slash /es un poco ambigua. Para mí significa que tenemos que lidiar con ambos, pero definitivamente puedo ver tu lado. Supongo que el OP debería aclarar esto.
Denker
3

T-SQL, 210 , 206 , 194 bytes

(Primera publicación aquí, espero que esto esté bien, pero por favor sé amable :)

La entrada entra @i, abastece a ambos /y -como separador. Estoy en Australia, así que mi formato de fecha es el mismo que @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;

Actualización varchar para charguardar 3 bytes más eliminado un espacio :)

Actualización 2 declarar @cy asignar sin seleccionar

Liesel
fuente
2

T-SQL, 296 bytes

Creado como una función con valores de tabla

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

Usado de la siguiente manera

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 explicacion

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
fuente
2

JavaScript (ES6), 134 bytes

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 todavía me tiene superado por 3 bytes, pero no puedo encontrar ningún otro lugar para sacar algo de aquí. Funciona calculando el número de días transcurridos en lugar de usar Fecha, y luego comparándolo con una serie de compensaciones de vacaciones.

Mwr247
fuente
2

Python 2, 204 185 165 166 Bytes

Actualización: Golfed ~ 20 Bytes calculando el día del año por mí mismo. Ya no hay necesidad de las largas importaciones :)

Actualización 2: Otros 20 bytes menos al darme cuenta de que puedo tratar los años nuevos como el día 367 y hacer algunos otros pequeños ajustes.

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

Pruébalo en línea!

Sin golf:

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

Funciona almacenando el número de días festivos del año en una lista, filtrando los que están antes de la fecha dada, tomando el primer elemento en esa lista filtrada y restando el día del año, que se calculó a partir de la entrada.

Denker
fuente
1

PHP, 116 bytes

Enfoque bastante directo. Almacena los días del año para las vacaciones y los muestra mientras estén en el pasado. Finalmente se resta el día solicitado del año.

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;

Pasado todos los casos de prueba. Se ejecuta desde la línea de comandos y acepta la entrada usando un guión, como:

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

Ruby 1.9.3, 155 153 bytes

¡Después del feriado del día de Navidad, necesitamos nuestro día súper especial 366! Caso similar al @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"
Tarod
fuente
No sé mucho sobre Ruby, pero creo que puede guardar 3 bytes eliminando espacios en blanco en las líneas 1 y 3. También debe especificar qué método de entrada está utilizando, ya que no es tan obvio en su código. Puede guardar algunos bytes definiendo una función, de modo que pueda tomar la entrada como argumen y usar el valor de retorno como salida.
Denker
@DenkerAffe ¡Muchas gracias! He guardado 2 bytes, pero creo que una función aumentará el número. He actualizado la respuesta con un ejemplo de uso.
Tarod
0

05AB1E , 45 bytes

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

Puede que ya no sea 2016, pero lo que sea ...;) Todavía se supone que el año es 2016 por ser un año bisiesto 29para febrero.

Pruébelo en línea o verifique todos los casos de prueba .

Explicación:

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)

Vea esta sugerencia mía 05AB1E (secciones ¿Cómo comprimir enteros grandes? Y ¿Cómo comprimir listas enteras? ) Para comprender por qué •9JRt€ª´Q®Ië•es 10549819042671399072072399; •9JRt€ª´Q®Ië•368вes [85,86,88,116,123,277,360,361,362,367]; y •Σ₁t•es 5354545.

Kevin Cruijssen
fuente