Calendar: Difference between revisions

From Rosetta Code
Content added Content deleted
m (→‎[[Calendar#ALGOL 68]]: rename some varaibles...)
m (→‎[[Calendar#ALGOL 68]]: centered some headings)
Line 11: Line 11:
For economy of size, do not actually include Snoopy generation in either the code or the output, instead just output a place-holder.
For economy of size, do not actually include Snoopy generation in either the code or the output, instead just output a place-holder.
=={{header|ALGOL 68}}==
=={{header|ALGOL 68}}==
{{works with|ALGOL 68|Revision 1 - no extensions to language used}}
{{works with|ALGOL 68G|Any - tested with release [http://sourceforge.net/projects/algol68/files/algol68g/algol68g-1.18.0/algol68g-1.18.0-9h.tiny.el5.centos.fc11.i386.rpm/download 1.18.0-9h.tiny].}}
{{works with|ALGOL 68G|Any - tested with release [http://sourceforge.net/projects/algol68/files/algol68g/algol68g-1.18.0/algol68g-1.18.0-9h.tiny.el5.centos.fc11.i386.rpm/download 1.18.0-9h.tiny].}}
{{wont work with|ELLA ALGOL 68|Any (with appropriate job cards) - tested with release [http://sourceforge.net/projects/algol68/files/algol68toc/algol68toc-1.8.8d/algol68toc-1.8-8d.fc9.i386.rpm/download 1.8-8d] - due to extensive use of '''format'''[ted] ''transput''.}}
{{wont work with|ELLA ALGOL 68|Any (with appropriate job cards) - tested with release [http://sourceforge.net/projects/algol68/files/algol68toc/algol68toc-1.8.8d/algol68toc-1.8-8d.fc9.i386.rpm/download 1.8-8d] - due to extensive use of '''format'''[ted] ''transput''.}}
Line 26: Line 27:
MODE WINDOW = STRUCT(SLICE line, char);
MODE WINDOW = STRUCT(SLICE line, char);
# Juggle the calendar format to fit the screen #
# Juggle the calendar format to fit the printer/screen width #
INT day chars = 2, day gap=1;
INT day chars = 2, day gap=1;
INT month chars = (UPB weekday names[1]+1) * UPB weekday names-1;
INT month chars = (UPB weekday names[1]+1) * UPB weekday names-1;
Line 68: Line 69:


# center the title #
# center the title #
sputf(month box[1,(month chars - UPB month name ) OVER 2:], ($g$, month name));
sputf(month box[1,(month chars - UPB month name ) OVER 2+1:], ($g$, month name));
sputf(month box[2,], (weekday fmt, weekday names));
sputf(month box[2,], (weekday fmt, weekday names));


Line 107: Line 108:


printf((
printf((
$n(center - 10)k g l$, "[Insert Snoopy here]",
$n(center - 9)k g l$, "[Insert Snoopy here]",
$n(center - 2)k 4d l$, year, $l$,
$n(center - 1)k 4d l$, year, $l$,
$n(2 UPB LOC YEARBOX)(g)l$, year repr(year)
$n(2 UPB LOC YEARBOX)(g)l$, year repr(year)
))
))
Line 126: Line 127:
Output:
Output:
<pre>
<pre>
[Insert Snoopy here]
[Insert Snoopy here]
1969
1969


January February March April May June
January February March April May June
Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
1 2 3 4 1 1 1 2 3 4 5 1 2 3 1 2 3 4 5 6 7
1 2 3 4 1 1 1 2 3 4 5 1 2 3 1 2 3 4 5 6 7
Line 137: Line 138:
26 27 28 29 30 31 23 24 25 26 27 28 23 24 25 26 27 28 29 27 28 29 30 25 26 27 28 29 30 31 29 30
26 27 28 29 30 31 23 24 25 26 27 28 23 24 25 26 27 28 29 27 28 29 30 25 26 27 28 29 30 31 29 30
30 31
30 31
July August September October November December
July August September October November December
Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
1 2 3 4 5 1 2 1 2 3 4 5 6 1 2 3 4 1 1 2 3 4 5 6
1 2 3 4 5 1 2 1 2 3 4 5 6 1 2 3 4 1 1 2 3 4 5 6
Line 144: Line 145:
20 21 22 23 24 25 26 17 18 19 20 21 22 23 21 22 23 24 25 26 27 19 20 21 22 23 24 25 16 17 18 19 20 21 22 21 22 23 24 25 26 27
20 21 22 23 24 25 26 17 18 19 20 21 22 23 21 22 23 24 25 26 27 19 20 21 22 23 24 25 16 17 18 19 20 21 22 21 22 23 24 25 26 27
27 28 29 30 31 24 25 26 27 28 29 30 28 29 30 26 27 28 29 30 31 23 24 25 26 27 28 29 28 29 30 31
27 28 29 30 31 24 25 26 27 28 29 30 28 29 30 26 27 28 29 30 31 23 24 25 26 27 28 29 28 29 30 31
31 30
31 30
</pre>
</pre>
[[Category:Date and time]]
[[Category:Date and time]]

Revision as of 07:25, 30 May 2011

Task
Calendar
You are encouraged to solve this task according to the task description, using any language you may know.

Create a routine that will generate an ASCII calendar for any date. Test the calendar by generating a calendar for the year 1969 on a line printer of the time with a width of 132 characters.

Ideally the program will generate well formatted calendars for any page width from 20 characters up.

Kudos (κῦδος) for routines that also correctly transition from Julian to Gregorian calendar in September 1752.

This task is inspired by Real Programmers Don't Use PASCAL by Ed Post, Datamation, volume 29 number 7, July 1983.

THE REAL PROGRAMMER'S NATURAL HABITAT
"Taped to the wall is a line-printer Snoopy calender for the year 1969."

For economy of size, do not actually include Snoopy generation in either the code or the output, instead just output a place-holder.

ALGOL 68

Works with: ALGOL 68 version Revision 1 - no extensions to language used
Works with: ALGOL 68G version Any - tested with release 1.18.0-9h.tiny.

<lang algol68>#!/usr/local/bin/a68g --script #

PROC print calendar = (INT year, max width)VOID: (

 []STRING month names = (
     "January","February","March","April","May","June",
     "July","August","September","October","November","December"),
   weekday names = ("Su","Mo","Tu","We","Th","Fr","Sa");
 FORMAT weekday fmt = $g,n(UPB weekday names - LWB weekday names)(" "g)$;
 
 MODE SLICE = STRUCT(INT lwb, upb);
 MODE WINDOW = STRUCT(SLICE line, char);
 
 # Juggle the calendar format to fit the printer/screen width #
 INT day chars = 2, day gap=1;
 INT month chars = (UPB weekday names[1]+1) * UPB weekday names-1;
 INT month lines = (31 OVER UPB weekday names+4); # 4 extra lines for title plue head/tail weeks #
 INT year cols = (max width+1) OVER (month chars+1);
 INT year rows = (UPB month names-1)OVER year cols + 1;
 INT month gap = ( year cols NE 1 | (max width - year cols*month chars)OVER (year cols-1) | 0 );
 
 MODE MONTHBOX = [month lines, month chars] CHAR;
 MODE YEARBOX = [year rows*month lines, year cols*(month chars+month gap)-month gap#-1#]CHAR;
 
 INT week start = 1; # Sunday #
 
 PROC days in month = (INT year, month)INT:
   CASE month IN 31,
     IF year MOD 4 EQ 0 AND year MOD 100 NE 0 OR year MOD 400 EQ 0 THEN 29 ELSE 28 FI,
     31, 30, 31, 30, 31, 31, 30, 31, 30, 31
   ESAC;
 
 PROC day of week = (INT year, month, day) INT: (
   # Day of the week by Zeller’s Congruence algorithm from 1887 #
   INT y := year, m := month, d := day, c;
   IF m <= 2 THEN m +:= 12; y -:= 1 FI;
   c := y OVER 100;
   y %*:= 100;
   (d - 1 + ((m + 1) * 26) OVER 10 + y + y OVER 4 + c OVER 4 - 2 * c) MOD 7
 );
 
 MODE SIMPLEOUT = [0]UNION(FORMAT, STRING, []STRING, INT, []INT);
 
 PROC sputf = (REF[]CHAR out, SIMPLEOUT argv)VOID:(
   FILE f; STRING s; associate(f,s);
   putf(f, (argv[1],argv[2]));
   out[:UPB s]:=s;
   close(f)
 );
 
 PROC month repr = (INT year, month)MONTHBOX:(
   MONTHBOX month box; FOR line TO UPB month box DO month box[line,]:=" "* 2 UPB month box OD;
   STRING month name = month names[month];
 # center the title #
   sputf(month box[1,(month chars - UPB month name ) OVER 2+1:], ($g$, month name));
   sputf(month box[2,], (weekday fmt, weekday names));
   INT first day := day of week(year, month, 1);
   FOR day TO days in month(year, month) DO
     INT line = (day+first day-week start) OVER UPB weekday names + 3;
     INT char =((day+first day-week start) MOD UPB weekday names)*(day chars+day gap) + 1;
     sputf(month box[line,char:char+day chars-1],($g(-day chars)$, day))
   OD;
   month box
 );
 
 PROC year repr = (INT year)YEARBOX:(
   YEARBOX year box; 
   FOR line TO UPB year box DO year box[line,]:=" "* 2 UPB year box OD;
   FOR month row FROM 0 TO year rows-1 DO
     FOR month col FROM 0 TO year cols-1 DO
       INT month = month row * year cols + month col + 1;
       IF month > UPB month names THEN
         done
       ELSE
         INT month width = month chars+month gap;
         WINDOW box = (
           (month row*month lines+1, (month row+1)*month lines),
           (month col*month width+1, (month col+1)*month width-month gap)
         );
         year box[
           lwb OF line OF box:upb OF line OF box,
           lwb OF char OF box:upb OF char OF box
         ]:= month repr(year, month)
       FI
     OD
   OD;
   done: year box
 );
 INT center = (year cols * (month chars+month gap) - month gap ) OVER 2;
 printf((
   $n(center - 9)k g l$, "[Insert Snoopy here]",
   $n(center - 1)k 4d l$, year, $l$,
   $n(2 UPB LOC YEARBOX)(g)l$, year repr(year)
 ))

);

main: ( CO inspired by http://www.ee.ryerson.ca/~elf/hack/realmen.html

          Real Programmers Don't Use PASCAL - Ed Post
           Datamation, volume 29 number 7, July 1983
             THE REAL PROGRAMMER'S NATURAL HABITAT

"Taped to the wall is a line-printer Snoopy calender for the year 1969." CO

 INT mankind stepped on the moon = 1969,
     line printer width = 132; # as at 1969! #
 print calendar(mankind stepped on the moon, line printer width)

)</lang> Output:

                                                       [Insert Snoopy here]
                                                               1969

      January               February               March                 April                  May                   June        
Su Mo Tu We Th Fr Sa  Su Mo Tu We Th Fr Sa  Su Mo Tu We Th Fr Sa  Su Mo Tu We Th Fr Sa  Su Mo Tu We Th Fr Sa  Su Mo Tu We Th Fr Sa
          1  2  3  4                     1                     1         1  2  3  4  5               1  2  3   1  2  3  4  5  6  7
 5  6  7  8  9 10 11   2  3  4  5  6  7  8   2  3  4  5  6  7  8   6  7  8  9 10 11 12   4  5  6  7  8  9 10   8  9 10 11 12 13 14
12 13 14 15 16 17 18   9 10 11 12 13 14 15   9 10 11 12 13 14 15  13 14 15 16 17 18 19  11 12 13 14 15 16 17  15 16 17 18 19 20 21
19 20 21 22 23 24 25  16 17 18 19 20 21 22  16 17 18 19 20 21 22  20 21 22 23 24 25 26  18 19 20 21 22 23 24  22 23 24 25 26 27 28
26 27 28 29 30 31     23 24 25 26 27 28     23 24 25 26 27 28 29  27 28 29 30           25 26 27 28 29 30 31  29 30               
                                            30 31                                                                                 
        July                 August              September              October               November              December      
Su Mo Tu We Th Fr Sa  Su Mo Tu We Th Fr Sa  Su Mo Tu We Th Fr Sa  Su Mo Tu We Th Fr Sa  Su Mo Tu We Th Fr Sa  Su Mo Tu We Th Fr Sa
       1  2  3  4  5                  1  2      1  2  3  4  5  6            1  2  3  4                     1      1  2  3  4  5  6
 6  7  8  9 10 11 12   3  4  5  6  7  8  9   7  8  9 10 11 12 13   5  6  7  8  9 10 11   2  3  4  5  6  7  8   7  8  9 10 11 12 13
13 14 15 16 17 18 19  10 11 12 13 14 15 16  14 15 16 17 18 19 20  12 13 14 15 16 17 18   9 10 11 12 13 14 15  14 15 16 17 18 19 20
20 21 22 23 24 25 26  17 18 19 20 21 22 23  21 22 23 24 25 26 27  19 20 21 22 23 24 25  16 17 18 19 20 21 22  21 22 23 24 25 26 27
27 28 29 30 31        24 25 26 27 28 29 30  28 29 30              26 27 28 29 30 31     23 24 25 26 27 28 29  28 29 30 31         
                      31                                                                30