Perencana Kalender ASCII

11

Diberikan daftar kegiatan dan waktu / tanggal mulai, mengeluarkan kalender ASCII-art yang menunjukkan kegiatan pada hari yang tepat. Semua aktivitas dijamin berada di bulan yang sama, tidak ada dua aktivitas yang akan dilakukan pada hari yang sama, dan semua aktivitas dijamin sesuai di dalam kotak kalender.

Kalender memiliki tanggal di sudut kiri atas setiap kotak, kotak-kotaknya berukuran 9 spasi dengan tinggi 5 ruang, dikelilingi oleh -dan |. Singkatan dua huruf untuk hari dalam seminggu berpusat di atas baris pertama, dan minggu-minggu dimulai dengan hari Minggu.

Misalnya, mengingat kegiatan berikut:

10/5/2018 - 9:00am - Sandbox calendar challenge
10/9/2018 - 9:00am - Post challenge to main
10/10/2018 - 10:00am - Profit
10/31/2018 - 7:30pm - Halloween party

Keluarkan kalender yang sesuai ini:

    Su        Mo        Tu        We        Th        Fr        Sa     
-----------------------------------------------------------------------
|         |1        |2        |3        |4        |5        |6        |
|         |         |         |         |         |9:00am   |         |
|         |         |         |         |         |Sandbox  |         |
|         |         |         |         |         |calendar |         |
|         |         |         |         |         |challenge|         |
-----------------------------------------------------------------------
|7        |8        |9        |10       |11       |12       |13       |
|         |         |9:00am   |10:00am  |         |         |         |
|         |         |Post     |Profit   |         |         |         |
|         |         |challenge|         |         |         |         |
|         |         |to main  |         |         |         |         |
-----------------------------------------------------------------------
|14       |15       |16       |17       |18       |19       |20       |
|         |         |         |         |         |         |         |
|         |         |         |         |         |         |         |
|         |         |         |         |         |         |         |
|         |         |         |         |         |         |         |
-----------------------------------------------------------------------
|21       |22       |23       |24       |25       |26       |27       |
|         |         |         |         |         |         |         |
|         |         |         |         |         |         |         |
|         |         |         |         |         |         |         |
|         |         |         |         |         |         |         |
-----------------------------------------------------------------------
|28       |29       |30       |31       |         |         |         |
|         |         |         |7:30pm   |         |         |         |
|         |         |         |Halloween|         |         |         |
|         |         |         |party    |         |         |         |
|         |         |         |         |         |         |         |
-----------------------------------------------------------------------

Klarifikasi

  • Kata-kata jadwal (pencocokan [A-Za-z] +) akan dibatasi oleh satu spasi di antara mereka (seperti dalam contoh).
  • Memisahkan teks pada batas kata sudah cukup. Tidak perlu kata-kata hyphenating.
  • Jika Februari dimulai pada hari Minggu tanpa tahun kabisat, Anda hanya akan memiliki empat baris kalender.
  • Jika bulan 31 hari (mis. Agustus) dimulai pada akhir minggu, Anda mungkin harus mengeluarkan enam baris kalender.

I / O dan Aturan

  • Kode Anda harus menangani tanggal setidaknya antara 0001-01-01dan 9999-12-31dalam kalender Gregorian, termasuk tahun kabisat yang sesuai. Misalnya, jika diberi input 2016-02-13 9:00am Test, kalender output harus memiliki 29 Februari.
  • Format tanggal input dapat dalam format apa pun yang diinginkan. ISO 8601, datetimeobjek, string terformat khusus, dll. Penguraian input bukan bagian yang menarik dari tantangan ini.
  • Input dan output dapat dengan metode apa pun yang mudah .
  • Leading / trailing newlines atau spasi putih lainnya adalah opsional, asalkan karakternya berbaris dengan tepat.
  • Program lengkap atau fungsi dapat diterima. Jika suatu fungsi, Anda dapat mengembalikan output daripada mencetaknya.
  • Output bisa ke konsol, dikembalikan sebagai daftar string, dikembalikan sebagai string tunggal, dll.
  • Celah standar dilarang.
  • Ini adalah sehingga semua aturan golf biasa berlaku, dan kode terpendek (dalam byte) menang.
AdmBorkBork
sumber
1.) Apakah Anda harus membagi nama aktivitas pada batas kata? 2.) Ketika Anda memiliki bulan Februari non-kabisat dimulai pada hari Minggu, apakah Anda hanya memiliki 4 baris? 3.) Kapan Anda akan membutuhkan 6 baris untuk menunjukkan bulan (mis. Agustus mulai hari Sabtu) apa yang terjadi?
nedla2004
Terkait (lebih mudah).
Arnauld
@ nedla2004 1) Ya, batas kata akan berfungsi dengan baik. 2) Benar, 4 baris. 3) Kalender Anda harus menunjukkan 6 baris. Saya akan mengedit klarifikasi.
AdmBorkBork
@Arnauld Ya, itu asumsi yang adil
AdmBorkBork
1
1752-09-02 - 09:00am - Wife's Birthday Tomorrow (14th!)
ngm

Jawaban:

10

JavaScript (ES8), 380 ... 321 320 byte

Mengambil input di (y,m,e)mana:

  • y adalah tahunnya
  • m adalah bulan, 0-diindeks
  • eadalah objek yang kuncinya adalah hari dan yang nilainya adalah peristiwa dalam [hour, task]format
(y,m,e)=>`SuMoTuWeThFrSa
`.split(/(..)/).join`    `+(p='-'.repeat(d=71)+`
`)+(g=i=>++d<1|(x=G`getMonth`==m)|i%7?`|${[h,t]=e[d]||E,o=[x*d,h],q=E,t&&t.split` `.map(s=>q=(u=q?q+' '+s:s)[9]?o.push(q)&&s:u),[...o,q][r%5]||E}`.padEnd(10)+(++i%7?E:`|
`+(++r%5?(d-=7,E):p))+g(i):E)(E=r='',d=-(G=s=>new Date(y,m,d)[s]())`getDay`)

Cobalah online!

Bagaimana?

Di bawah ini adalah beberapa bagian penting dalam kode.

Header

Baris tajuk dibuat dengan:

'SuMoTuWeThFrSa\n'.split(/(..)/).join`    `

Ketika split()digunakan dengan ekspresi reguler yang berisi grup penangkap, grup ini termasuk dalam larik keluaran. Dalam hal ini, ia memberikan:

[ '', 'Su', '', 'Mo', '', 'Tu', '', 'We', '', 'Th', '', 'Fr', '', 'Sa', '\n' ]

Kami bergabung dengan array ini dengan 4 spasi, mengarah ke:

'    Su        Mo        Tu        We        Th        Fr        Sa    \n'

yang persis apa yang kita inginkan.

Struktur bulan

Gymd

G = s => new Date(y, m, d)[s]()

x

Pemformatan acara

Kode berikut digunakan untuk memformat acara.

[h, t] = e[d] || E,           // split the content of the event into h and t
o = [x * d, h],               // set the first 2 entries of o[]: day and hour
q = E,                        // we start with q = empty string
t &&                          // skip this .map() loop entirely if t is not defined
t.split` `                    // split the string on spaces
.map(s =>                     // for each word s:
  q =                         //   update q:
    (u = q ? q + ' ' + s : s) //     u is the concatenation of the previous string with
                              //     the new word, separated by a space if needed
    [9] ?                     //     if u is more than 9 character long:
      o.push(q)               //       push the previous string in o[]
      && s                    //       and reset q to s
    :                         //     else:
      u                       //       update q to u
),                            // end of map()
[...o, q][r % 5]              // append the last pending part to o[] and extract the
|| E                          // relevant row; or use an empty string by default
Arnauld
sumber
3

Python 2 , 326 324 315 312 307 byte

import calendar as c,textwrap as t
c.setfirstweekday(6)
y,m,e=input()
print' Su Mo Tu We Th Fr Sa\n'.replace(' ',' '*8)[4:]+'-'*71
for w in c.monthcalendar(y,m):
 for l in zip(*[[d or'',a]+(t.wrap(b,9)+['']*3)[:3]for d in w for a,b in[e.get(d,'  ')]]):print'|'+'|'.join('%-9s'%v for v in l)+'|'
 print'-'*71

Cobalah online!

Masukan yang sama dengan jawaban JS Arnauld :

Mengambil input di (y,m,e)mana:

  • y adalah tahunnya
  • m adalah bulan, 1-diindeks
  • eadalah objek yang kuncinya adalah hari dan yang nilainya adalah peristiwa dalam (hour, task)format
TFeld
sumber
3

Arang , 215 206 byte

Sθ≔I⪪§⪪θ ⁰/η≔⁻⁺×¹²⊟η⊟η²η≔EE²⁻ηι﹪Σ⟦÷ι⁴⁸⁰⁰±÷ι¹²⁰⁰÷ι⁴⁸÷ι¹²÷×¹³⁺⁴﹪ι¹²¦⁵⟧⁷η≔±⊟ηζ≔⁺²⁸﹪⁺⊟ηζ⁷ε⭆⪪SuMoTuWeThFrSa²◨◧ι⁶χ↓←⁷¹W‹ζε«↘F⁷«P↓⁵→≦⊕ζF⁼Iζ§⪪θ/⁰«≔⪪θ - θ≔⟦ω◨§θ¹¦⁹⟧δF⪪⊟θ ⊞δ⎇‹⁺L§δ±¹Lμ⁹⁺⁺⊟δ μμP⪫δ¶Sθ»◨×››ζ⁰›ζεIζ⁹»↓⁵←⁷¹

Cobalah online! Tautan adalah untuk mengucapkan versi kode. Membawa tanggal dalam format d / m / yyyy. Penjelasan:

Sθ

Masukkan acara pertama.

≔I⪪§⪪θ ⁰/η

Ekstrak tanggal dan pisah pada /s.

≔⁻⁺×¹²⊟η⊟η²η

Konversi ke bulan sejak Maret, 1 SM. Saya ingin menghitung hari minggu pada bulan pertama dan bulan berikutnya, dan bekerja dalam bulan lebih mudah daripada memisahkan bulan dan tahun dan membawa pada akhir tahun, ditambah lagi juga memungkinkan saya untuk mulai menghitung bulan dimulai pada bulan Maret alih-alih Januari, yang disyaratkan oleh kongruensi Zeller.

≔EE²⁻ηι﹪Σ⟦÷ι⁴⁸⁰⁰±÷ι¹²⁰⁰÷ι⁴⁸÷ι¹²÷×¹³⁺⁴﹪ι¹²¦⁵⟧⁷η

Gunakan kongruensi Zeller yang dimodifikasi untuk mengekstrak hari minggu di hari pertama bulan depan dan bulan ini. Bagian dasarnya bergantung pada fakta bahwa jumlah hari dari 30 Oktober tahun sebelumnya ke tanggal 1 bulan tertentu di mana m = 4untuk bulan Maret dan m = 14Januari tahun berikutnya diberikan oleh rumus m * 153 / 5, namun kita dapat mengurangi 140 karena kita hanya peduli dengan hari dalam seminggu. Kemudian tetap membuat penyesuaian karena tahun; setiap tahun menambah satu hari, setiap tahun ke-4 menambahkan hari ekstra, setiap tahun ke-100 mengurangi satu hari, dan setiap tahun ke-400 menambahkan hari lagi. (Karena saya bekerja dalam bulan, nilai-nilai ini semua dikalikan dengan 12.) Agak nyaman ini langsung memberi saya jawaban dalam hal minggu indeks-Minggu (biasanya Anda akan menambahkan hari bulan dan mulai menghitung pada hari Sabtu).

≔±⊟ηζ

Meniadakan hari dalam seminggu dan simpan sebagai hari saat ini dalam sebulan.

≔⁺²⁸﹪⁺⊟ηζ⁷ε

Hitung jumlah hari dalam sebulan dari hari minggu dua bulan.

⭆⪪SuMoTuWeThFrSa²◨◧ι⁶χ

Keluarkan header hari.

↓←⁷¹

Cetak baris atas -s.

W‹ζε«

Loop sampai hari terakhir bulan telah di-output.

Pindahkan kursor ke awal baris berikutnya.

F⁷«

Memproses 7 hari sekaligus.

P↓⁵→

Cetak kolom |s ke kiri.

≦⊕ζ

Tambahkan hari saat ini di bulan tersebut.

F⁼Iζ§⪪θ/⁰«

Jika hari saat ini di bulan tersebut adalah hari acara saat ini, ...

≔⪪θ - θ

... ekstrak bagian lain dari acara tersebut, ...

≔⟦ω◨§θ¹¦⁹⟧δ

... pad waktu ke 9 spasi dan simpan dan string kosong sebagai daftar, ...

F⪪⊟θ 

... pisahkan deskripsi pada spasi dan lewati, ...

⊞δ⎇‹⁺L§δ±¹Lμ⁹⁺⁺⊟δ μμ

... menambahkan setiap kata ke kata sebelumnya jika itu sesuai; ...

P⪫δ¶

... menampilkan waktu dan deskripsi ( Pδtidak berfungsi, mungkin bug Charcoal?), ...

Sθ»

... dan masukan acara selanjutnya.

◨×››ζ⁰›ζεIζ⁹»

Jika hari saat ini di bulan adalah antara 1 dan hari terakhir dari bulan lalu keluarkan, jika tidak cukup output ruang yang cukup untuk pindah ke hari berikutnya.

↓⁵←⁷¹

Pada akhir minggu, cetak kolom kanan |s dan baris bawah -s.

Neil
sumber
Mungkin saya melewatkannya dalam kode TIO verbose Anda, tetapi apakah Anda yakin implementasi kongruensi Zeller Anda sudah selesai? Tampaknya benar untuk bulan Maret hingga Desember, tetapi untuk bulan Januari dan Februari year-1harus digunakan sebagai pengganti yeardan month+12harus digunakan sebagai pengganti month. Atau apakah Anda entah bagaimana menyederhanakan algoritma yang saya sebutkan dalam jawaban saya di 05AB1E ini yang sama dengan yang ada di Wikipedia ?
Kevin Cruijssen
@KevinCruijssen Ini pada dasarnya mengapa saya menghitung jumlah bulan sejak Maret, 1BC, tapi terlalu rumit untuk dijelaskan lebih lanjut dalam komentar.
Neil
1
@KevinCruijssen Saya telah memperbarui penjelasan saya; Saya harap Anda merasa terbantu.
Neil
Terima kasih! Itu memang formula modifikasi yang bagus, dan sekarang saya mengerti alasan di baliknya. Terima kasih banyak telah menambahkannya ke penjelasan. +1 dari saya.
Kevin Cruijssen
2

Java (JDK) , 538 439 428 425 byte

Sangat mungkin solusi Code Golf terpanjang yang pernah saya posting. Masih mencoba untuk bermain golf dari sini tapi itu sulit.

Berhasil merobohkan 99 byte dengan mengubah format input dan menggunakan beberapa penguraian regex, dan 11 lainnya dari bit lain-lain.

3 byte ekstra, terima kasih kepada Kevin!

Mengambil inspirasi dari jawaban lain, dibutuhkan input sebagai tahun, bulan dan Peta hari ke String yang mewakili waktu dan acara dalam format <time>-<event>.

(y,m,M)->{var C=java.util.Calendar.getInstance();C.set(y,m-1,1);String r=",Su,,Mo,,Tu,,We,,Th,,Fr,,Sa\n".replace(",","    "),e;for(int x=C.getActualMaximum(5),l=0,b=0,j,c,i=0;i<7;r+="\n",l+=b<=x&++i>6?7*(i=1):0)for(j=0;j<71;b=l+j/10+2-C.get(7),e=(e=M.get(b))!=null?e.replaceAll("([^-]{1,9})(-| |$)","$1-")+" - ":null,r+=e=i%6<1?"-":c<1?"|":c*i<2&b>0&b<=x?b+"":c<2&e!=null?e.split("-")[i-2]:" ",j+=e.length())c=j%10;return r;}

Cobalah online!


Tidak disatukan

(y,m,M)->{                                              // Lambda taking input as a year, month and map
  var C=java.util.Calendar.getInstance();               // Creates a new Calendar instance
  C.set(y,m-1,1);                                       // Sets the calendar to the first of the month in the given year    
  String r=",Su,,Mo,,Tu,,We,,Th,,Fr,,Sa\n"              // Creates the header row by replacing
    .replace(",","    "),e;                             // commas with 4 sets of spaces

  for(                                                  // Creates 7 rows for a calendar row
      int x=C.getActualMaximum(5)                       // Stores last day of the month
      ,l=0,b=0,j,c,i=0;i<7;                             // Initialises other integers
      r+="\n",                                          // Add new line each row
      l+=b<=x&++i>6                                     // If end of a calendar row is reached, and current day is less than max
        ?7*(i=1)                                        // Set i to 1 and add 7 to line count to create another calendar row
        :0)                                             // Otherwise do nothing

    for(j=0;j<71;                                       // Loop 71 times, appending characters to create a row
        b=l+j/10+2-C.get(7),                            // Determine the day of the box we're in
        e=(e=M.get(b))!=null?                           // Get the event for this day from the map and if not null
            e.replaceAll("([^-]{1,9})(-| |$)","$1-")      // Do some regex to separate the line entries by hyphens
            +" - "                                      // Append extra hyphen to prevent array out of bounds
            :null,                                      // Otherwise do nothing
        r+=e=i%6<1?"-":                                 // If it's the first line of a calendar row, append -
           c<1?"|":                                     // If it's the first column of a box, append |
           c*i<2&b>0&b<=x?b+"":                         // If it's the second column of a box, the second row, 
                                                        // and less than the max day, append the day
           c<2&e!=null?e.split("-")[i-2]:               // If it's any other row and there is an event then split and append correct line
           " ",                                         // Else just append a space
        j+=e.length())                                  // Increase the row character count by the length to append
          c=j%10;                                       // Set the column of box (this is the only thing in the loop so happens first)

  return r;                                             // return the calendar string!
}
Luke Stevens
sumber
&&(i=1)<2?7:0bisa ?7*(i=1):0untuk menghemat 3 byte.
Kevin Cruijssen
@KevinCruijssen Bagus sekali terima kasih!
Luke Stevens
Sarankan b>x|i++<6?0:7*(i=1)alih-alih b<=x&++i>6?7*(i=1):0dan c*i>1|b<1|b>x?c<2&e!=null?e.split("-")[i-2]:" ":b+""bukannyac*i<2&b>0&b<=x?b+"":c<2&e!=null?e.split("-")[i-2]:" "
ceilingcat
1

Merah , 674 651 byte

func[a][z: func[a b c][to-tuple reduce[a b c]]c: a/1 c/4: 1 d: c + 31
d/4: 1 d: d - 1 e: 1 + c/weekday % 7 if e = 0[e: 7]foreach
t[:Su:Mo:Tu:We:Th:Fr:Sa][prin pad pad/left t 6 10]h:
pad/with"-"71 #"-"print["^/"h]m: copy[]foreach[i b]a[put m z r:(t: e - 1)+
i/4 / 7 + 1 n: i/4 % 7 + t 2 b/1 t: split b/2" "l: 0
until[if t/2[if 10 >((length? t/1)+ length? t/2)[t/1:
rejoin reduce[t/1" "take next t]]]put m z r n 2 + l: l + 1 take t
tail? t]i: 0]n: k: 0 repeat v(g: e - 1 + d/4)/ 7 + sign? g % 7[repeat
r 5[repeat i 7[t: copy"|"if i = e[k: 1]if all[k = 1 r = 1 n < d/4][append t
n: n + 1]if s: select m z v i r[append t s]prin pad t 10]print"|"]print h]]

Cobalah online!

Lebih mudah dibaca:

func [ a ] [
    c: d: a/1
    c/4: d/4: 1
    d: d + 31
    d/4: 1
    d: d - 1
    e: 1 + c/weekday % 7
    if e = 0[e: 7]
    g: e - 1 + d/4
    w: g / 7 + sign? g % 7
    foreach t [ :Su :Mo :Tu :We :Th :Fr :Sa ] [
        prin pad pad/left t 6 10
    ]
    h: pad/with "-" 71 #"-"
    print[ "^/" h ]
    m: copy #()
    foreach[ i b ] a [
        n: i/4 % 7 + t: e - 1
        r: t + i/4 / 7 + 1
        put m to-tuple reduce[ r n 2 ] b/1
        t: split b/2" "
        i: 0
        until [
            if t/2 [ if 9 >= ((length? t/1) + (length? t/2)) [
                t/1: rejoin reduce[t/1" "take next t]
                ]
            ]
            put m to-tuple reduce [ r n 2 + i: i + 1 ] take t
            tail? t
        ]

    ]
    n: 0
    g: off
    repeat v w [
        repeat r 5 [
           repeat i 7 [
                t: copy "|"
                if i = e[ g: on ]
                if all [ g r = 1 n < d/4 ] [ append t n: n + 1 ]
                if s: select m to-tuple reduce [ v i r ]
                    [ append t s ]
                prin pad t 10
            ]
            print "|"
        ]
        print h
    ]
]
Galen Ivanov
sumber
if e = 0[e: 7]dapat dihapus, kan? Anda menggunakan e: 1 + c/weekday % 7, jadi eakan selalu berada dalam jangkauan [1, 7].
Kevin Cruijssen
@KevinCruijssen: Mungkin saya melewatkan sesuatu, tapi saya pikir saya membutuhkannya. Pengindeksan merah berbasis 1. Silakan lihat ini: >> c: sekarang / waktu / tanggal == 12-Oktober-2018 >> c: c + 1 == 13-Okt-2018 >> 1 + c / hari kerja% 7 == 0; >> 1 + 2 * 3 adalah 9 di Red, bukan 7
Galen Ivanov
1
EDIT: Ah, nvm .. 1 + Terjadi dulu .. Ok, saya melihat kesalahan saya. Saya sudah terbiasa %dan /lebih diutamakan dari operator +.
Kevin Cruijssen
1
@KevinCruijssen Ya, tepatnya. Tidak ada operator yang diutamakan dalam Merah, orang perlu menggunakan () sebagai gantinya
Galen Ivanov