Вывеска, показывающая сгруппированные часы работы кафе


20

Вы, наверное, видели эти знаки на дверях разных магазинов:

ЧАСЫ РАБОТЫ

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

Задача здесь состоит в том, чтобы сгенерировать такой знак, сгруппировав последовательные дни с одинаковыми часами работы из списка часов работы на всю неделю. Обратите внимание, что неделя «оборачивается» тем, что считается последовательным.

Входные данные:

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

    0900-1800 0900-1800 0930-1730 0930-1730 0900-1500 1100-1500 1100-1500
    
  • Можно отправлять входные данные в виде массива (например, в качестве входных данных для функции, если вы не читаете из стандартного ввода)

Выход:

  • Список часов работы, где последовательные дни с одинаковыми часами работы отображаются в виде диапазона. Обратите внимание, что воскресенье (последний день) и понедельник (первый день) также являются последовательными днями.
  • День, в который у дня нет часов, аналогичных дням до или после, печатается сам по себе.
  • Дни обозначаются тремя строчными буквами: пн вт ср чт пт сб вс
  • Помните, что первый элемент на входе соответствует mon, рядом с tue и т. Д.
  • Часы работы показаны как на входе
  • Два примера

    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
Добро пожаловать в Программирование головоломок и Code Golf. Это хороший вызов; отлично сработано! В будущем я бы порекомендовал использовать песочницу, прежде чем отправлять вызов. (Вы знаете, на всякий случай ...)
wizzwizz4

1
Мне кажется странным иметь воскресенье и понедельник ...
Фредерик

1
Я чувствую, что должен быть тестовый случай для «mon-sun» на тот случай, если любая заявка не будет правильно обрабатывать этот конкретный базовый случай.
Патрик Робертс

Ответы:


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 - РЕДАКТИРОВАТЬ: объединяя ваш метод с другим исправлением, это определенно победа. Благодарность!
Арно

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используется в качестве заполнителя, потому что пустые строки стоят больше байтов для сравнения в пакетном режиме.


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 байта в пакете, потому что я смог объединить инициализацию с set/a).


1

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