ASCII 캘린더 플래너


11

활동 목록과 시작 시간 / 날짜가 주어지면 해당 날짜의 활동을 보여주는 ASCII 아트 달력을 출력하십시오. 모든 활동은 같은 달에 보장되며 같은 날에는 두 가지 활동이 없으며 모든 활동은 달력 상자에 맞도록 보장됩니다.

달력은 각 상자의 왼쪽 상단 모서리에있는 날짜가, 상자에 의해 둘러싸여 키가 5 개 공간 너비 9 개 공간입니다 -및이 |. 요일의 두 문자 약어는 첫 번째 행 위에 있으며주는 일요일로 시작합니다.

예를 들어 다음과 같은 활동이 있습니다.

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] +와 일치)는 그들 사이의 단일 공백으로 구분됩니다 (예와 같이).
  • 단어 경계에서 텍스트를 분할하면 충분합니다. 하이픈을 넣을 필요가 없습니다.
  • 윤년이 아닌 일요일에 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 월이 아닌 2 월이 일요일에 시작하는 경우 4 행만 있습니까? 3.) 달 (토요일에 시작하는 8 월)을 표시하기 위해 6 개의 행이 필요한 경우 어떻게됩니까?
nedla2004

관련성 (쉽게).
Arnauld

@ nedla2004 1) 그렇습니다. 단어 경계는 잘 작동합니다. 2) 맞습니다, 4 행. 3) 캘린더에 6 개의 행이 표시되어야합니다. 명확하게 편집하겠습니다.
AdmBorkBork

@Arnauld 예, 그것은 공정한 가정입니다
AdmBorkBork

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

답변:


10

자바 스크립트 (ES8), 380 ... 321 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'

정확히 우리가 원하는 것입니다.

월 구조

와이미디엄

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

엑스

이벤트 형식

다음 코드는 이벤트를 형식화하는 데 사용됩니다.

[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

파이썬 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

온라인으로 사용해보십시오!

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로 나누십시오 .

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

BC 1 월 3 일 이후의 달로 변환합니다. 다음 달과 현재 달의 첫 번째 요일을 계산하고 싶습니다. 월과 연도를 분리하여 유지하고 연말에 옮기는 것보다 몇 달 동안 일하는 것이 더 쉬우 며, 또한 계산을 시작할 수 있습니다 1 월이 아닌 3 월에 시작하는 달. Zeller의 합의에 필요합니다.

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

다음 달의 첫 번째 요일과 이번 달의 요일을 추출하려면 수정 된 Zeller의 일치를 사용하십시오. 기본적인 부분은 특정 달의 1 일에 이전 해 10 월 30 일부터 일 수 있다는 사실에 의존 m = 4월과 m = 14다음 해 1 월이 공식에 의해 주어진다 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의 일치 구현이 완료 되었습니까? 3 월부터 12 월까지는 올바른 것 같지만 1 월과 2 월 year-1은 대신 사용해야 year하고 대신 month+12사용해야합니다 month. 아니면 이 05AB1E 답변에서 언급 한 알고리즘을 Wikipedia 의 알고리즘 과 동일하게 단순화 했습니까?
Kevin Cruijssen

@KevinCruijssen 이것이 기본적으로 1BC 년 3 월 이후의 개월 수를 계산하는 이유이지만 의견을 더 자세히 설명하기에는 너무 복잡합니다.
Neil

1
@KevinCruijssen 내 설명을 업데이트했습니다. 도움이 되셨기를 바랍니다.
Neil

감사! 그것은 참으로 훌륭한 수정 된 공식이며, 이제 그 이유를 이해합니다. 설명에 추가해 주셔서 감사합니다. 나에게서 +1
Kevin Cruijssen

2

자바 (JDK) , 538 439 428 425 바이트

내가 게시 한 가장 긴 코드 골프 솔루션 일 것입니다. 아직도 여기에서 골프를 치려고하지만 어려움이 있습니다.

입력 형식을 변경하고 일부 정규식 구문 분석을 사용하고 기타 비트에서 다른 11을 사용하여 99 바이트를 차단했습니다.

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 바이트를 절약 할 수 있습니다 .
Kevin Cruijssen

@KevinCruijssen 멋진 감사합니다!
Luke Stevens

제안 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]:" "
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]있습니다.
Kevin Cruijssen

@KevinCruijssen : 어쩌면 뭔가 빠졌을 수도 있지만 필요하다고 생각합니다. 빨간색 인덱싱은 1 기반입니다. >> c : now / time / date == 2018 년 10 월 12 일 >> c : c + 1 == 2018 년 10 월 13 일 >> 1 + c / 평일 % 7 == 0; >> 1 + 2 * 3은 7이 아닌 빨간색으로 9입니다
Galen Ivanov

1
편집 : 아, nvm .. 1 + 먼저 발생합니다. 좋아, 내 오류가 나타납니다. 나는에 익숙 %하고 /이상 연산자 우선 순위를 가진 +.
Kevin Cruijssen

1
@KevinCruijssen 그렇습니다. Red에는 연산자 우선 순위가 없으므로 대신 ()을 사용해야합니다.
Galen Ivanov
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.