Ein Zeichen, das gruppierte Öffnungszeiten eines Cafés zeigt

20

Sie haben wahrscheinlich diese Schilder an den Türen verschiedener Geschäfte gesehen:

ÖFFNUNGSZEITEN

Mo
-Fr 9.00-18.00 Uhr Sa -So 11.00-15.30 Uhr

Die Aufgabe hier ist es, ein solches Zeichen zu generieren, das aufeinanderfolgende Tage mit denselben Öffnungszeiten aus einer Liste von Öffnungszeiten für die ganze Woche gruppiert. Beachten Sie, dass die Woche für das, was als aufeinanderfolgend angesehen wird, "umläuft".

Eingang:

  • 7 Elemente, die die Öffnungszeiten für jeden Tag in einer Woche darstellen, beginnend mit Montag.
  • Jedes Element ist eine Zeichenfolge in der Form XXXX-XXXX
  • Beispiel Eingabe:

    0900-1800 0900-1800 0930-1730 0930-1730 0900-1500 1100-1500 1100-1500
    
  • Es ist in Ordnung, die Eingabe als Array zu senden (zum Beispiel als Eingabe für eine Funktion, wenn Sie nicht aus stdin lesen).

Ausgabe:

  • Eine Liste der Öffnungszeiten, wobei aufeinanderfolgende Tage mit denselben Öffnungszeiten als Bereich angezeigt werden. Beachten Sie, dass Sonntag (letzter Tag) und Montag (erster Tag) auch aufeinanderfolgende Tage sind.
  • Ein Tag, an dem der Tag keine ähnlichen Öffnungszeiten wie die Tage davor oder danach hat, wird von selbst gedruckt
  • Tage werden in drei Kleinbuchstaben angegeben: Mo Di Mi Do Fr Sa So
  • Denken Sie daran, dass das erste Element in der Eingabe mon, neben tue usw. entspricht.
  • Öffnungszeiten werden wie in der Eingabe angezeigt
  • Zwei Beispiele

    mon-fri 0900-1800, sat-sun 1100-1500
    mon-wed 1030-1530, thu 100-1800, fri-sun 1200-1630
    
  • Die Ausgabe sollte sortiert sein, damit Bereiche in der Reihenfolge angezeigt werden, in der die Tage in der Woche liegen. Montag ist der erste Tag, aber es kann vorkommen, dass er nicht der erste in einer Gruppe ist, weil die Woche vorüber ist. In diesem Fall ist Di der erste Bereich.

    tue-fri 0900-1800, sat-mon 1100-1500
    
  • Keine Gruppe, es sei denn, dies ist aufeinanderfolgend. Hier haben Mittwoch und Freitag die gleichen Öffnungszeiten, sind jedoch durch einen Donnerstag mit unterschiedlichen Öffnungszeiten getrennt, sodass sie für sich aufgelistet sind.

    mon-tue 1000-1200, wed 0900-1500, thu 1000-1800, fri 0900-1500, sat-sun 1000-1500
    
  • Die Ausgabe kann hier entweder durch Kommas oder durch eine neue Zeile wie im obigen Beispiel getrennt werden.

Testfälle

Erste Zeile wird eingegeben, zweite Zeile wird ausgegeben

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

Regeln

Das ist Code-Golf, also gewinnt die kürzeste Antwort in Bytes.

Matsemann
quelle
7
Willkommen bei Programming Puzzles und Code Golf. Das ist eine gute Herausforderung; gut gemacht! In Zukunft würde ich empfehlen, die Sandbox zu verwenden, bevor Sie eine Herausforderung veröffentlichen. (Weißt du, nur für den Fall ...)
wizzwizz4
1
Sonntag und Montag hintereinander zu haben, scheint mir seltsam ...
Frédéric
1
Ich bin der Meinung, dass es einen Testfall für "mon-sun" geben sollte, nur für den Fall, dass eine Einsendung diesen bestimmten Basisfall nicht richtig behandelt.
Patrick Roberts

Antworten:

7

JavaScript (ES6), 182 173 170 163 157 Byte

6 Bytes mit Hilfe von edc65 gespeichert

Nimmt Eingaben als ein Array von Zeichenfolgen und druckt das Ergebnis direkt auf die Konsole:

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)}

Formatiert und kommentiert

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)

Testfälle

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
quelle
D='montuewedthufrisatsun'.match(/.../g)Die Verwendung Deines Arrays anstelle einer Funktion sollte einige Bytes speichern
edc65
@ edc65 - Kann leider D()mit aufgerufen werden -1(wenn wir nach 'den Tag vor Montag' suchen), was substr()mit einem Array funktioniert, aber nicht funktionieren würde.
Arnauld
@ edc65 - EDIT: Wenn Sie Ihre Methode mit einem anderen Fix kombinieren, ist dies definitiv ein Gewinn. Vielen Dank!
Arnauld
3

Batch, 334 Bytes

@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

Übernimmt Eingaben als Befehlszeilenparameter und gibt jede Gruppe in einer separaten Zeile aus. Vergleicht die Stunden eines jeden Tages mit dem vorherigen Tag und protokolliert dabei fden ersten Tag in der Gruppe, hdie Stunden dieser Gruppe, lden letzten Tag in der Gruppe und den wZeitpunkt, zu dem die letzte Gruppe auf den Beginn der Woche zurückgeht. Wenn eine Nichtübereinstimmung festgestellt wird, wird die vorherige Gruppe gedruckt, es sei denn, der Wochenumbruch ist aktiviert. Wenn schließlich alle Tage verarbeitet sind, wird die letzte Gruppe für einen Wochenumbruch angepasst und ob sich herausgestellt hat, dass alle Stunden gleich sind, bevor sie ausgegeben werden. 0wird als Platzhalter verwendet, da leere Zeichenfolgen mehr Byte kosten, um sie in Batch zu vergleichen.

Neil
quelle
2

Jelly , 87 84 80 75 Bytes

  • 4Bytes mit der freundlichen Hilfe von @Dennis (Fehler behoben, den ich mit dem 'schnellen "Flat" benutzt habe)

Ich bin mir ziemlich sicher, dass es einen besseren Weg gibt, aber im Moment:

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

TryiItOnline

Wie?

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

Übernimmt die Eingabe als Array und gibt sie in separaten Zeilen an die Konsole aus. Dies ist fast genau ein Port meiner Batch-Antwort; fjetzt standardmäßig auf eine leere Zeichenfolge natürlich, während ich auch Standard kann lund wauf 'sun'(unter Verwendung eines Sentinel - Wert gespeichert me 3 Bytes in Batch , weil ich in der Lage war , die Initialisierung in die verschmelzen set/a).

Neil
quelle
1

BaCon , 514 496 455 Bytes

Das folgende BASIC-Programm wird mit seinem Einzug angezeigt. Ohne Einrückung besteht es jedoch aus 455 Bytes.

Die Idee ist, die Zeitpläne als Indizes für ein assoziatives Array zu verwenden. Dann steht jeder Tag für ein Bit: Montag = Bit 0, Dienstag = Bit 1, Mittwoch = Bit 2 und so weiter. Die tatsächlichen Werte für die Mitglieder des assoziativen Arrays werden durch die jeweiligen Bits der Tage unter Verwendung eines binären ODER berechnet.

Danach muss überprüft werden, wie viele aufeinanderfolgende Bits in den assoziativen Array-Elementen vorhanden sind, beginnend mit Bit 0.

Falls Bit 0 und auch Bit 6 gesetzt sind, erfolgt ein Wochenumbruch. Suchen Sie in diesem Fall nach dem Beginn der nächsten Bitfolge und speichern Sie diese Startposition. Drucken Sie den Rest der Sequenzen aus und sobald Bit 6 erreicht ist, sollte der Tagesbereich mit der gespeicherten Position früher beendet werden.

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

Verwenden Sie die folgenden Aufrufe, um den SUB aufzurufen:

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")

Ausgabe :

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
quelle