Sebuah tanda yang menunjukkan jam buka sebuah kafe yang dikelompokkan

20

Anda mungkin telah melihat tanda-tanda ini di pintu berbagai toko:

JAM BUKA

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

Tugas di sini adalah membuat tanda seperti itu, mengelompokkan hari berturut-turut dengan jam buka yang sama, dari daftar jam buka selama seminggu penuh. Perhatikan bahwa minggu "membungkus" untuk apa yang dianggap berturut-turut.

Memasukkan:

  • 7 elemen, mewakili jam buka untuk setiap hari dalam seminggu, dimulai dengan hari Senin.
  • Setiap elemen adalah string, pada formulir XXXX-XXXX
  • Input contoh:

    0900-1800 0900-1800 0930-1730 0930-1730 0900-1500 1100-1500 1100-1500
    
  • Tidak apa-apa untuk mengirim input sebagai array (misalnya sebagai input ke fungsi jika Anda tidak membaca dari stdin)

Keluaran:

  • Daftar jam buka, di mana hari berturut-turut dengan jam buka yang sama ditampilkan sebagai rentang. Perhatikan bahwa hari Minggu (hari terakhir) dan Senin (hari pertama) juga merupakan hari berturut-turut.
  • Hari di mana hari itu tidak memiliki jam buka yang sama dengan hari-hari sebelum atau sesudah dicetak dengan sendirinya
  • Hari-hari ditentukan sebagai tiga huruf kecil: Senin malam, Minggu
  • Ingat bahwa elemen pertama dalam input sesuai dengan mon, di samping sel dll.
  • Jam buka ditampilkan seperti pada input
  • Dua contoh

    mon-fri 0900-1800, sat-sun 1100-1500
    mon-wed 1030-1530, thu 100-1800, fri-sun 1200-1630
    
  • Outputnya harus disortir, sehingga rentang muncul sesuai urutan hari dalam seminggu. Senin lebih disukai menjadi yang pertama, tetapi mungkin terjadi itu bukan yang pertama dalam suatu kelompok karena minggu itu berakhir. Jadi dalam hal ini sel adalah rentang pertama.

    tue-fri 0900-1800, sat-mon 1100-1500
    
  • Jangan berkelompok kecuali berturut-turut, di sini Rabu dan Jumat memiliki jam buka yang sama tetapi dipisahkan oleh hari Kamis dengan jam buka yang berbeda sehingga mereka didaftar sendiri.

    mon-tue 1000-1200, wed 0900-1500, thu 1000-1800, fri 0900-1500, sat-sun 1000-1500
    
  • Outputnya dapat dipisahkan dengan koma sebagai contoh di sini, atau dipisahkan oleh baris baru seperti pada contoh di atas.

Uji kasus

Baris pertama adalah input, baris kedua adalah output yang diharapkan

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

Aturan

Ini adalah kode-golf, jadi jawaban tersingkat dalam byte menang.

Matsemann
sumber
7
Selamat datang di Programming Puzzles and Code Golf. Ini adalah tantangan yang bagus; sudah selesai dilakukan dengan baik! Di masa depan, saya akan merekomendasikan menggunakan kotak pasir sebelum memposting tantangan. (Anda tahu, untuk berjaga-jaga ...)
wizzwizz4
1
Memiliki hari Minggu dan Senin secara berurutan sepertinya aneh bagi saya ...
Frédéric
1
Saya merasa seperti harus ada test case untuk "mon-sun" kalau-kalau pengajuan tidak benar menangani kasus dasar tertentu.
Patrick Roberts

Jawaban:

7

JavaScript (ES6), 182 173 170 163 157 byte

Disimpan 6 byte dengan bantuan edc65

Mengambil input sebagai array string dan langsung mencetak hasilnya ke konsol:

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

Diformat dan dikomentari

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)

Uji kasus

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"]);

Arnauld
sumber
D='montuewedthufrisatsun'.match(/.../g)menggunakan Dsebagai array bukan fungsi harus menyimpan beberapa byte
edc65
@ edc65 - Sayangnya D()dapat dipanggil dengan -1(ketika kita mencari 'hari sebelum Senin'), yang berfungsi dengan substr()tetapi tidak akan bekerja dengan array.
Arnauld
@ edc65 - EDIT: dengan menggabungkan metode Anda dengan perbaikan lain, ini pasti menang. Terima kasih!
Arnauld
3

Batch, 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

Mengambil input sebagai parameter baris perintah, output setiap grup pada baris terpisah. Bekerja dengan membandingkan jam setiap hari dengan hari sebelumnya, melacak fsebagai hari pertama dalam grup, hsebagai jam untuk grup itu, lsebagai hari terakhir dalam grup dan wketika kelompok terakhir kembali ke awal minggu. Ketika ketidakcocokan ditemukan kelompok sebelumnya dicetak kecuali pembungkus minggu berlaku. Akhirnya ketika semua hari diproses, kelompok terakhir disesuaikan untuk setiap minggu pembungkus dan apakah semua jam ternyata sama sebelum menjadi output. 0digunakan sebagai pengganti karena string kosong membutuhkan lebih banyak byte untuk dibandingkan di Batch.

Neil
sumber
2

Jelly , 87 84 80 75 byte

  • 4bytes dengan bantuan jenis @Dennis (memperbaiki retas yang saya gunakan dengan '"flat" yang cepat)

Cukup yakin ada cara yang lebih baik tetapi untuk saat ini:

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

TryiItOnline

Bagaimana?

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

Membawa input sebagai array dan output ke konsol pada baris terpisah. Ini hampir persis port jawaban Batch saya; fsekarang default ke string kosong tentu saja, sementara saya juga bisa default ldan wke 'sun'(menggunakan nilai sentinel menyelamatkan saya 3 byte di Batch karena saya bisa menggabungkan inisialisasi ke dalam set/a).

Neil
sumber
1

BaCon , 514 496 455 byte

Program BASIC di bawah ini ditunjukkan dengan lekukannya. Tetapi tanpa lekukan itu terdiri dari 455 byte.

Idenya adalah untuk menggunakan jadwal waktu sebagai indeks ke array asosiatif. Kemudian, setiap hari mewakili sedikit: Senin = bit 0, Selasa = bit 1, Rabu = bit 2 dan seterusnya. Nilai aktual untuk anggota array asosiatif dihitung oleh bit masing-masing hari menggunakan biner OR.

Setelah itu, masalah memeriksa berapa banyak bit berturut-turut hadir dalam anggota array asosiatif, dimulai dengan bit 0.

Dalam kasus bit 0 dan juga bit 6 diatur, ada bungkus minggu. Dalam hal ini, mulailah mencari awal dari urutan bit berikutnya, hafalkan posisi awal ini. Cetak sisa urutan, dan segera setelah bit 6 tercapai, rentang hari harus diakhiri dengan posisi yang dihafal sebelumnya.

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

Menggunakan panggilan berikut untuk memanggil 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")

Keluaran :

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
Peter
sumber