ASCII-Kalenderplaner

11

Geben Sie anhand einer Liste der Aktivitäten und ihrer Startzeit / ihres Startdatums einen ASCII-Kunstkalender aus, in dem die Aktivitäten an den entsprechenden Tagen angezeigt werden. Es wird garantiert, dass alle Aktivitäten im selben Monat stattfinden, dass keine zwei Aktivitäten am selben Tag stattfinden und dass alle Aktivitäten garantiert in das Kalenderfeld passen.

Der Kalender hat das Datum in der oberen linken Ecke jeder Box. Die Boxen sind 9 Felder breit und 5 Felder hoch, umgeben von -und |. Die aus zwei Buchstaben bestehende Abkürzung für den Wochentag befindet sich über der ersten Zeile, und die Wochen beginnen mit dem Sonntag.

Zum Beispiel bei folgenden Aktivitäten:

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

Geben Sie diesen entsprechenden Kalender aus:

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

Klarstellungen

  • Die Zeitplanwörter (passend zu [A-Za-z] +) werden durch ein einzelnes Leerzeichen zwischen ihnen begrenzt (wie im Beispiel).
  • Das Aufteilen des Textes auf Wortgrenzen ist ausreichend. Keine Notwendigkeit, Wörter zu trennen.
  • Wenn der Februar an einem Sonntag in einem Nicht-Schaltjahr beginnt, haben Sie nur vier Kalenderzeilen.
  • Wenn ein 31-Tage-Monat (z. B. August) spät in der Woche beginnt, müssen Sie möglicherweise sechs Kalenderzeilen ausgeben.

E / A und Regeln

  • Ihr Code muss mindestens Daten zwischen 0001-01-01und 9999-12-31im Gregorianischen Kalender enthalten, einschließlich der Schaltjahre. Wenn beispielsweise eine Eingabe erfolgt 2016-02-13 9:00am Test, sollte der Ausgabekalender den 29. Februar haben.
  • Das eingegebene Datumsformat kann in einem beliebigen Format vorliegen. ISO 8601, ein datetimeObjekt, eine besonders formatierte Zeichenfolge usw. Das Parsen von Eingaben ist nicht der interessante Teil dieser Herausforderung.
  • Die Ein- und Ausgabe kann auf jede bequeme Weise erfolgen .
  • Führende / nachfolgende Zeilenumbrüche oder andere Leerzeichen sind optional, sofern die Zeichen entsprechend ausgerichtet sind.
  • Entweder ein vollständiges Programm oder eine Funktion sind akzeptabel. Wenn es sich um eine Funktion handelt, können Sie die Ausgabe zurückgeben, anstatt sie zu drucken.
  • Die Ausgabe kann an die Konsole erfolgen, als Liste von Zeichenfolgen, als einzelne Zeichenfolge usw. zurückgegeben werden.
  • Standardlücken sind verboten.
  • Dies ist daher gelten alle üblichen Golfregeln, und der kürzeste Code (in Bytes) gewinnt.
AdmBorkBork
quelle
1.) Müssen Sie die Aktivitätsnamen an den Wortgrenzen aufteilen? 2.) Wenn Sie einen Februar ohne Leapyear haben, der an einem Sonntag beginnt, haben Sie nur 4 Reihen? 3.) Wenn Sie 6 Zeilen benötigen, um den Monat anzuzeigen (z. B. August ab Samstag), was passiert dann?
nedla2004
Verwandte (einfacher).
Arnauld
@ nedla2004 1) Ja, Wortgrenzen funktionieren gut. 2) Das ist richtig, 4 Zeilen. 3) Ihr Kalender muss 6 Zeilen anzeigen. Ich werde in Klarstellungen bearbeiten.
AdmBorkBork
@Arnauld Ja, das ist eine faire Annahme
AdmBorkBork
1
1752-09-02 - 09:00am - Wife's Birthday Tomorrow (14th!)
ngm

Antworten:

10

JavaScript (ES8), 380321 320 Byte

Nimmt Eingabe als (y,m,e)wo:

  • y ist das Jahr
  • m ist der Monat, 0-indiziert
  • eist ein Objekt, dessen Schlüssel die Tage und dessen Werte die Ereignisse im [hour, task]Format sind
(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`)

Probieren Sie es online aus!

Wie?

Im Folgenden sind einige wichtige Teile des Codes aufgeführt.

Header

Die Kopfzeile wird generiert mit:

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

Wenn split()ein regulärer Ausdruck verwendet wird, der eine Erfassungsgruppe enthält, wird diese Gruppe in das Ausgabearray aufgenommen. In diesem Fall gibt es:

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

Wir verbinden dieses Array mit 4 Leerzeichen, was zu Folgendem führt:

'    Su        Mo        Tu        We        Th        Fr        Sa    \n'

Das ist genau das, was wir wollen.

Monatsstruktur

Die Hilfsfunktion ein Datum aus dem Eingabejahr und dem Eingabemonat (die konstant sind) und dem Tag (der dynamisch ist). Sein Parameter ist ein Methodenname, mit dem entweder der Wochentag oder der Monat extrahiert werden kann.Gymd

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

Es wird zuerst verwendet, um den Wochentag des ersten Tages des Monats zu identifizieren, damit wir von dort zum letzten Sonntag zurückkehren können. Es wird dann verwendet, um zu erkennen, wann wir den richtigen Monat zurückgeben und wann wir ihn verlassen (diese Informationen werden im Booleschen gespeichert ).x

Ereignisformatierung

Der folgende Code wird zum Formatieren eines Ereignisses verwendet.

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

Python 2 , 326 324 315 312 307 Bytes

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

Probieren Sie es online aus!

Gleiche Eingabe wie Arnauld's JS-Antwort :

Nimmt Eingabe als (y,m,e)wo:

  • y ist das Jahr
  • m ist der Monat, 1-indiziert
  • eist ein Objekt, dessen Schlüssel die Tage und dessen Werte die Ereignisse im (hour, task)Format sind
TFeld
quelle
3

Holzkohle , 215 206 Bytes

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

Probieren Sie es online aus! Der Link führt zur ausführlichen Version des Codes. Nimmt Daten im Format TT / M / JJJJ. Erläuterung:

Sθ

Geben Sie das erste Ereignis ein.

≔I⪪§⪪θ ⁰/η

Extrahieren Sie das Datum und teilen Sie es auf /s auf.

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

Umrechnung in Monate seit März 1 v. Ich möchte den Wochentag des ersten des nächsten Monats und des aktuellen Monats berechnen, und das Arbeiten in Monaten ist einfacher, als die Monate und Jahre getrennt zu halten und am Ende des Jahres zu tragen. Außerdem kann ich mit dem Zählen beginnen Monate ab März statt Januar, was nach Zellers Kongruenz erforderlich ist.

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

Verwenden Sie eine modifizierte Zellerkongruenz, um den Wochentag des ersten Tages des nächsten Monats und dieses Monats zu extrahieren. Der grundlegende Teil beruht auf der Tatsache, dass die Anzahl der Tage vom 30. Oktober des Vorjahres bis zum 1. eines bestimmten Monats, an denen m = 4für März und m = 14für Januar des folgenden Jahres angegeben wird, durch die Formel angegeben m * 153 / 5wird. Wir können jedoch 140 subtrahieren, weil wir nur kümmere dich um den Wochentag. Es bleiben dann Anpassungen aufgrund des Jahres vorzunehmen; Jedes Jahr fügt einen Tag hinzu, jedes 4. Jahr fügt einen zusätzlichen Tag hinzu, jedes 100. Jahr subtrahiert einen Tag und jedes 400. Jahr fügt wieder einen Tag hinzu. (Da ich in Monaten arbeite, werden diese Werte alle mit 12 multipliziert.) Praktischerweise gibt mir dies direkt die Antwort in Form einer sonntagsindizierten Woche (normalerweise würden Sie den Tag des Monats hinzufügen und am Samstag mit dem Zählen beginnen).

≔±⊟ηζ

Negieren Sie den Wochentag und speichern Sie ihn als aktuellen Tag des Monats.

≔⁺²⁸﹪⁺⊟ηζ⁷ε

Berechnen Sie die Anzahl der Tage im Monat ab dem Wochentag der beiden Monate.

⭆⪪SuMoTuWeThFrSa²◨◧ι⁶χ

Geben Sie die Tagesüberschriften aus.

↓←⁷¹

Drucken Sie die oberste Zeile von -s.

W‹ζε«

Schleife bis zum letzten Tag des Monats ausgegeben wurde.

Bewegen Sie den Cursor an den Anfang der nächsten Zeile.

F⁷«

7 Tage auf einmal verarbeiten.

P↓⁵→

Drucken Sie die Spalte von |s links aus.

≦⊕ζ

Erhöhen Sie den aktuellen Tag des Monats.

F⁼Iζ§⪪θ/⁰«

Wenn der aktuelle Tag des Monats der Tag des aktuellen Ereignisses ist, ...

≔⪪θ - θ

... die anderen Teile der Veranstaltung extrahieren, ...

≔⟦ω◨§θ¹¦⁹⟧δ

... die Zeit auf 9 Leerzeichen auffüllen und eine leere Zeichenfolge als Liste speichern, ...

F⪪⊟θ 

... die Beschreibung auf Leerzeichen aufteilen und diese durchlaufen, ...

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

... jedes Wort zum vorherigen Wort hinzufügen, wenn es passt; ...

P⪫δ¶

... Zeit und Beschreibung ausgeben ( Pδfunktioniert nicht, könnte ein Holzkohlefehler sein?), ...

Sθ»

... und geben Sie das nächste Ereignis ein.

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

Wenn der aktuelle Tag des Monats zwischen 1 und dem letzten Tag des Monats liegt, geben Sie ihn aus. Andernfalls geben Sie einfach genügend Leerzeichen aus, um zum nächsten Tag zu wechseln.

↓⁵←⁷¹

Drucken Sie am Ende der Woche die rechte Spalte von |s und die untere Zeile von -s.

Neil
quelle
Vielleicht habe ich es in Ihrem ausführlichen TIO-Code übersprungen, aber sind Sie sicher, dass die Kongruenzimplementierung Ihres Zeller abgeschlossen ist? Es scheint für die Monate März bis Dezember korrekt zu sein, aber für die Monate Januar und Februar year-1sollte anstelle von yearund month+12anstelle von verwendet werden month. Oder haben Sie den Algorithmus, den ich in meiner 05AB1E-Antwort erwähnt habe, irgendwie vereinfacht, der dem von Wikipedia entspricht ?
Kevin Cruijssen
@ KevinCruijssen Dies ist im Grunde der Grund, warum ich die Anzahl der Monate seit März 1 v. Chr. Berechne, aber es ist zu kompliziert, um dies in einem Kommentar weiter zu erläutern.
Neil
1
@ KevinCruijssen Ich habe meine Erklärung aktualisiert. Ich hoffe, Sie finden es hilfreich.
Neil
Vielen Dank! Das ist in der Tat eine schöne modifizierte Formel, und ich verstehe jetzt die Gründe dafür. Vielen Dank, dass Sie es der Erklärung hinzugefügt haben. +1 von mir.
Kevin Cruijssen
2

Java (JDK) , 538 439 428 425 Byte

Wahrscheinlich die längste Code Golf-Lösung, die ich je gepostet habe. Ich versuche immer noch, von hier aus Golf zu spielen, aber es ist ein Kampf.

Es gelang, 99 Bytes durch Ändern des Eingabeformats und Verwenden von Regex-Parsing und weitere 11 Bytes aus verschiedenen Bits zu entfernen.

3 zusätzliche Bytes dank Kevin!

Inspiriert von anderen Antworten werden Eingaben wie Jahr, Monat und Karte von Tagen in eine Zeichenfolge eingegeben, die die Zeit und das Ereignis im Format darstellt <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;}

Probieren Sie es online aus!


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!
}
Luke Stevens
quelle
&&(i=1)<2?7:0kann sein ?7*(i=1):0, 3 Bytes zu speichern.
Kevin Cruijssen
@ KevinCruijssen Schön, danke!
Luke Stevens
Schlagen Sie b>x|i++<6?0:7*(i=1)anstelle von b<=x&++i>6?7*(i=1):0und c*i>1|b<1|b>x?c<2&e!=null?e.split("-")[i-2]:" ":b+""anstelle vonc*i<2&b>0&b<=x?b+"":c<2&e!=null?e.split("-")[i-2]:" "
Deckenkatze
1

Rot , 674 651 Bytes

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

Probieren Sie es online aus!

Besser lesbar:

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
quelle
if e = 0[e: 7]kann entfernt werden, oder? Sie verwenden e: 1 + c/weekday % 7, ewird also immer im Bereich sein [1, 7].
Kevin Cruijssen
@ KevinCruijssen: Vielleicht fehlt mir etwas, aber ich denke, dass ich es brauche. Die rote Indizierung basiert auf 1. Bitte sehen Sie sich das an: >> c: now / time / date == 12-Okt-2018 >> c: c + 1 == 13-Okt-2018 >> 1 + c / Wochentag% 7 == 0; >> 1 + 2 * 3 ist 9 in Rot, nicht 7
Galen Ivanov
1
EDIT: Ah, nvm .. Das 1 + passiert zuerst .. Ok, ich sehe meinen Fehler. Ich bin es gewohnt %und habe /Vorrang vor Operatoren +.
Kevin Cruijssen
1
@ KevinCruijssen Ja genau. Es gibt keine Operator-Priorität in Rot, man muss stattdessen () verwenden
Galen Ivanov