一个显示咖啡馆分组营业时间的标志


20

您可能已经在各种商店的门上看到这些标志:

营业时间

周一至周五
0900-1800周日1100-1530

这里的任务是从整个星期的开放时间列表中生成一个类似的符号,将具有相同开放时间的连续天分组。请注意,一周被认为是连续的。

输入:

  • 7个元素,代表每周从星期一开始的每天的开放时间。
  • 每个元素都是一个字符串,格式为XXXX-XXXX
  • 输入示例:

    0900-1800 0900-1800 0930-1730 0930-1730 0900-1500 1100-1500 1100-1500
    
  • 可以将输入作为数组发送(例如,如果您不从stdin中读取,则作为函数的输入)

输出:

  • 营业时间列表,其中具有相同营业时间的连续天显示为一个范围。请注意,星期日(最后一天)和星期一(第一天)也是连续的几天。
  • 一天的营业时间与之前或之后的日子没有类似的一天是自己打印的
  • 将日期指定为三个小写字母:周一周二周三周四周五周日
  • 请记住,输入中的第一个元素对应于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'8-10-8

1
有周日和周一连续作为似乎很奇怪,我...
弗雷德里克

1
我觉得应该有一个“ mon-sun”的测试用例,以防万一任何提交都不能正确处理该特定基本情况。
帕特里克·罗伯茨

Answers:


7

的JavaScript(ES6),182个 173 170 163 157字节

在edc65的帮助下保存了6个字节

将输入作为字符串数组并将结果直接打印到控制台:

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()数组一起使用,但不能与数组一起使用。
Arnauld

@ edc65-编辑:通过将您的方法与另一个修复程序结合,这绝对是一个胜利。谢谢!
Arnauld

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 字节

  • @Dennis的帮助下为4bytes(修复了我与'快速的“ flat” 一起使用的hack )

可以肯定,现在有更好的方法:

Ṫ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

培根514 496 455字节

下面的BASIC程序及其缩进显示。但如果没有缩进,则它包含455个字节。

这个想法是将时间表用作关联数组的索引。然后,每一天代表一个位:星期一=位0,星期二=位1,星期三=位2,依此类推。关联数组成员的实际值是使用二进制OR通过天的各个位计算的。

之后,检查从位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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.