ป้ายแสดงเวลาเปิดทำการของร้านกาแฟ


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
มีวันอาทิตย์และวันจันทร์เป็นติดต่อกันดูเหมือนว่าแปลกที่ฉัน ...
Frédéric

1
ฉันรู้สึกว่าควรจะมีกรณีทดสอบสำหรับ "จันทร์ - อาทิตย์" ในกรณีที่การส่งใด ๆ ที่ไม่เหมาะสมกับกรณีฐานนั้น
Patrick Roberts

คำตอบ:


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()แต่จะไม่ทำงานกับอาร์เรย์
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ใช้เป็นตัวยึดตำแหน่งเนื่องจากสตริงที่ว่างเปล่ามีค่าใช้จ่ายมากกว่าไบต์เพื่อเปรียบเทียบในชุดงาน


2

เยลลี่ , 87 84 80 75 ไบต์

  • 4bytes ด้วยความช่วยเหลือจาก @Dennis (แก้ไขแฮ็คที่ฉันใช้ด้วย'"flat" อย่างรวดเร็ว)

ค่อนข้างแน่ใจว่ามีวิธีที่ดีกว่า แต่ตอนนี้:

Ṫ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 bytes ใน Batch เพราะฉันสามารถผสาน initialisation ในset/a)


1

BaCon , 514 496 455 ไบต์

โปรแกรมพื้นฐานด้านล่างจะแสดงพร้อมการเยื้อง แต่ถ้าไม่มีการเยื้องก็จะประกอบด้วย 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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.