Znak pokazujący zgrupowane godziny otwarcia kawiarni

20

Prawdopodobnie widziałeś te znaki na drzwiach różnych sklepów:

GODZINY OTWARCIA

pn – pt 0900–1800 sob.
-niedz. 1100–1530

Zadanie polega na wygenerowaniu takiego znaku, grupując kolejne dni z tymi samymi godzinami otwarcia, z listy godzin otwarcia na cały tydzień. Zauważ, że tydzień „zawija się”, co jest uważane za kolejne.

Wejście:

  • 7 elementów, reprezentujących godziny otwarcia każdego dnia w tygodniu, zaczynając od poniedziałku.
  • Każdy element jest ciągiem w postaci XXXX-XXXX
  • Przykładowe dane wejściowe:

    0900-1800 0900-1800 0930-1730 0930-1730 0900-1500 1100-1500 1100-1500
    
  • Można wysłać dane wejściowe jako tablicę (na przykład jako dane wejściowe do funkcji, jeśli nie czytasz ze standardowego wejścia)

Wynik:

  • Lista godzin otwarcia, w których kolejne dni z tymi samymi godzinami otwarcia są pokazane jako zakres. Pamiętaj, że niedziela (ostatni dzień) i poniedziałek (pierwszy dzień) to także kolejne dni.
  • Dzień, w którym dzień nie ma podobnych godzin otwarcia jak dni przed lub po, jest drukowany sam
  • Dni są określone jako trzy małe litery: pon wt śr czw pt sr niedz
  • Pamiętaj, że pierwszy element na wejściu odpowiada mon, obok wt itp.
  • Godziny otwarcia są pokazane jak na wejściu
  • Dwa przykłady

    mon-fri 0900-1800, sat-sun 1100-1500
    mon-wed 1030-1530, thu 100-1800, fri-sun 1200-1630
    
  • Dane wyjściowe należy posortować, aby zakresy były wyświetlane w kolejności dni w tygodniu. Poniedziałek jest preferowany jako pierwszy, ale może się zdarzyć, że nie jest pierwszy w grupie, ponieważ tydzień się kończy. Więc w tym przypadku wt jest pierwszym zakresem.

    tue-fri 0900-1800, sat-mon 1100-1500
    
  • Nie grupuj, chyba że z rzędu, tutaj środa i piątek mają takie same godziny otwarcia, ale są oddzielone czwartkiem z różnymi godzinami otwarcia, więc są one wymienione osobno.

    mon-tue 1000-1200, wed 0900-1500, thu 1000-1800, fri 0900-1500, sat-sun 1000-1500
    
  • Dane wyjściowe mogą być rozdzielone przecinkami jako przykłady tutaj lub oddzielone znakiem nowej linii, jak w przykładzie na górze.

Przypadki testowe

Pierwszy wiersz jest wprowadzany, drugi wiersz jest oczekiwany

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

Zasady

To jest golf golfowy, więc wygrywa najkrótsza odpowiedź w bajtach.

Matsemann
źródło
7
Witamy w Programowaniu zagadek i Code Golf. To dobre wyzwanie; dobra robota! W przyszłości polecam korzystanie z piaskownicy przed opublikowaniem wyzwania. (Wiesz, na wszelki wypadek ...)
wizzwizz4,
1
Dzisiejsza niedziela i poniedziałek wydaje mi się dziwna ...
Frédéric,
1
Wydaje mi się, że powinien istnieć testowy przypadek „mon-sun” na wypadek, gdyby jakiekolwiek przesłanie nie obsługiwało właściwie tego konkretnego przypadku podstawowego.
Patrick Roberts,

Odpowiedzi:

7

JavaScript (ES6), 182 173 170 163 157 bajtów

Zapisano 6 bajtów za pomocą edc65

Pobiera dane wejściowe jako tablicę ciągów i bezpośrednio drukuje wynik na konsoli:

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

Sformatowane i skomentowane

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)

Przypadki testowe

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
źródło
D='montuewedthufrisatsun'.match(/.../g)użycie Djako tablicy zamiast funkcji powinno zaoszczędzić trochę bajtów
edc65
@ edc65 - Niestety D()można go wywołać za pomocą -1(gdy szukamy słowa „dzień przed poniedziałkiem”), który działa, substr()ale nie działa z tablicą.
Arnauld,
@ edc65 - EDYCJA: łącząc twoją metodę z inną poprawką, jest to zdecydowanie wygrana. Dzięki!
Arnauld,
3

Partia, 334 bajty

@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

Pobiera dane wejściowe jako parametry wiersza polecenia, wyświetla każdą grupę w osobnym wierszu. Działa poprzez porównywanie godzin każdego dnia z poprzednim dniem, śledząc fjako pierwszy dzień w grupie, hjako godziny dla tej grupy, ljako ostatni dzień w grupie i wkiedy ostatnia grupa wraca na początek tygodnia. Po znalezieniu niedopasowania drukowana jest poprzednia grupa, chyba że ma miejsce zawijanie tygodnia. Na koniec, gdy wszystkie dni są przetwarzane, ostatnia grupa jest dostosowywana do każdego tygodnia pakowania i czy wszystkie godziny okazały się takie same przed wyjściem. 0jest używany jako symbol zastępczy, ponieważ puste ciągi kosztują więcej bajtów do porównania w partii.

Neil
źródło
2

Galareta , 87 84 80 75 bajtów

  • 4 bajty z uprzejmą pomocą @Dennis (naprawiono włamanie, którego użyłem z 'szybkim, „płaskim”)

Jestem pewien, że istnieje lepszy sposób, ale na razie:

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

TryiItOnline

W jaki sposób?

            “ḅạṄ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
źródło
1

JavaScript (ES6), 171 169 bajtów

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)

Pobiera dane wejściowe jako tablicę i wysyła do konsoli osobnymi wierszami. To jest prawie dokładnie port mojej odpowiedzi wsadowej; fteraz domyślnie pusty ciąg oczywiście, natomiast mogę również domyślnie li wdo 'sun'(używając wartości wskaźnikowych zaoszczędziło mi 3 bajty w trybie wsadowym, ponieważ udało mi się połączyć inicjalizacji Into the set/a).

Neil
źródło
1

BaCon , 514 496 455 bajtów

Poniższy program BASIC jest pokazany z wcięciem. Ale bez wcięcia składa się z 455 bajtów.

Chodzi o to, aby wykorzystać harmonogramy jako indeksy do tablicy asocjacyjnej. Następnie każdy dzień oznacza trochę: poniedziałek = bit 0, wtorek = bit 1, środa = bit 2 i tak dalej. Rzeczywiste wartości członków tablicy asocjacyjnej są obliczane na podstawie odpowiednich bitów dni przy użyciu binarnego OR.

Następnie należy sprawdzić, ile kolejnych bitów jest obecnych w elementach tablicy asocjacyjnej, zaczynając od bitu 0.

W przypadku ustawienia bitu 0 i bitu 6 jest zawijanie tygodnia. W takim przypadku zacznij szukać początku następnej sekwencji bitów, zapamiętując tę ​​pozycję początkową. Wydrukuj resztę sekwencji, a gdy tylko bit 6 zostanie osiągnięty, zakres dnia powinien zostać zakończony wcześniej zapamiętaną pozycją.

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

Korzystanie z następujących wywołań w celu wywołania 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")

Wyjście :

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
Piotr
źródło