ASCII Календарний планувальник


11

Враховуючи перелік заходів та час / дату їх початку, виведіть ASCII-графічний календар із зазначенням заходів у відповідні дні. Усі заходи гарантовано проводяться в одному місяці, два дні не будуть проводитися в один і той же день, і всі заходи гарантовано вписуються в поле календаря.

У верхньому лівому куті кожного вікна в календарі вказано дату, поля - 9 пробілів завширшки на 5 пробілів, оточені -і |. Двобуквенне абревіатура для дня тижня зосереджено вище першого ряду, а тижні починаються з неділі.

Наприклад, враховуючи такі види діяльності:

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

Виведіть цей відповідний календар:

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

Роз'яснення

  • Слова розкладу (відповідність [A-Za-z] +) буде розмежовано одним проміжком між ними (як у прикладі).
  • Розщеплення тексту на межі слів достатньо. Немає потреби в переносі слова.
  • Якщо лютий розпочнеться у неділю в неробочий рік, у вас буде лише чотири рядки календаря.
  • Якщо 31-денний місяць (наприклад, серпень) починається наприкінці тижня, можливо, доведеться вивести шість рядків календаря.

I / O та правила

  • Ваш код повинен обробляти дані по крайней мере , між 0001-01-01і 9999-12-31за григоріанським календарем, в тому числі і високосні роки , у відповідних випадках. Наприклад, якщо дано вхідний 2016-02-13 9:00am Testкалендар, вихідний календар повинен мати 29 лютого.
  • Формат дати введення може бути у будь-якому бажаному форматі. ISO 8601, datetimeоб'єкт, особливо відформатований рядок тощо. Аналіз вводу - не цікава частина цього завдання.
  • Введення та вихід можна будь-яким зручним способом .
  • Провідні / остаточні рядки чи інші пробіли необов’язкові, за умови, що символи розташовуються належним чином.
  • Прийнятна або повна програма, або функція. Якщо функція, ви можете повернути вихід, а не надрукувати його.
  • Вихід може бути на консолі, повернутий у вигляді списку рядків, повернутий як окремий рядок тощо.
  • Стандартні лазівки заборонені.
  • Це тому застосовуються всі звичайні правила гольфу, і найкоротший код (у байтах) виграє.

1.) Чи потрібно розділяти назви діяльності на межі слів? 2.) Коли у вас недільний рік лютого починається з неділі, у вас всього 4 ряди? 3.) Коли вам знадобиться 6 рядків, щоб показати місяць (наприклад, серпень, починаючи з суботи), що відбувається?
nedla2004

Пов'язані (простіше).
Арнольд

@ nedla2004 1) Так, межі слів будуть добре працювати. 2) Це правильно, 4 ряди. 3) У вашому календарі знадобиться 6 рядків. Я відредагую в уточненнях.
AdmBorkBork

@Arnauld Так, це справедливе припущення
AdmBorkBork

1
1752-09-02 - 09:00am - Wife's Birthday Tomorrow (14th!)
ngm

Відповіді:


10

JavaScript (ES8), 380321 320 байт

Вводиться як (y,m,e)де:

  • y є рік
  • m - місяць, індексований 0
  • e- це об'єкт, ключі якого - дні та значення якого - події у [hour, task]форматі
(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`)

Спробуйте в Інтернеті!

Як?

Нижче наведено кілька важливих частин коду.

Заголовок

Рядок заголовка генерується за допомогою:

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

Якщо split()використовується з регулярним виразом, що містить групу захоплення, ця група включається у вихідний масив. У цьому випадку він дає:

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

Ми поєднуємо цей масив з 4 пробілів, що веде до:

'    Su        Mo        Tu        We        Th        Fr        Sa    \n'

чого саме ми хочемо.

Місячна структура

Gymd

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

x

Форматування події

Наступний код використовується для форматування події.

[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

3

Python 2 , 326 324 315 312 307 байт

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

Спробуйте в Інтернеті!

Той самий вклад, що і відповідь Арнаульда JS :

Вводиться як (y,m,e)де:

  • y є рік
  • m - місяць, 1-індексований
  • e- це об'єкт, ключі якого - дні та значення якого - події у (hour, task)форматі

3

Вугілля деревне , 215 206 байт

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

Спробуйте в Інтернеті! Посилання на багатослівну версію коду. Дати приймає у форматі д / м / рік. Пояснення:

Sθ

Введіть першу подію.

≔I⪪§⪪θ ⁰/η

Витягніть дату і розділіть на /s.

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

Перетворюється на місяці з березня, 1 до н. Я хочу обчислити день тижня першого і наступного місяця, і поточного місяця, і працювати в місяцях простіше, ніж тримати окремі місяці та роки в кінці року, плюс це також дозволяє мені почати рахувати місяців, починаючи з березня замість січня, що вимагає конгрегенція Зеллера.

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

Використовуйте модифіковану конгрегенцію Зеллера для вилучення дня тижня першого дня наступного місяця та цього місяця. Основна частина спирається на той факт, що кількість днів з 30 жовтня попереднього року до 1-го числа зазначеного місяця, де m = 4за березень та m = 14січень наступного року за формулою визначається m * 153 / 5, однак ми можемо відняти 140, тому що ми лише дбайте про день тижня. Потім залишається вносити корективи через рік; кожен рік додає день, кожен 4-й рік додає додатковий день, кожен 100-й рік віднімає день, а кожен 400-й рік додає день знову. (Оскільки я працюю місяцями, ці значення помножуються на 12.) Швидше за все це прямо дає мені відповідь у терміні тижнів, що індексуються неділею (як правило, ви додасте день місяця і почнете рахувати суботу).

≔±⊟ηζ

Негатуйте день тижня і збережіть його як поточний день місяця.

≔⁺²⁸﹪⁺⊟ηζ⁷ε

Обчисліть кількість днів у місяці з дня тижня двох місяців.

⭆⪪SuMoTuWeThFrSa²◨◧ι⁶χ

Виведіть заголовки дня.

↓←⁷¹

Роздрукуйте верхній рядок -s.

W‹ζε«

Цикл до останнього дня місяця був виведений.

Перемістіть курсор на початок наступного ряду.

F⁷«

Обробляти за один раз 7 днів.

P↓⁵→

Роздрукуйте стовпчик |s ліворуч.

≦⊕ζ

Збільшення поточного дня місяця.

F⁼Iζ§⪪θ/⁰«

Якщо поточний день місяця - день поточної події, ...

≔⪪θ - θ

... витягніть інші частини події, ...

≔⟦ω◨§θ¹¦⁹⟧δ

... додайте час на 9 пробілів і збережіть його та порожній рядок як список, ...

F⪪⊟θ 

... розділіть опис на пробіли і петлі над ними, ...

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

... додавання кожного слова до попереднього слова, якщо воно підходить; ...

P⪫δ¶

... виведіть час та опис ( Pδне працює, може бути помилка деревного вугілля?), ...

Sθ»

... і введіть наступну подію.

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

Якщо поточний день місяця становить від 1 до останнього дня місяця, тоді виведіть його, інакше просто виведіть достатньо місця, щоб перейти на наступний день.

↓⁵←⁷¹

В кінці тижня надрукуйте правий стовпчик |s і нижній рядок -s.


Можливо, я пропустив це у вашому багатослівному коді TIO, але ви впевнені, що ваша конфігурація Zeller завершена? Це здається правильним для місяців березня по грудень, але для січня та лютого year-1слід використовувати замість yearі month+12використовувати їх замість month. Або ви якимось чином спростили алгоритм, про який я згадував у цій моїй відповіді 05AB1E, яка дорівнює тому, що йде з Вікіпедії ?
Kevin Cruijssen

@KevinCruijssen Це в основному чому я обчислюю кількість місяців з березня 1BC, але це занадто складно, щоб пояснити далі в коментарі.
Ніл

1
@KevinCruijssen я оновив своє пояснення; Я сподіваюся, що Ви вважаєте це корисним.
Ніл

Дякую! Це справді приємна модифікована формула, і я зараз розумію міркування, що стоять за нею. Дякую велике, що додали його до пояснення. +1 від мене.
Кевін Кройсейсен

2

Java (JDK) , 538 439 428 425 байт

Цілком можливо найдовше рішення Golf Golf, яке я коли-небудь публікував. Досі намагаюся гольфу це звідси, але це боротьба.

Вдалося зняти 99 байт, змінивши вхідний формат і використовуючи деякий синтаксичний аналіз, а ще 11 - з різних бітів.

3 зайвих байти завдяки Кевіну!

Отримуючи натхнення з інших відповідей, він вводить рядок, як рік, місяць та мапу днів до рядка, що відображає час та подію у форматі <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;}

Спробуйте в Інтернеті!


Безумовно

(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!
}

&&(i=1)<2?7:0можна ?7*(i=1):0зберегти 3 байти.
Кевін Кройсейсен

@KevinCruijssen Приємний спасибі!
Люк Стівенс

Запропонувати b>x|i++<6?0:7*(i=1)замість b<=x&++i>6?7*(i=1):0і c*i>1|b<1|b>x?c<2&e!=null?e.split("-")[i-2]:" ":b+""замістьc*i<2&b>0&b<=x?b+"":c<2&e!=null?e.split("-")[i-2]:" "
roofcat

1

Червоний , 674 651 байт

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]]

Спробуйте в Інтернеті!

Більш зрозумілі:

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
    ]
]

if e = 0[e: 7]можна зняти, правда? Ви використовуєте e: 1 + c/weekday % 7, так eзавжди буде в асортименті [1, 7].
Кевін Круїйсен

@KevinCruijssen: Можливо, мені щось не вистачає, але я думаю, що мені це потрібно. Червона індексація базується на 1. Погляньте на це: >> c: зараз / час / дата == 12-жовтень 2018 >> c: c + 1 == 13-жовтень 2018 >> 1 + c / будній день% 7 == 0; >> 1 + 2 * 3 - це 9 червоних, а не 7
Гален Іванов

1
EDIT: Ах, нвм .. Це 1 + відбувається спочатку .. Добре, я бачу свою помилку. Я звик %і /маю перевагу перед оператором +.
Кевін Круїйсен

1
@KevinCruijssen Так, саме так. У Червоному немає пріоритету оператора, замість цього потрібно використовувати ()
Гален Іванов
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.