Prochain jour férié

18

Les Australiens adorent les jours fériés et boire. Hier, le 26 janvier, c'était le jour de l'Australie, qui est un jour férié. J'étais content de ne pas être au travail hier, et impatient de savoir la prochaine fois que j'aurai un jour férié! Malheureusement, j'avais un peu trop à boire et je ne suis pas en mesure de m'en sortir moi-même.

Écrivez un programme qui prendra une date en notation date / heure australienne (dd / mm) en entrée et affichera le nombre de jours jusqu'au prochain jour férié. Parce que je suis un résident du Queensland (QLD), je ne suis intéressé que par les jours fériés qui affectent les Queenslanders :

25/03 | Vendredi Saint
26/03 | Samedi de Pâques
28/03 | Lundi de Pâques
25/04 | Jour de l'Anzac
02/05 | Fête du travail
03/10 | Anniversaire de la Reine
25/12 | Jour de Noël
26/12 | Boxing Day
27/12 | Vacances de Noël

Notez ce qui suit sur le site:

Vacances de Noël

Un jour férié supplémentaire à ajouter lorsque le jour de l'An, le jour de Noël ou le lendemain de Noël tombe un week-end.

Parce que le jour de Noël est le dimanche, il y a un jour férié supplémentaire . Le jour de Noël est toujours un jour férié.

Parce que je suis une personne du matin, vous devez inclure la date actuelle comme un jour (car c'est le moment le plus probable pour lequel je vérifierai votre programme pour le prochain jour férié). Autrement dit, si la date d'un jour férié est entrée, votre sortie devrait être 0; si la veille d'un jour férié est entré, votre sortie sera 1.

Je ne m'intéresse qu'aux dates d' ici (le 27/01) jusqu'à la fin de l'année. La date finale dont vous devrez tenir compte est le 31/12 où votre sortie sera 1(pour le jour de l'an).

Les failles standard sont interdites.

Contribution

  • L'entrée sera toujours de 5 caractères: 4 lettres, séparées par un trait d'union -ou une barre oblique/
  • L'entrée ne sera qu'une date entre le 27/01 et le 31/12

Production

  • Le nombre de jours avant le prochain jour férié dans le Queensland en Australie, y compris la date d'entrée: doit être un nombre compris entre 0et 153(l'écart le plus long)
  • Aucune nouvelle ligne ou erreur

Exemples

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

Espérons que ce soit clair et que rien ne manque; cependant, c'est ma deuxième question, donc j'apprécierai tout commentaire et ferai de mon mieux pour résoudre les problèmes dès que possible.

Tas
la source
@insertusernamehere Merci pour cette excellente suggestion! J'ai ajouté les dates à la question
Tas
@Tas-tu sûr que ces dates sont correctes? Ceux des exemples ne correspondent pas au devis et les deux ne correspondent pas au site Web.
Adam Martin
@AdamMartin Merci d'avoir signalé cela. J'avais mal inscrit les dates de décembre. Celles de l'exemple ne sont que des dates non spécifiques aux jours fériés. Ce ne sont que des exemples de dates qui pourraient être entrées et de ce que la sortie devrait être. Ceux cités devraient (et, espérons-le, le faire) correspondre à ceux du site Web.
Tas
Vous célébrez l'anniversaire de la Reine en octobre dans le Queensland? C'est tellement bizarre, mais semble correct à partir du lien.
Level River St
Wow, vous n'avez pas de vacances de juin à septembre? C'est rude.
Joe Z.27

Réponses:

2

Pyth , 98 84 62 67 octets

Mise à jour: économisé 14 octets en raccourcissant la liste du nombre de jours pour les 12 mois pour le calcul du nombre de jours. Je n'ai pas trouvé un bon moyen de compresser l'autre liste, tout en essayant!

Update2: enregistré 22 octets supplémentaires en codant à la fin la liste des numéros de jour sous forme de chaîne base256.

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

Essayez-le en ligne!

Même algorithme que dans ma réponse Python. Et pas de fonction intégrée pour avoir le jour de l'année, j'ai donc dû le faire moi-même. La création de ces 2 listes pour le calcul du jour de l'année et pour les jours de vacances est assez coûteuse ... je vais y jeter un coup d'œil et essayer de les générer en moins d'octets.

Denker
la source
Il ne semble pas aimer l'entrée séparée par un trait d'union, mais sinon c'est super
Tas
@Tas Merci pour l'astuce, a complètement dépassé cette partie ... Correction au prix de 5 octets de plus. Vous devriez peut-être ajouter des tirets aux cas de test, car vous voulez qu'ils couvrent toutes les variations d'entrée possibles.
Denker
5

Visual Basic pour Applications, 155 ou 118 octets

Version 1 - indépendante des paramètres régionaux, 155 octets

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 - dépendante des paramètres régionaux, 118 octets

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

Le nombre d'octets correspond au fichier .BAS final, y compris les caractères de saut de ligne. Édité en dehors de l'éditeur VBA standard (car il impose des espaces supplémentaires et des formes verbeuses de certains mots clés) - mais importe et s'exécute sans problème sur n'importe quelle application Office (pour tester le type, par exemple ? h("10/08")dans une fenêtre immédiate ou dans Excel, utiliser directement dans une formule de cellule).

(MODIFIÉ) Au départ, j'ai choisi d'utiliser DateSerialpour rendre la fonction locale sûre (version 1). Comme je vis au Brésil et donc mon système est configuré pour utiliser le format "jj / mm / aa" pour les dates (comme en Australie), je pourrais écrire une version encore plus petite en utilisant à la CDateplace (version 2). CDateutilise les informations sur les paramètres régionaux du système pour convertir le texte en date. J'ai également supposé dans cette version que le code ne serait exécuté qu'en 2016 (si l'année est omise (-6 octets) CDatesuppose l'année en cours selon l'horloge système).

Le nombre 42454 sur la troisième ligne est la somme de 42450 qui est la représentation numérique du 01/01/2016 sur VBA, et 84 qui est le jour de l'année pour le premier jour férié. Le tableau contient le jour de l'année pour chaque jour férié (y compris le 01/01/2017) compensé par -84 car cela enlève quelques chiffres. L'utilisation de 16 au lieu de 2016 sur DateSerialsupprime deux octets supplémentaires.

Créer un tableau identique neuf fois à l'intérieur de l'itération est un "mauvais" code, mais fonctionne et enregistre 3 octets supplémentaires (un pour le nom du tableau et un pour le signe égal à l'extérieur de la boucle, et un de plus pour référencer le tableau à l'intérieur de la boucle).

Les espaces "manquants" entre 0 et le mot-clé suivant sur les deuxième et quatrième lignes ne sont pas nécessaires car ils sont réintroduits automatiquement par VBE lors de l'importation du module. Utilisé obsolète mais bon marché If <...> Goto <linenumber>pour rompre la boucle (les deux If <...> Then Exit Foret If <...> Then Exit Functionutiliser plus de caractères).

A également profité du fait que le nom de la fonction dans VBA se comporte comme une variable locale, et sa valeur est automatiquement retournée par la fonction en fin d'exécution.

dnep
la source
Bienvenue chez PPCG! Ici, nous définissons un langage de programmation par l'interpréteur, il est donc parfaitement acceptable d'exiger une certaine locale.
lirtosiast
Merci! Modifié pour ajouter une version plus petite dépendante des paramètres régionaux.
dnep
4

JavaScript (ES6), 131 128 octets

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

Explication

Utilise le constructeur intégré JavaScript Datepour convertir la chaîne d'entrée en un nombre de millisecondes depuis l'époque, puis compare cela avec le nombre de millisecondes pour chaque jour férié.

Pour ce faire, il stocke les jours fériés dans un tableau en tant que nombre de jours depuis une date de référence. J'ai choisi 2016-01-29la date de référence car le nombre de millisecondes depuis l'époque peut être condensé le plus court pour cette date. N'importe quel nombre de millisecondes entre ce jour et le suivant fonctionne car le résultat est arrondi vers le bas, et garder le nombre au milieu évite les effets de l'heure d'été (bien que le fuseau horaire de l'OP n'ait pas d'heure d'été). Le nombre de cette journée est 1453986000000et arrondi à 1454000000000(en ajoutant quelques heures) signifie qu'il peut être écrit comme 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

Tester

Cette solution dépend du fuseau horaire de l'utilisateur. Cela fonctionne dans le fuseau horaire de l'OP (et mon) (GMT +1000). Si vous souhaitez le tester dans un autre fuseau horaire, l'ajout numberOfHoursDifferentFromGMT1000 * 60 * 60 * 1000au numéro de date de référence devrait fonctionner. (par exemple, GMT +0430 serait -5.5 * 60 * 60 * 1000 + 1454e9+n*864e5)

user81655
la source
Cela donne toujours 0 lorsque la date est séparée par un trait d'union. J'ai déjà demandé à l'OP d'ajuster ses tests, car ils sont tous avec une barre oblique comme séparateur.
Denker
@DenkerAffe Oh, je pensais qu'il voulait dire que nous étions libres de choisir un séparateur. Soit dit en passant, le rendre ambivalent séparateur m'a fait économiser 3 octets, alors merci!
user81655
1
On dirait que la règle separated with a hyphen - or slash /est un peu ambigüe. Pour moi, cela signifie que nous devons faire face aux deux, mais je peux certainement voir votre côté. Je suppose que le PO devrait clarifier cela.
Denker
3

T-SQL, 210 , 206 , 194 octets

(Premier post ici, j'espère que ça va, mais soyez gentil :)

L'entrée entre @i, s'adresse aux deux /et -comme séparateur. Je suis en Australie, donc mon format de date est le même 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;

Mettre varchar à jour pour charenregistrer 3 octets et supprimer un espace :)

Mettre à jour 2 déclarer @cet attribuer sans sélection

Liesel
la source
2

T-SQL, 296 octets

Créé comme une fonction de valeur de table

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

Utilisé de la manière suivante

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)

Une brève explication

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
la source
2

JavaScript (ES6), 134 octets

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 m'a toujours battu de 3 octets, mais je ne trouve nulle part ailleurs pour presser quoi que ce soit d'ici. Fonctionne en calculant le nombre de jours écoulés au lieu d'utiliser Date, puis en le comparant à un tableau de compensations de vacances.

Mwr247
la source
2

Python 2, 204 185 165 165 166 octets

Mise à jour: golfé par ~ 20 octets en calculant le jour de l'année par moi-même. Plus besoin d'importations longues :)

Mise à jour 2: encore 20 octets de moins en réalisant que je peux traiter les nouvelles années comme le jour 367 et en faisant d'autres petits ajustements.

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

Essayez-le en ligne!

Non 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

Fonctionne en stockant le nombre de jours fériés de l'année dans une liste, en filtrant ceux qui sont avant la date donnée, en prenant le premier élément de cette liste filtrée et en soustrayant le jour de l'année, qui obtenu calculé à partir de l'entrée.

Denker
la source
1

PHP, 116 octets

Approche assez simple. Il stocke les jours de l'année pour les vacances et les affiche tant qu'ils sont dans le passé. Enfin, le jour de l'année demandé est soustrait.

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;

Passé tous les cas de test. S'exécute à partir de la ligne de commande et accepte l'entrée à l'aide d'un trait d'union, comme:

$ php holidays.php "12-05"
insertusernamehere
la source
1

1.9.3 rubis, 155 153 octets

Après les vacances de Noël, nous avons besoin de notre 366 super spécial! Cas similaire à @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

Usage:

$ ruby i_want_to_break_free.rb "03/05"
Tarod
la source
Je ne sais pas grand-chose sur Ruby, mais je pense que vous pouvez économiser 3 octets en supprimant les espaces blancs aux lignes 1 et 3. Vous devez également spécifier la méthode d'entrée que vous utilisez, car ce n'est pas si évident dans votre code. Vous pouvez enregistrer certains octets en définissant une fonction, vous pouvez donc prendre l'entrée comme argument et utiliser la valeur de retour comme sortie.
Denker
@DenkerAffe Merci beaucoup! J'ai économisé 2 octets, mais je pense qu'une fonction augmentera le nombre. J'ai mis à jour la réponse avec un exemple d'utilisation.
Tarod
0

05AB1E , 45 octets

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

Ce n'est peut-être plus 2016, mais peu importe ..;) Suppose toujours que l'année est 2016 pour être une année bissextile avec 29pour février.

Essayez-le en ligne ou vérifiez tous les cas de test .

Explication:

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)

Voir cette astuce de mes 05AB1E (sections Comment compresser les grands entiers? Et comment les listes entières Compresser? ) Pour comprendre pourquoi •9JRt€ª´Q®Ië•est 10549819042671399072072399; •9JRt€ª´Q®Ië•368вest [85,86,88,116,123,277,360,361,362,367]; et •Σ₁t•est 5354545.

Kevin Cruijssen
la source