Знак, що показує згруповані години роботи кафе


20

Напевно ви бачили ці знаки на дверях різних магазинів:

ГОДИНИ РОБОТИ

пн-пт 0900-1800
сб-нд 1100-1530

Завдання тут - створити такий знак, групуючи дні поспіль з однаковими годинами роботи, зі списку годин роботи протягом цілого тижня. Зауважте, що тиждень "обгортається" для того, що вважається послідовним.

Вхід:

  • 7 елементів, що представляють години роботи кожного дня в тиждень, починаючи з понеділка.
  • Кожен елемент є рядком у формі XXXX-XXXX
  • Приклад введення:

    0900-1800 0900-1800 0930-1730 0930-1730 0900-1500 1100-1500 1100-1500
    
  • Добре надсилати вхід як масив (наприклад, як вхід до функції, якщо ви не читаєте з stdin)

Вихід:

  • Перелік годин роботи, де послідовні дні з однаковими годинами роботи відображаються як діапазон. Зауважте, що неділя (останній день) та понеділок (перший день) також є днями поспіль.
  • День, коли день не має подібних годин роботи до днів до або після, друкується сам
  • Дні вказані у вигляді трьох малих літер: пн вт ср пт сб св
  • Пам’ятайте, що перший елемент у вході відповідає пн, поруч з т. Д.
  • Години роботи відображаються як на вході
  • Два приклади

    mon-fri 0900-1800, sat-sun 1100-1500
    mon-wed 1030-1530, thu 100-1800, fri-sun 1200-1630
    
  • Вихід повинен бути відсортований, так що діапазони відображаються в порядку порядку днів у тиждень. Понеділок вважають за краще бути першим, але може статися, що він не перший у групі, тому що тиждень завершується. Тож у даному випадку вт є перший діапазон.

    tue-fri 0900-1800, sat-mon 1100-1500
    
  • Не групуйтеся, якщо не є послідовними, тут середа та п’ятниця мають однакові години роботи, але розділяються на четвер з різним часом роботи, тому вони перераховані самі.

    mon-tue 1000-1200, wed 0900-1500, thu 1000-1800, fri 0900-1500, sat-sun 1000-1500
    
  • Вихід може бути або розділеним комою, як приклади тут, або розділеним новим рядком, як у прикладі зверху.

Тестові кейси

Перший рядок вводиться, другий рядок очікується вихід

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

Правила

Це код-гольф, тому найкоротша відповідь у байтах виграє.


7
Ласкаво просимо до головоломки програмування та коду для гольфу. Це хороший виклик; молодець! Надалі я рекомендую використовувати пісочницю перед тим, як опублікувати виклик. (Ви знаєте, про всяк випадок ...)
wizzwizz4

1
Вважати неділю та понеділок поспіль мені здається дивним ...
Фредерік

1
Я відчуваю, що має бути тестовий випадок для "пн-сонця" про всяк випадок, якщо будь-яке подання не належним чином обробляє конкретний базовий випадок.
Патрік Робертс

Відповіді:


7

JavaScript (ES6), 182 173 170 163 157 байт

Збережено 6 байт за допомогою edc65

Приймає введення як масив рядків і безпосередньо друкує результат на консоль:

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

Відформатовано та прокоментовано

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)

Тестові кейси

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)використання Dв якості масиву замість функції має зберегти деякий байт
edc65

@ edc65 - На жаль, D()його можна викликати -1(коли ми шукаємо "день до понеділка"), який працює з, substr()але не працює з масивом.
Арнольд

@ edc65 - EDIT: комбінуючи свій метод з іншим виправленням, це безумовно виграш. Спасибі!
Арнольд

3

Пакетна, 334 байт

@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

Приймає введення як параметри командного рядка, виводить кожну групу в окремий рядок. Працює, порівнюючи години кожного дня з попереднім днем, відслідковуючи fяк перший день у групі, hяк години для цієї групи, lяк останній день у групі та wза те, коли остання група завершується до початку тижня. При виявленні невідповідностей попередня група друкується, якщо не діє тижневе обгортання. Нарешті, коли всі дні обробляються, останню групу коригують під будь-яке завершення тижня і чи всі години виявилися однаковими до виведення. 0використовується як заповнювач, оскільки порожні рядки коштують більше байтів для порівняння в Batch.


2

Желе , 87 84 80 75 байт

  • 4 байти з доброю допомогою @Dennis (виправлено хак, який я використовував із 'швидкою, "плоскою")

Напевно, є кращий спосіб, але поки що:

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

TryiItOnline

Як?

            “ḅạṄ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 байт

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)

Приймає введення як масив і виводить на консоль окремими рядками. Це майже точно порт моєї відповіді Партії; fтепер, за замовчуванням, звичайно, порожній рядок, тоді як я також можу за замовчуванням lі wдо 'sun'(використовуючи дозорне значення врятувало мені 3 байти в Batch, оскільки мені вдалося об'єднати ініціалізацію в set/a).


1

Бакон , 514 496 455 байт

Програма BASIC нижче показана з відступом. Але без відступу він складається з 455 байт.

Ідея полягає у використанні графіків часу як індексів асоціативного масиву. Потім кожен день являє собою трохи: понеділок = біт 0, вівторок = біт 1, середа = біт 2 тощо. Фактичні значення для членів асоціативного масиву обчислюються відповідними бітами днів за допомогою двійкового АБО.

Після цього слід перевірити, скільки послідовних бітів є в асоціативних елементах масиву, починаючи з біта 0.

Якщо встановлено біт 0, а також біт 6, відбувається тижневе завершення роботи. У такому випадку починайте шукати початок наступної послідовності бітів, запам'ятовуючи це початкове положення. Роздрукуйте решту послідовностей, і як тільки досягне біт 6, діапазон дня повинен бути закінчений на запам'ятоване положення раніше.

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

Використовуючи наступні дзвінки для виклику 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")

Вихід :

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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.