Calendario ASCII


11

Dato un elenco di attività e la loro data / ora di inizio, emette un calendario di arte ASCII che mostra le attività nei giorni appropriati. Tutte le attività sono garantite nello stesso mese, non ci saranno due attività nello stesso giorno e tutte le attività sono garantite per rientrare nella casella del calendario.

Il calendario ha la data nell'angolo in alto a sinistra di ogni riquadro, le caselle sono larghe 9 spazi per 5 alte, circondate da -e |. L'abbreviazione di due lettere per il giorno della settimana è centrata sopra la prima riga e le settimane iniziano con domenica.

Ad esempio, date le seguenti attività:

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

Stampa questo calendario corrispondente:

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

chiarimenti

  • Le parole del programma (corrispondenti a [A-Za-z] +) saranno delimitate da un singolo spazio tra loro (come nell'esempio).
  • Dividere il testo sui confini delle parole è sufficiente. Non c'è bisogno di parole sillabanti.
  • Se febbraio inizia di domenica in un anno non bisestile, avrai solo quattro righe di calendario.
  • Se un mese di 31 giorni (ad es. Agosto) inizia alla fine della settimana, potrebbe essere necessario generare sei righe di calendario.

I / O e regole

  • Il codice deve gestire le date almeno tra 0001-01-01e 9999-12-31nel calendario gregoriano, compresi gli anni bisestili, a seconda dei casi. Ad esempio, se viene fornito un input 2016-02-13 9:00am Test, il calendario di output dovrebbe avere il 29 febbraio.
  • Il formato della data di input può essere in qualsiasi formato desiderato. ISO 8601, un datetimeoggetto, una stringa particolarmente formattata, ecc. L'analisi dell'input non è la parte interessante di questa sfida.
  • Ingresso e uscita possono essere con qualsiasi metodo conveniente .
  • Le linee guida iniziali / finali o altri spazi bianchi sono opzionali, a condizione che i caratteri siano allineati in modo appropriato.
  • È accettabile un programma completo o una funzione. Se una funzione, è possibile restituire l'output anziché stamparlo.
  • L'output può essere sulla console, restituito come un elenco di stringhe, restituito come singola stringa, ecc.
  • Sono vietate le scappatoie standard .
  • Si tratta di quindi si applicano tutte le normali regole del golf e vince il codice più breve (in byte).

1.) Devi dividere i nomi delle attività sui limiti delle parole? 2.) Quando hai un febbraio non bisestile a partire da una domenica, hai solo 4 file? 3.) Quando occorrono 6 righe per mostrare il mese (es. Agosto a partire da sabato) cosa succede?
nedla2004,

Correlato (più semplice).
Arnauld,

@ nedla2004 1) Sì, i confini delle parole funzioneranno bene. 2) È corretto, 4 file. 3) Il tuo calendario dovrà mostrare 6 righe. Modificherò in chiarimenti.
AdmBorkBork,

@Arnauld Sì, è un presupposto giusto
AdmBorkBork,

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

Risposte:


10

JavaScript (ES8), 380321 320 byte

Accetta input come (y,m,e)dove:

  • y è l'anno
  • m è il mese, indicizzato 0
  • eè un oggetto le cui chiavi sono i giorni e i cui valori sono gli eventi in [hour, task]formato
(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`)

Provalo online!

Come?

Di seguito sono riportate alcune parti importanti del codice.

Intestazione

La riga di intestazione viene generata con:

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

Quando split()viene utilizzato con un'espressione regolare contenente un gruppo di acquisizione, questo gruppo è incluso nell'array di output. In questo caso, fornisce:

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

Uniamo questo array con 4 spazi, portando a:

'    Su        Mo        Tu        We        Th        Fr        Sa    \n'

che è esattamente quello che vogliamo.

Struttura mensile

Gymd

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

x

Formattazione degli eventi

Il seguente codice viene utilizzato per formattare un evento.

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

Provalo online!

Stesso input della risposta JS di Arnauld :

Accetta input come (y,m,e)dove:

  • y è l'anno
  • m è il mese, 1 indicizzato
  • eè un oggetto le cui chiavi sono i giorni e i cui valori sono gli eventi in (hour, task)formato

3

Carbone , 215 206 byte

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

Provalo online! Il collegamento è alla versione dettagliata del codice. Accetta le date nel formato gg / m / aaaa. Spiegazione:

Sθ

Inserisci il primo evento.

≔I⪪§⪪θ ⁰/η

Estrarre la data e dividere su /s.

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

Converti in mesi dal 1 marzo a.C. Voglio calcolare il giorno della settimana del primo sia del mese successivo sia del mese corrente, e lavorare in mesi è più facile che tenere separati i mesi e gli anni e portarli alla fine dell'anno, inoltre mi permette anche di iniziare a contare mesi che iniziano a marzo anziché a gennaio, come richiesto dalla congruenza di Zeller.

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

Usa una congruenza di Zeller modificata per estrarre il giorno della settimana del primo giorno del mese successivo e di questo mese. La parte di base si basa sul fatto che il numero di giorni dal 30 ottobre dell'anno precedente al 1 di un determinato mese in cui m = 4per marzo e m = 14per gennaio dell'anno successivo è dato dalla formula m * 153 / 5, tuttavia possiamo sottrarre 140 perché possiamo solo preoccupati per il giorno della settimana. Resta quindi da apportare rettifiche dovute all'anno; ogni anno aggiunge un giorno, ogni 4 ° anno aggiunge un giorno in più, ogni 100 ° anno viene sottratto al giorno e ogni 400 ° anno aggiunge di nuovo un giorno. (Dato che lavoro da mesi, tutti questi valori vengono moltiplicati per 12.) Piuttosto convenientemente questo mi dà direttamente la risposta in termini di una settimana indicizzata domenica (normalmente aggiungeresti il ​​giorno del mese e inizierai a contare il sabato).

≔±⊟ηζ

Annulla il giorno della settimana e salvalo come giorno corrente del mese.

≔⁺²⁸﹪⁺⊟ηζ⁷ε

Calcola il numero di giorni del mese dal giorno della settimana dei due mesi.

⭆⪪SuMoTuWeThFrSa²◨◧ι⁶χ

Stampa le intestazioni del giorno.

↓←⁷¹

Stampa la riga superiore di -s.

W‹ζε«

Ripeti fino all'ultimo giorno del mese in uscita.

Sposta il cursore all'inizio della riga successiva.

F⁷«

Elaborazione 7 giorni alla volta.

P↓⁵→

Stampa la colonna di |s a sinistra.

≦⊕ζ

Incrementa il giorno corrente del mese.

F⁼Iζ§⪪θ/⁰«

Se il giorno corrente del mese è il giorno dell'evento corrente, ...

≔⪪θ - θ

... estrai le altre parti dell'evento, ...

≔⟦ω◨§θ¹¦⁹⟧δ

... pad il tempo a 9 spazi e salvarlo e una stringa vuota come un elenco, ...

F⪪⊟θ 

... dividere la descrizione sugli spazi e passarci sopra, ...

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

... aggiungendo ogni parola alla parola precedente se si adatta; ...

P⪫δ¶

... visualizza l'ora e la descrizione ( Pδnon funziona, potrebbe trattarsi di un bug di carbone?), ...

Sθ»

... e inserisci il prossimo evento.

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

Se il giorno corrente del mese è compreso tra 1 e l'ultimo giorno del mese, quindi emettilo, altrimenti emetti abbastanza spazi per passare al giorno successivo.

↓⁵←⁷¹

Alla fine della settimana, stampa la colonna destra di se |la riga inferiore di -s.


Forse l'ho ignorato nel tuo dettagliato codice TIO, ma sei sicuro che l'implementazione della congruenza di Zeller sia completa? Sembra essere corretto per i mesi da marzo a dicembre, ma per i mesi gennaio e febbraio year-1dovrebbero essere usati al posto yeare month+12dovrebbero essere usati al posto di month. O hai in qualche modo semplificato l'algoritmo che ho citato in questa mia risposta 05AB1E che è uguale a quella di Wikipedia ?
Kevin Cruijssen,

@KevinCruijssen Questo è fondamentalmente il motivo per cui calcolo il numero di mesi da marzo 1BC, ma è troppo complicato per spiegare ulteriormente in un commento.
Neil,

1
@KevinCruijssen Ho aggiornato la mia spiegazione; Spero che lo trovi utile.
Neil,

Grazie! Questa è davvero una bella formula modificata, e ora capisco il ragionamento alla base. Grazie mille per averlo aggiunto alla spiegazione. +1 da me.
Kevin Cruijssen,

2

Java (JDK) , 538 439 428 425 byte

Probabilmente la soluzione Code Golf più lunga che abbia mai pubblicato. Sto ancora cercando di giocare a golf da qui, ma è una lotta.

Riesce a eliminare 99 byte modificando il formato di input e utilizzando un regex parsing e altri 11 da bit vari.

3 byte extra di sconto grazie a Kevin!

Prendendo ispirazione da altre risposte, ci vogliono input come l'anno, il mese e una mappa dei giorni in una stringa che rappresenta l'ora e l'evento nel formato <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;}

Provalo online!


Ungolfed

(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:0può essere ?7*(i=1):0per salvare 3 byte.
Kevin Cruijssen,

@KevinCruijssen Bello grazie!
Luke Stevens,

Suggerisci b>x|i++<6?0:7*(i=1)invece b<=x&++i>6?7*(i=1):0e c*i>1|b<1|b>x?c<2&e!=null?e.split("-")[i-2]:" ":b+""invece dic*i<2&b>0&b<=x?b+"":c<2&e!=null?e.split("-")[i-2]:" "
ceilingcat il

1

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

Provalo online!

Più leggibile:

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]può essere rimosso, giusto? Usi e: 1 + c/weekday % 7, quindi esarà sempre nell'intervallo [1, 7].
Kevin Cruijssen,

@KevinCruijssen: Forse mi manca qualcosa, ma penso di averne bisogno. L'indicizzazione rossa è basata su 1. Dai un'occhiata a questo: >> c: ora / ora / data == 12-ott-2018 >> c: c + 1 == 13-ott-2018 >> 1 + c / giorno della settimana% 7 == 0; >> 1 + 2 * 3 è 9 in rosso, non 7
Galen Ivanov,

1
EDIT: Ah, nvm .. 1 + Succede prima .. Ok, vedo il mio errore. Sono abituato %e ho la /precedenza dell'operatore +.
Kevin Cruijssen,

1
@KevinCruijssen Sì, esattamente. Non c'è precedenza per l'operatore in Red, bisogna invece usare () invece
Galen Ivanov il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.