Un cartello che mostra gli orari di apertura raggruppati di un caffè


20

Probabilmente hai visto questi segni sulle porte di vari negozi:

ORARI DI APERTURA


lun -ven 0900-1800 sab-dom 1100-1530

Il compito qui è generare un segno del genere, raggruppando giorni consecutivi con gli stessi orari di apertura, da un elenco di orari di apertura per l'intera settimana. Si noti che la settimana "si svolge" per ciò che è considerato consecutivo.

Ingresso:

  • 7 elementi, che rappresentano gli orari di apertura di ogni giorno in una settimana, a partire dal lunedì.
  • Ogni elemento è una stringa, nella forma XXXX-XXXX
  • Esempio di input:

    0900-1800 0900-1800 0930-1730 0930-1730 0900-1500 1100-1500 1100-1500
    
  • Va bene inviare l'input come un array (ad esempio come input per una funzione se non si legge da stdin)

Produzione:

  • Un elenco di orari di apertura, in cui i giorni consecutivi con gli stessi orari di apertura vengono visualizzati come intervallo. Nota che domenica (l'ultimo giorno) e lunedì (il primo giorno) sono giorni consecutivi.
  • Un giorno in cui il giorno non ha orari di apertura simili ai giorni precedenti o successivi viene stampato da solo
  • I giorni sono indicati con tre lettere minuscole: lun mar mer gio ven sab dom
  • Ricorda che il primo elemento nell'input corrisponde a mon, accanto a tue ecc.
  • Gli orari di apertura sono indicati come nell'input
  • Due esempi

    mon-fri 0900-1800, sat-sun 1100-1500
    mon-wed 1030-1530, thu 100-1800, fri-sun 1200-1630
    
  • L'output deve essere ordinato, quindi gli intervalli vengono visualizzati nell'ordine in cui compaiono i giorni della settimana. Il lunedì è preferito essere il primo, ma può succedere che non sia il primo di un gruppo perché la settimana finisce. Quindi in questo caso la tua è la prima gamma.

    tue-fri 0900-1800, sat-mon 1100-1500
    
  • Non raggruppare se non consecutivi, qui mercoledì e venerdì hanno gli stessi orari di apertura ma sono separati da un giovedì con orari di apertura diversi, quindi sono elencati da soli.

    mon-tue 1000-1200, wed 0900-1500, thu 1000-1800, fri 0900-1500, sat-sun 1000-1500
    
  • L'output può essere separato da virgola come nell'esempio qui oppure separato da una nuova riga come nell'esempio in alto.

Casi test

Viene immessa la prima riga, è prevista l'uscita della seconda riga

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

Regole

Questo è code-golf, quindi vince la risposta più breve in byte.


7
Benvenuti in Programming Puzzle and Code Golf. Questa è una bella sfida; molto bene! In futuro, consiglierei di utilizzare la sandbox prima di pubblicare una sfida. (Sai, per ogni evenienza ...)
wizzwizz4,

1
Avere domenica e lunedì come consecutivi mi sembra strano ...
Frédéric,

1
Sento che dovrebbe esserci un caso di prova per "mon-sun" nel caso in cui qualsiasi presentazione non gestisca correttamente quel particolare caso di base.
Patrick Roberts,

Risposte:


7

JavaScript (ES6), 182 173 170 163 157 byte

6 byte salvati con l'aiuto di edc65

Prende l'input come una matrice di stringhe e stampa direttamente il risultato sulla 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)}

Formattato e commentato

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)

Casi 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"]);


D='montuewedthufrisatsun'.match(/.../g)l'uso Dcome array anziché come funzione dovrebbe salvare un po 'di byte
edc65

@ edc65 - Sfortunatamente D()può essere chiamato con -1(quando cerchiamo 'il giorno prima di lunedì'), che funziona con substr()ma non funzionerebbe con un array.
Arnauld,

@ edc65 - EDIT: combinando il tuo metodo con un'altra correzione, questa è sicuramente una vittoria. Grazie!
Arnauld,

3

Lotto, 334 byte

@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

Accetta input come parametri della riga di comando, genera ciascun gruppo su una riga separata. Funziona confrontando le ore di ogni giorno con il giorno precedente, monitorando fcome primo giorno nel gruppo, hcome le ore per quel gruppo, lcome l'ultimo giorno nel gruppo e wper quando l'ultimo gruppo torna all'inizio della settimana. Quando viene rilevata una mancata corrispondenza, il gruppo precedente viene stampato a meno che non sia attiva la disposizione della settimana. Alla fine, quando tutti i giorni vengono elaborati, l'ultimo gruppo viene adattato per il wrapping di ogni settimana e se tutte le ore si sono rivelate uguali prima dell'emissione. 0viene utilizzato come segnaposto perché le stringhe vuote costano più byte da confrontare in batch.


2

Gelatina , 87 84 80 75 byte

  • 4byte con il gentile aiuto di @Dennis (risolto un trucco che ho usato con il 'veloce "piatto")

Abbastanza sicuro che ci sia un modo migliore, ma per ora:

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

TryiItOnline

Come?

            “ḅạṄ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)

1

JavaScript (ES6), 171 169 byte

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)

Prende l'input come un array e l'output alla console su linee separate. Questa è quasi esattamente una porta della mia risposta Batch; fora per impostazione predefinita è ovviamente una stringa vuota, mentre io posso anche impostare un valore predefinito le wsu 'sun'(usando un valore di sentinella ho salvato 3 byte in Batch perché sono stato in grado di unire l'inizializzazione in set/a).


1

BaCon , 514 496 455 byte

Il seguente programma BASIC è mostrato con il suo rientro. Ma senza il rientro è costituito da 455 byte.

L'idea è di utilizzare le pianificazioni temporali come indici in una matrice associativa. Quindi, ogni giorno rappresenta un bit: lunedì = bit 0, martedì = bit 1, mercoledì = bit 2 e così via. I valori effettivi per i membri dell'array associativo vengono calcolati dai rispettivi bit dei giorni utilizzando un OR binario.

Successivamente, si tratta di verificare quanti bit consecutivi sono presenti nei membri dell'array associativo, a partire dal bit 0.

Nel caso in cui siano impostati il ​​bit 0 e anche il bit 6, è presente una settimana. In tal caso, iniziare a cercare l'inizio della sequenza successiva di bit, memorizzando questa posizione iniziale. Stampa il resto delle sequenze e non appena viene raggiunto il bit 6, l'intervallo di giorni deve terminare con la posizione memorizzata in precedenza.

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

Utilizzo delle seguenti chiamate per richiamare il 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")

Uscita :

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
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.