Một dấu hiệu cho thấy giờ mở cửa của một quán cà phê


20

Bạn có thể đã nhìn thấy những dấu hiệu này trên cửa của các cửa hàng khác nhau:

GIỜ MỞ CỬA

mon-fri 0900-1800
sat-sun 1100-1530

Nhiệm vụ ở đây là tạo ra một dấu hiệu như vậy, nhóm các ngày liên tiếp với cùng giờ mở cửa, từ danh sách giờ mở cửa cho cả tuần. Lưu ý rằng tuần "kết thúc tốt đẹp" cho những gì được coi là liên tiếp.

Đầu vào:

  • 7 yếu tố, đại diện cho giờ mở cửa cho mỗi ngày trong một tuần, bắt đầu từ thứ Hai.
  • Mỗi phần tử là một chuỗi, trên biểu mẫu XXXX-XXXX
  • Ví dụ đầu vào:

    0900-1800 0900-1800 0930-1730 0930-1730 0900-1500 1100-1500 1100-1500
    
  • Bạn có thể gửi đầu vào dưới dạng một mảng (ví dụ như đầu vào cho hàm nếu bạn không đọc từ stdin)

Đầu ra:

  • Một danh sách các giờ mở cửa, trong đó các ngày liên tiếp có cùng giờ mở cửa được hiển thị dưới dạng một phạm vi. Lưu ý rằng chủ nhật (ngày cuối cùng) và thứ hai (ngày đầu tiên) cũng là những ngày liên tiếp.
  • Một ngày mà ngày không có giờ mở cửa tương tự như ngày trước hoặc sau được in
  • Ngày được chỉ định là ba chữ cái viết thường: mon tue wed thu fri sat sun
  • Hãy nhớ rằng phần tử đầu tiên trong đầu vào tương ứng với mon, bên cạnh tue, v.v.
  • Giờ mở cửa được hiển thị như trong đầu vào
  • Hai ví dụ

    mon-fri 0900-1800, sat-sun 1100-1500
    mon-wed 1030-1530, thu 100-1800, fri-sun 1200-1630
    
  • Đầu ra phải được sắp xếp, để các phạm vi xuất hiện theo thứ tự các ngày làm trong tuần. Thứ hai được ưu tiên là đầu tiên, nhưng có thể xảy ra nó không phải là đầu tiên trong một nhóm vì tuần kết thúc tốt đẹp. Vì vậy, trong trường hợp này, tue là phạm vi đầu tiên.

    tue-fri 0900-1800, sat-mon 1100-1500
    
  • Đừng nhóm trừ khi liên tiếp, ở đây thứ tư và thứ sáu có cùng giờ mở cửa nhưng được phân tách vào thứ năm với giờ mở cửa khác nhau để chúng được liệt kê bởi chính họ.

    mon-tue 1000-1200, wed 0900-1500, thu 1000-1800, fri 0900-1500, sat-sun 1000-1500
    
  • Đầu ra có thể được phân tách bằng dấu phẩy như các ví dụ ở đây hoặc được phân tách bằng một dòng mới như trong ví dụ trên.

Các trường hợp thử nghiệm

Dòng đầu tiên là đầu vào, dòng thứ hai là đầu ra dự kiến

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

Quy tắc

Đây là môn đánh gôn, vì vậy câu trả lời ngắn nhất bằng byte sẽ thắng.


7
Chào mừng bạn đến với Câu đố lập trình và Code Golf. Đây là một thử thách tốt; làm tốt! Trong tương lai, tôi sẽ khuyên bạn nên sử dụng hộp cát trước khi đăng một thử thách. (Bạn biết đấy, chỉ trong trường hợp ...)
wizzwizz4

1
Có chủ nhật và thứ hai liên tiếp có vẻ kỳ lạ đối với tôi ...
Frédéric

1
Tôi cảm thấy như nên có một trường hợp thử nghiệm cho "mon-sun" chỉ trong trường hợp bất kỳ đệ trình nào không xử lý đúng trường hợp cơ sở cụ thể đó.
Patrick Roberts

Câu trả lời:


7

JavaScript (ES6), 182 173 170 163 157 byte

Đã lưu 6 byte với sự trợ giúp của edc65

Đưa đầu vào dưới dạng một chuỗi các chuỗi và trực tiếp in kết quả ra bàn điều khiển:

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

Định dạng và nhận xét

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)

Các trường hợp thử nghiệm

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)sử dụng Dnhư một mảng thay vì một hàm nên tiết kiệm một số byte
edc65

@ edc65 - Thật không may D()có thể được gọi với -1(khi chúng tôi tìm kiếm 'ngày trước thứ Hai'), hoạt động với substr()nhưng không hoạt động với một mảng.
Arnauld

@ edc65 - EDIT: bằng cách kết hợp phương pháp của bạn với một bản sửa lỗi khác, đây chắc chắn là một chiến thắng. Cảm ơn!
Arnauld

3

Mẻ, 334 byte

@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

Lấy đầu vào làm tham số dòng lệnh, xuất ra mỗi nhóm trên một dòng riêng biệt. Hoạt động bằng cách so sánh giờ của mỗi ngày với ngày hôm trước, theo dõi flà ngày đầu tiên trong nhóm, hlà giờ của nhóm đó, llà ngày cuối cùng trong nhóm và wkhi nhóm cuối cùng kết thúc vào đầu tuần. Khi tìm thấy sự không phù hợp, nhóm trước đó được in trừ khi gói tuần có hiệu lực. Cuối cùng, khi tất cả các ngày được xử lý, nhóm cuối cùng được điều chỉnh cho bất kỳ gói tuần nào và liệu tất cả các giờ có giống nhau hay không trước khi được xuất. 0được sử dụng như một trình giữ chỗ vì các chuỗi rỗng tốn nhiều byte hơn để so sánh trong Batch.


2

Thạch , 87 84 80 75 byte

  • 4byte với sự trợ giúp của @Dennis (đã sửa một bản hack tôi đã sử dụng với tính năng '"phẳng" nhanh chóng)

Khá chắc chắn có một cách tốt hơn nhưng bây giờ:

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

Thử trực tuyến

Làm sao?

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

Đưa đầu vào dưới dạng một mảng và xuất ra bàn điều khiển trên các dòng riêng biệt. Đây gần như chính xác là một cổng của câu trả lời Batch của tôi; ftại mặc định là một chuỗi rỗng tất nhiên, trong khi tôi cũng có thể mặc lwđể 'sun'(sử dụng một giá trị trọng điểm đã cứu tôi 3 byte trong hàng loạt vì tôi đã có thể hợp nhất khởi động vào set/a).


1

BaCon , 514 496 455 byte

Chương trình BASIC dưới đây được hiển thị với thụt lề. Nhưng không có thụt lề, nó bao gồm 455 byte.

Ý tưởng là sử dụng lịch trình thời gian làm chỉ mục cho một mảng kết hợp. Sau đó, mỗi ngày đại diện cho một bit: Thứ hai = bit 0, Thứ ba = bit 1, Thứ tư = bit 2, v.v. Các giá trị thực tế cho các thành viên của mảng kết hợp được tính bằng các bit tương ứng của ngày sử dụng OR nhị phân.

Sau đó, vấn đề là kiểm tra có bao nhiêu bit liên tiếp có mặt trong các thành viên mảng kết hợp, bắt đầu với bit 0.

Trong trường hợp bit 0 và bit 6 được đặt, có một gói tuần. Trong trường hợp đó, bắt đầu tìm kiếm sự bắt đầu của chuỗi bit tiếp theo, ghi nhớ vị trí bắt đầu này. In phần còn lại của chuỗi và ngay khi đạt được bit 6, phạm vi ngày sẽ được kết thúc bằng vị trí ghi nhớ trước đó.

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

Sử dụng các cuộc gọi sau để gọi 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")

Đầu ra :

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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.