Un panneau indiquant les heures d'ouverture groupées d'un café

20

Vous avez probablement vu ces panneaux sur les portes de divers magasins:

HORAIRES D'OUVERTURES

lun
-ven 0900-1800 sam-dim 1100-1530

La tâche ici est de générer un signe comme celui-ci, regroupant des jours consécutifs avec les mêmes heures d'ouverture, à partir d'une liste d'heures d'ouverture pour toute la semaine. Notez que la semaine «se déroule» pour ce qui est considéré comme consécutif.

Contribution:

  • 7 éléments, représentant les heures d'ouverture pour chaque jour d'une semaine, à partir du lundi.
  • Chaque élément est une chaîne, sous la forme XXXX-XXXX
  • Exemple d'entrée:

    0900-1800 0900-1800 0930-1730 0930-1730 0900-1500 1100-1500 1100-1500
    
  • Il est correct d'envoyer l'entrée sous forme de tableau (par exemple en tant qu'entrée vers une fonction si vous ne lisez pas depuis stdin)

Production:

  • Une liste des heures d'ouverture, où les jours consécutifs avec les mêmes heures d'ouverture sont affichés sous forme de plage. Notez que le dimanche (le dernier jour) et le lundi (le premier jour) sont également des jours consécutifs.
  • Un jour où le jour n'a pas d'heures d'ouverture similaires aux jours avant ou après est imprimé seul
  • Les jours sont spécifiés en trois lettres minuscules: lun mar mer jeu ven sam dim
  • N'oubliez pas que le premier élément de l'entrée correspond à mon, à côté de mar, etc.
  • Les heures d'ouverture sont indiquées comme dans l'entrée
  • Deux exemples

    mon-fri 0900-1800, sat-sun 1100-1500
    mon-wed 1030-1530, thu 100-1800, fri-sun 1200-1630
    
  • La sortie doit être triée, les plages apparaissent donc dans l'ordre des jours de la semaine. Le lundi est préférable d'être le premier, mais il se peut que ce ne soit pas le premier dans un groupe car la semaine se termine. Donc dans ce cas, le tue est la première plage.

    tue-fri 0900-1800, sat-mon 1100-1500
    
  • Ne groupez pas sauf si consécutif, ici mercredi et vendredi ont les mêmes heures d'ouverture mais sont séparés par un jeudi avec des heures d'ouverture différentes donc ils sont listés par eux-mêmes.

    mon-tue 1000-1200, wed 0900-1500, thu 1000-1800, fri 0900-1500, sat-sun 1000-1500
    
  • La sortie peut être soit séparée par des virgules comme les exemples ici, soit séparée par une nouvelle ligne comme dans l'exemple ci-dessus.

Cas de test

La première ligne est entrée, la deuxième ligne est attendue

0900-1800 0900-1800 0900-1800 0900-1800 0900-1800 1100-1500 1100-1500
mon-fri 0900-1800, sat-sun 1100-1500

0900-1800 0900-1800 0900-1800 0930-1700 0900-1800 1100-1500 1100-1500
mon-wed 0900-1800, thu 0930-1700, fri 0900-1800, sat-sun 1100-1500

1100-1500 0900-1800 0900-1800 0900-1800 0900-1800 1100-1500 1100-1500
tue-fri 0900-1800, sat-mon 1100-1500

1100-1500 1100-1500 0900-1800 0900-1800 0900-1800 0900-1800 1100-1500
wed-sat 0900-1800, sun-tue 1100-1500

1200-1500 1100-1500 0900-1800 0900-1800 0900-1800 0900-1800 1100-1500
mon 1200-1500, tue 1100-1500, wed-sat 0900-1800, sun 1100-1500

Règles

Il s'agit de code-golf, donc la réponse la plus courte en octets l'emporte.

Matsemann
la source
7
Bienvenue dans Programming Puzzles et Code Golf. C'est un bon défi; bien joué! À l'avenir, je recommanderais d'utiliser le bac à sable avant de publier un défi. (Vous savez, juste au cas où ...)
wizzwizz4
1
Le dimanche et le lundi consécutifs me semblent bizarres ...
Frédéric
1
Je pense qu'il devrait y avoir un test pour "mon-sun" juste au cas où une soumission ne traiterait pas correctement ce cas de base particulier.
Patrick Roberts,

Réponses:

7

JavaScript (ES6), 182 173 170 163 157 157 octets

Enregistré 6 octets avec l'aide d'edc65

Prend l'entrée comme un tableau de chaînes et imprime directement le résultat sur la console:

h=>{for(D="montuewedthufrisatsun".match(/.../g),d=c=i=j=0;j<8;y=d)h[i]==h[6]?i++:(v=h[d=(i+j++)%7])!=c&&(j>1&&console.log(D[x]+(x-y?'-'+D[y]:''),c),x=d,c=v)}

Formaté et commenté

h => {                               // input = list h of opening hours
  for(                               //
    D = "montuewedthufrisatsun"      // D = list of abbreviated names of days
        .match(/.../g),              //
    d =                              // d = current day of week
    c =                              // c = current opening hours
    i =                              // i = first day of week to process
    j = 0;                           // j = day counter
    j < 8;                           // stop when 7 days have been processed
    y = d                            // update y = last day of current day range
  )                                  //
  h[i] == h[6] ?                     // while the opening hours of day #i equal the opening
    i++                              // hours of sunday: increment i
  : (v = h[d = (i + j++) % 7]) != c  // else, if the new opening hours (v) of the current
    && (                             // day (d) doesn't match the current opening hours (c):
      j > 1 &&                       //   if this is not the first iteration:
        console.log(                 //     print:
          D[x] +                     //     - the first day of the current day range (x)
          (x - y ?                   //     - followed by either an empty string
            '-' + D[y]               //       or a '-' and the last day of the range
          : ''),                     //       (if they differ)
          c                          //     - the corresponding opening hours
        ),                           //   (endif)
      x = d,                         //   update x = first day of current day range
      c = v                          //   update c = current opening hours
    )                                // (endif)
}                                    // (end)

Cas de test

let f =

h=>{for(D="montuewedthufrisatsun".match(/.../g),d=c=i=j=0;j<8;y=d)h[i]==h[6]?i++:(v=h[d=(i+j++)%7])!=c&&(j>1&&console.log(D[x]+(x-y?'-'+D[y]:''),c),x=d,c=v)}

f(["0900-1800", "0900-1800", "0900-1800", "0900-1800", "0900-1800", "1100-1500", "1100-1500"]);
console.log('-');
f(["0900-1800", "0900-1800", "0900-1800", "0930-1700", "0900-1800", "1100-1500", "1100-1500"]);
console.log('-');
f(["1100-1500", "0900-1800", "0900-1800", "0900-1800", "0900-1800", "1100-1500", "1100-1500"]);
console.log('-');
f(["1100-1500", "1100-1500", "0900-1800", "0900-1800", "0900-1800", "0900-1800", "1100-1500"]);
console.log('-');
f(["1200-1500", "1100-1500", "0900-1800", "0900-1800", "0900-1800", "0900-1800", "1100-1500"]);

Arnauld
la source
D='montuewedthufrisatsun'.match(/.../g)utiliser Dcomme un tableau au lieu d'une fonction devrait économiser de l'octet
edc65
@ edc65 - Malheureusement, D()peut être appelé avec -1(lorsque nous recherchons «la veille de lundi»), qui fonctionne avec substr()mais ne fonctionnerait pas avec un tableau.
Arnauld
@ edc65 - EDIT: en combinant votre méthode avec un autre correctif, c'est définitivement une victoire. Merci!
Arnauld
3

Lot, 334 octets

@echo off
set/af=l=w=0
set h=%7
call:l mon %1
call:l tue %2
call:l wed %3
call:l thu %4
call:l fri %5
call:l sat %6
call:l sun %7
if not %w%==0 set l=%w%
if %f%==0 set f=mon
call:l 0 0
exit/b
:l
if not %h%==%2 (
if %f%==0 (set w=%l%)else if %f%==%l% (echo %f% %h%)else echo %f%-%l% %h%
set f=%1
set h=%2
)
set l=%1

Prend l'entrée en tant que paramètres de ligne de commande, génère chaque groupe sur une ligne distincte. Fonctionne en comparant les heures de chaque jour au jour précédent, en effectuant fle suivi comme premier jour du groupe, hcomme heures pour ce groupe, lcomme dernier jour du groupe et wquand le dernier groupe revient au début de la semaine. Lorsqu'une incohérence est détectée, le groupe précédent est imprimé, sauf si l'habillage hebdomadaire est en vigueur. Finalement, lorsque tous les jours sont traités, le dernier groupe est ajusté pour tout emballage de semaine et si toutes les heures se sont avérées être les mêmes avant d'être sorties. 0est utilisé comme espace réservé car les chaînes vides coûtent plus d'octets à comparer dans Batch.

Neil
la source
2

Gelée , 87 84 80 75 octets

  • 4 octets avec l'aimable aide de @Dennis (correction d'un hack que j'ai utilisé avec le 'rapide, "plat")

Je suis sûr qu'il y a une meilleure façon mais pour l'instant:

Ṫ2ị$€;@µ+\µżṙ1’$Ṗị“ḅạṄMḤ9\E¥LḃɓṅÐĿ;$»s3¤Q€j€”-
ṙ7Ḷ¤Œr'€Ėµ2ịLµÐṂḢ
ÇṪḢ€ż@ÇÑ$G

TryiItOnline

Comment?

            “ḅạṄMḤ9\E¥LḃɓṅÐĿ;$» - compressed string "montuewedthufrisatsun"
                  v  v
Ṫ2ị$€;@µ+\µżṙ1’$Ṗị -- s3¤Q€j€”- - Link 1, getDayStrings: [offset, groupedList]
Ṫ                               - Tail: get groupedList
 2ị$€                           - second index of each: get group sizes, e.g. mon-thu is 4
     ;@                         - concatenate (reversed arguments): prepend with offset
       µ                        - monadic chain separation
        +\                      - cumulative reduce with addition: start indexes
          µ                     - monadic chain separation
           ż                    - zip with
               $                - last two links as a monad
            ṙ1                  -     rotated left by one
              ’                 -     decrement:  end indexes
                Ṗ               - pop: remove last one, it's circular
                 ị              - index into
                        ¤       - last two links as a nilad
                    --          -     compressed string of weekdays (as shown at the top)
                      s3        -     split into 3s
                        Q€      - unique items for each: [tue,tue] -> [tue]
                          j€    - join each with
                            ”-  - literal string "-"

ṙ7Ḷ¤Œr'€Ėµ2ịLµÐṂḢ - Link 2: CalculateGroupingData: list of time strings
   ¤              - last two links as a nilad
ṙ                 -    rotate time strings list left by
 7Ḷ               -    range 7: [0,1,2,3,4,5,6]
       €          - for each
    Œr            -     run length encode
      '           -     flat - i.e. don't vectorise
        Ė         - enumerate [[1,[groupsFromMon]],[2,[groupsFromTue], ...]
         µ        - monadic chain separation
              ÐṂ  - filter for minimum of
             L    -     length of
          2ị      -     item at index 2: The number of groupings
                Ḣ - head: get the first occurring minimal (i.e Mon, or Tue, ...)

ÇṪḢ€ż@ÇÑ$G - Main link: list of time strings
Ç          - call last link (1) as a monad: get the offset and grouping
 Ṫ         - tail: get the grouping
  Ḣ€       - head each: get the time information
        $  - last two links as a monad
      Ç    -      call last link (1) as a monad: get the offset and grouping
       Ñ   -      call the next link as a monad: get the day strings
    ż@     - zip (with reversed arguments)
         G - arrange as a group (performs a tabulation to nicely align the result)
Jonathan Allan
la source
1

JavaScript (ES6), 171 169 octets

a=>a.map((e,d)=>(d='montuewedthufrisatsun'.substr(d*3,3),e!=h&&(f?o(f):w=l,f=d,h=e),l=d),f='',l=w='sun',h=a[6],o=f=>console.log((f==l?l:f+'-'+l)+' '+h))&&o(f||'mon',l=w)

Prend les entrées sous forme de tableau et les sorties vers la console sur des lignes distinctes. C'est presque exactement un port de ma réponse Batch; fmaintenant par défaut à une chaîne vide bien sûr, alors que je peux aussi par défaut let wà 'sun'(l'utilisation d'une valeur sentinelle m'a sauvé 3 octets dans Batch car j'ai pu fusionner l'initialisation dans le set/a).

Neil
la source
1

BaCon , 514 496 455 octets

Le programme BASIC ci-dessous est illustré avec son indentation. Mais sans l'indentation, il se compose de 455 octets.

L'idée est d'utiliser les plannings horaires comme index d'un tableau associatif. Ensuite, chaque jour représente un bit: lundi = bit 0, mardi = bit 1, mercredi = bit 2 et ainsi de suite. Les valeurs réelles des membres du tableau associatif sont calculées par les bits respectifs des jours à l'aide d'un OU binaire.

Après cela, il s'agit de vérifier le nombre de bits consécutifs présents dans les membres du tableau associatif, en commençant par le bit 0.

Dans le cas où le bit 0 et le bit 6 sont définis, il y a un retour à la semaine. Dans ce cas, commencez à rechercher le début de la prochaine séquence de bits, en mémorisant cette position de départ. Imprimez le reste des séquences et dès que le bit 6 est atteint, la plage de jours doit être terminée avec la position mémorisée plus tôt.

LOCAL n$[]={"mon","tue","wed","thu","fri","sat","sun"}
GLOBAL p ASSOC int
SUB s(VAR t$ SIZE a)
    FOR i = 0 TO a-1
        p(t$[i])=p(t$[i])|BIT(i)
    NEXT
    LOOKUP p TO c$ SIZE o
    b=e=0
    REPEAT
        FOR i=0 TO o-1
            IF p(c$[i])&BIT(b) THEN
                IF b=0 AND p(c$[i])&65=65 THEN
                    WHILE p(c$[i])&BIT(b)
                        INCR b
                    WEND
                    e=b
                    BREAK
                FI
                ?n$[b];
                r=b
                REPEAT
                    INCR b
                UNTIL NOT(p(c$[i])&BIT(b))
                IF e AND b>6 THEN
                    ?"-",n$[e-1];
                ELIF b-r>1 THEN
                    ?"-",n$[b-1];
                FI
                ?" ",c$[i]
            FI
        NEXT
    UNTIL b>6
    FREE p
ENDSUB

Utilisation des appels suivants pour appeler le SUB:

s("0900-1800", "0900-1800", "0900-1800", "0900-1800", "0900-1800", "1100-1500", "1100-1500")
PRINT "======"
s("0900-1800", "0900-1800", "0900-1800", "0930-1700", "0900-1800", "1100-1500", "1100-1500")
PRINT "======"
s("1100-1500", "0900-1800", "0900-1800", "0900-1800", "0900-1800", "1100-1500", "1100-1500")
PRINT "======"
s("1100-1500", "1100-1500", "0900-1800", "0900-1800", "0900-1800", "0900-1800", "1100-1500")
PRINT "======"
s("1200-1500", "1100-1500", "0900-1800", "0900-1800", "0900-1800", "0900-1800", "1100-1500")

Sortie :

mon-fri 0900-1800
sat-sun 1100-1500
======
mon-wed 0900-1800
thu 0930-1700
fri 0900-1800
sat-sun 1100-1500
======
tue-fri 0900-1800
sat-mon 1100-1500
======
wed-sat 0900-1800
sun-tue 1100-1500
======
mon 1200-1500
tue 1100-1500
wed-sat 0900-1800
sun 1100-1500
Peter
la source