ASCIIカレンダープランナー


11

アクティビティのリストとその開始時刻/日付を指定して、適切な日のアクティビティを示すASCIIアートカレンダーを出力します。すべてのアクティビティは同じ月に行われることが保証され、同じ日に2つのアクティビティが行われることはありません。また、すべてのアクティビティはカレンダーボックスに収まることが保証されます。

カレンダーの日付は各ボックスの左上隅にあり、ボックスは幅9スペース、高さ5スペースで、で囲まれ-てい|ます。曜日の2文字の略語は最初の行の上に中央揃えされ、週は日曜日から始まります。

たとえば、次のアクティビティがあるとします。

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] +に一致)は、それらの間に1つのスペースで区切られます(例のように)。
  • 単語の境界でテキストを分割するだけで十分です。単語をハイフネーションする必要はありません。
  • 2月がうるう年以外の日曜日に始まる場合、カレンダー行は4つしかありません。
  • 31日間の月(8月など)が週の後半に始まる場合、6行のカレンダー行を出力する必要があります。

I / Oとルール

  • あなたのコードは、間に少なくとも日付を処理しなければならない0001-01-01し、9999-12-31必要に応じて、うるう年を含め、グレゴリオ暦で。たとえば、inputを指定した場合2016-02-13 9:00am Test、出力カレンダーには2月29日が必要です。
  • 入力日付形式は任意の形式にすることができます。ISO 8601、datetimeオブジェクト、特にフォーマットされた文字列など。入力の解析は、この課題の興味深い部分ではありません。
  • 入力と出力は、任意の便利な方法で行うことができます。
  • 文字が適切に整列している場合、先頭または末尾の改行またはその他の空白はオプションです。
  • 完全なプログラムまたは機能のいずれかが受け入れられます。関数の場合、出力する代わりに出力を返すことができます。
  • コンソールへの出力、文字列のリストとして返される、単一の文字列として返されるなど。
  • 標準的な抜け穴は禁止されています。
  • これはので、通常のゴルフルールがすべて適用され、最短のコード(バイト単位)が勝ちます。

1.)単語の境界でアクティビティ名を分割する必要がありますか?2.)日曜日から始まるうるう年以外の2月がある場合、4行しかありませんか?3.)月を表示するために6行(例:土曜日から始まる8月)が必要な場合はどうなりますか?
-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

パイソン2326の 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

オンラインでお試しください!

ArnauldのJS回答と同じ入力:

入力(y,m,e)は次のとおりです。

  • y 年です
  • m 1から始まる月
  • eキーが日であり、値が(hour, task)形式のイベントであるオブジェクトです

3

215206バイト

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

オンラインでお試しください!リンクは、コードの詳細バージョンです。d / m / yyyy形式の日付を取ります。説明:

Sθ

最初のイベントを入力します。

≔I⪪§⪪θ ⁰/η

日付を抽出し、/s で分割します。

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

紀元前1月3月以降の月に変換します。来月と今月の両方の最初の曜日を計算したいのですが、月と年を分けて年末に運ぶよりも月で作業する方が簡単ですZellerの合同により要求される1月ではなく3月から始まる月。

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

変更されたZellerの一致を使用して、来月と今月の最初の日の曜日を抽出します。基本的な部分は、前年の10月30日から特定の月の1日までの日数でありm = 4、3月とm = 14翌年の1月は式m * 153 / 5で与えられるという事実に依存していますが、曜日を気にします。その後、年度に応じて調整する必要があります。1年ごとに1日、4年ごとに1日、100年ごとに1日、400年ごとに1日がそれぞれ追加されます。(私は月で作業しているので、これらの値はすべて12で乗算されます。)むしろ都合よく、これは日曜日をインデックスとする週の観点から直接答えを与えます(通常、月の日を追加して土曜日にカウントを開始します)。

≔±⊟ηζ

曜日を無効にして、現在の日付として保存します。

≔⁺²⁸﹪⁺⊟ηζ⁷ε

2か月の曜日から月の日数を計算します。

⭆⪪SuMoTuWeThFrSa²◨◧ι⁶χ

日ヘッダーを出力します。

↓←⁷¹

-sの一番上の行を印刷します。

W‹ζε«

月の最後の日が出力されるまでループします。

カーソルを次の行の先頭に移動します。

F⁷«

一度に7日間処理します。

P↓⁵→

|s の列を左に印刷します。

≦⊕ζ

月の現在の日付を増やします。

F⁼Iζ§⪪θ/⁰«

月の現在の日が現在のイベントの日である場合、...

≔⪪θ - θ

...イベントの他の部分を抽出し、...

≔⟦ω◨§θ¹¦⁹⟧δ

...時間を9個のスペースに埋め込み、空の文字列をリストとして保存します...

F⪪⊟θ 

...スペースの説明を分割し、ループします...

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

...適合する場合は、前の単語に各単語を追加します。...

P⪫δ¶

...時間と説明を出力します(Pδ機能しない、炭のバグかもしれません)、...

Sθ»

...そして次のイベントを入力します。

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

月の現在の日が1から月の最後の日までの場合は出力します。そうでない場合は、翌日に移動するのに十分なスペースを出力します。

↓⁵←⁷¹

週の終わりに、|sの右の列とsの一番下の行を印刷します-


あなたの詳細なTIOコードでそれをスキップしたのかもしれませんが、Zellerの合同実装は完了していますか?12月を通してヶ月3月の正しいように見えますが、数ヶ月のために1月と2月には、year-1代わりに使用すべきであるyearmonth+12の代わりに使用する必要がありますmonth。または、ウィキペディアのものと等しい私の私のこの05AB1E回答で言及たアルゴリズムを何らかの形で単純化しましたか?
ケビンCruijssen

@KevinCruijssenこれは基本的に、1BCの3月以降の月数を計算する理由ですが、コメントでさらに説明するには複雑すぎます。
ニール

1
@KevinCruijssen説明を更新しました。お役に立てば幸いです。
ニール

ありがとう!それは本当に素晴らしい修正された式であり、今ではその背後にある理由を理解しています。説明に追加してくれてありがとう。私から+1。
ケビンクルーッセン

2

Java(JDK)538 439 428 425バイト

私がこれまでに投稿した中で最も長いCode Golfソリューション。ここからゴルフをしようとしていますが、それは苦労です。

入力フォーマットを変更し、いくつかの正規表現解析を使用することで99バイト、その他のビットから11バイトを取り除いた。

Kevinのおかげで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):03バイトを節約することができます。
ケビンクルーッセン

@KevinCruijssen素敵な方ありがとうございます!
ルークスティーブンス

提案b>x|i++<6?0:7*(i=1)の代わりb<=x&++i>6?7*(i=1):0c*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]:" "
ceilingcat

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:now / time / date == 12-Oct-2018 >> c:c + 1 == 13-Oct-2018 >> 1 + c / weekday%7 == 0; >> 1 + 2 * 3は赤では9で、7ではありません
ガレンイワノフ

1
編集:ああ、nvm.。1 + 最初に起こる.. OK、エラーが表示されます。私は慣れて%おり/、演算子よりも優先され+ます。
ケビンCruijssen

1
@KevinCruijssenはい、正確に。レッドには演算子の優先順位、使用への1つのニーズは、(代わりに)ありません
ガレン・イワノフ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.