Updates and improvements to 2001/westley

There are a number of improvements in this commit but first: added
missing file status to bugs.md and also note on gets() being used (but
see below).

Format fixes in README.md.

As for improvements the following things were done.

Move the 'try' commands to new script westley.sh. It includes
additional commands and shows what each one is before executing it.

Added westley.sort.c which is based on the author's suggestion of sort
-b which always sorts the input. This was actually westley3.c in the try
section but this has been removed or replaced.

Added westley.punch.c which is also based on the author's comments - it
shows the punch card always. This was also added to westley.sh. Why did
I name it westley.punch.c ? Besides the fact it shows punch cards
there's a silly remark/joke in the README.md about it that answers it. :-)

These updates seem worthy of Brian Westley's final entry and a most
wondrous entry at that!
This commit is contained in:
Cody Boone Ferguson committed 2023-04-24 06:44:49 -07:00
1 parent b894b0abc9
commit 56e7dc3e88
7 files changed
+213 -57

No files matched your search

+2 -2
View File
@@ -2,5 +2,5 @@ westley
westley.alt westley.alt
westley2 westley2
westley2.c westley2.c
westley3 westley.punch
westley3.c westley.sort
+6 -2
View File
@@ -63,7 +63,7 @@ CDEFINE=
# Include files that are needed to compile # Include files that are needed to compile
# #
CINCLUDE= CINCLUDE= -include stdio.h
# Optimization # Optimization
# #
@@ -113,7 +113,7 @@ PROG= ${ENTRY}
# #
OBJ= ${PROG}.o OBJ= ${PROG}.o
DATA= DATA=
TARGET= ${PROG} TARGET= ${PROG} ${PROG}.sort ${PROG}.punch
# #
ALT_OBJ= ${PROG}.alt.o ALT_OBJ= ${PROG}.alt.o
ALT_TARGET= ${PROG}.alt ALT_TARGET= ${PROG}.alt
@@ -143,6 +143,10 @@ westley2: westley2.c
westley3: westley3.c westley3: westley3.c
${CC} ${CFLAGS} $< -o $@ ${LIBS} ${CC} ${CFLAGS} $< -o $@ ${LIBS}
${PROG}.sort: ${PROG}.sort.c
${CC} ${CFLAGS} $< -o $@ ${LIBS}
# alternative executable # alternative executable
# #
alt: data ${ALT_TARGET} alt: data ${ALT_TARGET}
+77 -53
View File
@@ -1,12 +1,8 @@
# Best position-independent code # Best position-independent code
Brian Westley Brian Westley
Firesign Theatre webmaster US
1906 James Ave <http://www.westley.org>
St. Paul, MN 55105
US
http://www.westley.org
## To build: ## To build:
@@ -22,20 +18,20 @@ make
## Try: ## Try:
[Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) added the script
[westley.sh](westley.sh) to automate a heap of commands that we, the IOCCC
judges, suggested, as well as some additional ones that he thought would be fun.
These include the below sort and punch card versions that he added, described
below, based on the author's remarks. Thank you Cody!
```sh ```sh
./westley < westley.c > westley2.c ./westley.sh
make westley2
echo 'Bozos, please deflate shoes before entering the bus!'| ./westley2
sort -b < westley2.c > westley3.c
make westley3
./westley3 < westley.c | diff - westley.c
./westley3 < westley.c | diff - westley2.c
./westley3 < westley.c | diff - westley3.c
``` ```
### Alternate code ### Alternate code:
An alternate version of this entry, `westley.alt.c`, is provided. This alternate code may be less portable. An alternate version of this entry, [westley.alt.c](westley.alt.c), is provided.
This alternate code might be less portable.
To compile this alternate version: To compile this alternate version:
@@ -45,7 +41,27 @@ make alt
Use `westley.alt` as you would `westley` above. Use `westley.alt` as you would `westley` above.
## Judges' remarks ### Sorted code:
The author stated that one can sort (with ignoring leading blanks i.e. `sort
-b`) the code by line and it will always sort the order of the input.
Use `westley.sort` as you would `westley` above.
### Punch card code:
The author also stated that if you just sort the code you'll get the with
`sort`) version that just prints out the punch card. Cody put this in
[westley.punch.c](westley.punch.c) specifically so that Westley can punch
everyone in the face! :-) This is also compiled by default.
To use, try:
```sh
echo 'Brian Westley does it again!' | ./westley.punch 2>/dev/null
```
## Judges' remarks:
Try copying the source to a new file and changing around the Try copying the source to a new file and changing around the
order of the lines. Does it produce the exact same output? order of the lines. Does it produce the exact same output?
@@ -53,16 +69,19 @@ order of the lines. Does it produce the exact same output?
By changing the order of the source, figure out in how many different By changing the order of the source, figure out in how many different
ways this program can transform input to output. ways this program can transform input to output.
This assortment obfuscated lines takes position-independant code This assortment obfuscated lines takes position-independent code
to a new level! :-) to a new level! :-)
## Author's remarks We find it amazing that with just 28 lines of code (not counting comments and
blank lines) there are `28!` or ``304,888,344,611,713,860,501,504,000,000``
versions of the program, all valid C!
Punch cards, or Hollerith cards, were becoming obsolete just ## Author's remarks:
as C was becoming more popular*; this is rather unfortunate,
because C has an advantage over many other languages when it [Punch cards](https://en.wikipedia.org/wiki/Punched_card), or Hollerith cards,
comes to punch cards - C programs can be written to be "drop were becoming obsolete just as C was becoming more popular\*; this is rather
proof". unfortunate, because C has an advantage over many other languages when it comes
to punch cards - C programs can be written to be "drop proof".
Consider the following C program: Consider the following C program:
@@ -76,7 +95,7 @@ c(){printf("C");}
This program will compile and run no matter what order the This program will compile and run no matter what order the
lines are in. If you punch it on cards (one line of code per lines are in. If you punch it on cards (one line of code per
card, naturally) and drop them, you don't need to put them in card, naturally) and drop them, you don't need to put them in
any particular order**; it will always produce "ABC" as output. any particular order\*\*; it will always produce `ABC` as output.
You can also use global variables: You can also use global variables:
@@ -96,9 +115,9 @@ test(a,b){return a;}
main(){if (test(0,1)) printf("T"); else printf("F");} main(){if (test(0,1)) printf("T"); else printf("F");}
``` ```
This program will print out "T" if the #define statement This program will print out `T` if the `#define` statement
falls between the declaration of test() and its use in falls between the declaration of `test()` and its use in
main(), otherwise it will print out "F". Furthermore, `main()`, otherwise it will print out `F`. Furthermore,
you can use the same call to test() repeatedly in you can use the same call to test() repeatedly in
different lines to return different values: different lines to return different values:
@@ -120,16 +139,20 @@ number generator...
Of course, there are drawbacks to C programming on punch Of course, there are drawbacks to C programming on punch
cards; an 80-character line limit can be restricting, and cards; an 80-character line limit can be restricting, and
(to be maximally portable) you need to use trigraphs for (to be maximally portable) you need to use trigraphs for
the characters "^[]{}\" (these aren't found on every the characters `^[]{}\` (these aren't found on every
keypunch, and have various encodings). keypunch, and have various encodings).
My C program entry does the following: My C program entry does the following:
1) reads in lines 1. Reads in lines.
2) rearranges the lines, or not
2a) if it rearranges the lines, they are sorted or scrambled 2. Rearranges the lines, or not.
3) reverses the order of the lines, or not - if it rearranges the lines, they are sorted or scrambled.
4) prints out the lines as either text or EBCDIC punch cards.
3. Reverses the order of the lines, or not.
4. Prints out the lines as either text or
[EBCDIC](https://en.wikipedia.org/wiki/EBCDIC) punch cards.
The code, as written, scrambles the input and prints it out The code, as written, scrambles the input and prints it out
as normal text, so you can simulate 'dropping' the cards. as normal text, so you can simulate 'dropping' the cards.
@@ -137,19 +160,19 @@ You can repeatedly scramble the code to get all 12 variants
(but the scrambling isn't very random; it's just a bubble (but the scrambling isn't very random; it's just a bubble
sort with a random number, so some variants are more common sort with a random number, so some variants are more common
than others). You can also just swap the arguments in the than others). You can also just swap the arguments in the
calls to t() in all combinations to get all the variations. calls to `t()` in all combinations to get all the variations.
If you sort the lines, you will get the version that just If you sort the lines, you will get the version that just
prints out the input as punch cards (you will need to display prints out the input as punch cards (you will need to display
at least 82 columns of text, or clip the last few chars by at least 82 columns of text, or clip the last few chars by
piping it through "sed s/...$//"). If you use this on the piping it through `sed s/...$//`). If you use this on the
original code, you will see that it spells out "HOLLERITH" original code, you will see that it spells out `HOLLERITH`
when punched on cards (you can see the tall, thin letters when punched on cards (you can see the tall, thin letters
spelling out "HOLLERITH" if you turn the C code sideways). spelling out `HOLLERITH` if you turn the C code sideways).
You will also see why "/KC 0000 K" is a "Hollerith emoticon". You will also see why `/KC 0000 K` is a `Hollerith emoticon`.
Unrecognized characters are punched as a lace column. Unrecognized characters are punched as a lace column.
(You can see an ASCII simulation of the code as punch cards (You can see an ASCII simulation of the code as punch cards
by looking at card.gif) by looking at `card.gif`.)
For a nice test pattern, try For a nice test pattern, try
@@ -158,29 +181,30 @@ For a nice test pattern, try
``` ```
If you want to analyze the program, sorting the lines while If you want to analyze the program, sorting the lines while
ignoring leading blanks works best (sort -b). This will ignoring leading blanks works best (`sort -b`). This will
produce the version that just reverses the line order, and produce the version that just reverses the line order, and
the routines in the code are in a sensible order. the routines in the code are in a sensible order.
This program should work on EBCDIC computers. It assumes This program should work on EBCDIC computers. It assumes
that the time_t ptr param to time() will work with an int that the `time_t` ptr param to `time()` will work with an `int`
ptr, and that "passing through" a char[][] array as a simple ptr, and that "passing through" a `char[][]` array as a simple
char* is ok. Your compiler MUST understand trigraphs, or it `char *` is OK. Your compiler MUST understand trigraphs, or it
will miss the trigraph backslash before the double quote in will miss the trigraph backslash before the double quote in
the K string and complain about a malformed string; for GNU the `K` string and complain about a malformed string; for GNU
C, use -ansi or -trigraphs. Entering a line of more than 80 C, use `-ansi` or `-trigraphs`. Entering a line of more than 80
characters, or more than 81 lines, will jam the card reader. characters, or more than 81 lines, will jam the card reader.
I've used the a[b] ==> *(a+b) trick, because this is I've used the `a[b]` ==> `*(a+b)` trick, because this is
actually shorter than the trigraph version of a??(b??). actually shorter than the trigraph version of `a??(b??)`.
With 28 lines of code (not counting the blank lines or the With 28 lines of code (not counting the blank lines or the
comment), there are technically 28! different programs, or comment), there are technically `28!` different programs, or
304,888,344,611,713,860,501,504,000,000 different versions, `304,888,344,611,713,860,501,504,000,000` different versions,
all legal C. all legal C.
*except in Florida voting machines \* except in Florida voting machines
**all cards must be face down, nine-edge first, of course.
\*\* all cards must be face down, nine-edge first, of course.
## Copyright and CC BY-SA 4.0 License: ## Copyright and CC BY-SA 4.0 License:
+37
View File
@@ -0,0 +1,37 @@
T(c,r) ??< return Y(c, r)?'??(' :' '; ??>
W(r,a,b,c)??<return r==a||r==b||r==c; ??>
/* { /KC 0000 K } */
char*B=" yz0123456789";
U(c,i)char*c; ??<while(i++<80)printf(" "); puts("|"); ??>
char* B,*r; X(c,k)??<return isupper(c)?0:V(*(r+k),B); ??>
L(c,i,j)char c??(81??)??(81??);??<G(* (c+i),*(c+j));??>
char*r= "008y8yy8yyyyz8z8z88888z0yyz888 8888 88y00zz00z0088";
E(r,s)char*r,*s; ??< if(t( 0,1)&& F(r,s)<0)G(r,s); ??>
char*d= "yyzzyzz zz z0y000 zz 00yzz00y00yzz Brian Westley zyy00yy0yy 0" ; ; ;
t(a,b)??<return a;??>
#define t(a,b) t(b,a)
A(i ,c,j ,k) char *c; ??< for(j= -1; ++j<i; )for (k =j; k<i; )D(c ,j, k++); ??>
D(c,i,j) char c??(81??)??(81??);??<E(*(c+i),*(c+j));??>
F(r,s)char*r,*s; ??<return t(0,1)?H():strcmp(r,s); ??>
G(r,s)char*r,*s; ??<char t??( 81??); strcpy(t,r); strcpy(r,s); strcpy(s,t); ??>
H()??<static i=0; if (!i) ??< time(&i); srand(i); ??> return rand()-rand(); ??>
J(i,c,j)char*c; ??<for(j=t(i,0) ; j+j<i; j++)L(c,j,i-j); M(i,c); ??>
M(i,c)char c??(81??)??(81??);??<i++;while(i--)t(1,0)?puts(*(c+i)):P(*(c+i));??>
P(c)char*c; ??<Q(1,0); R(c,1 ); Q(0,0); ??>
Q(t,i)??< printf(t?" ":"|"); for(; i<80; i++) printf("_"); puts(t?"_":"|"); ??>
R(c,r) char *c; ??< printf( "/%-80s|??/n" ,c); for (; r< 13; r++)S (c,r,0); ??>
S(c,r,i)char*c; ??<printf("|");for(;*(c+i); i++)putchar(T(*(c+i),r));U(c,i);??>
V(c,k,i) char*k; ??<for (i=0; *(k+i) &&*(k+i)!=c; i++); return *(k+i)?i:-1; ??>
char* K;Y (c ,r) ??< int i=V ( tolower (c) ,K); return(i <0)?1 :Z(c ,r, i); ??>
char* d,*m,*B; Z(c,i,k)??<return W(i, V(*(d+k), B),V(*( m+k),B) ,X(c, k)); ??>
char*K= "gh$j|lm'pq&rv<x>z#);@_winky,.%/+*!=3-284106579 (:obfuscated??/?" ; ;
char*m= "7831734578 9547693564569528334164263z284106579 52626423135477"; ; ; ;
main(i)??<char c??(81??)??(81??);for(i=0;gets(*(c+i)); i++);A(i,c);J(i-1,c);??>
+38
View File
@@ -0,0 +1,38 @@
#!/usr/bin/env bash
echo "./westley < westley.c 2>/dev/null > westley2.c"
./westley < westley.c 2>/dev/null > westley2.c
make westley2 2>/dev/null 1>&2
echo
echo "echo 'Bozos, please deflate shoes before entering the bus!'| ./westley2 2>/dev/null"
echo 'Bozos, please deflate shoes before entering the bus!'| ./westley2 2>/dev/null
echo
make westley.sort 2>/dev/null 1>&2
echo
echo "./westley.sort < westley.c 2>/dev/null | diff - westley.c"
# SC2094 (info): Make sure not to read and write the same file in the same pipeline.
# shellcheck disable=SC2094
./westley.sort < westley.c 2>/dev/null | diff - westley.c
echo "./westley.sort < westley.c 2>/dev/null | diff - westley2.c"
./westley.sort < westley.c 2>/dev/null | diff - westley2.c
echo "./westley.sort < westley.c 2>/dev/null | diff - westley.sorted.c"
./westley.sort < westley.c 2>/dev/null | diff - westley.sorted.c
echo "./westley.sort < westley.c 2>/dev/null | diff - westley.punch.c"
./westley.sort < westley.c 2>/dev/null | diff - westley.punch.c
echo
# SC2028 (info): echo may not expand escape sequences. Use printf.
# shellcheck disable=SC2028
echo "printf \"1\n\4\n5\" | ./westley 2>/dev/null"
printf "1\n4\n5" | ./westley 2>/dev/null
echo
# SC2028 (info): echo may not expand escape sequences. Use printf.
# shellcheck disable=SC2028
echo "printf \"1\n\4\n5\" | ./westley 2>/dev/null"
printf "1\n4\n5" | ./westley 2>/dev/null
echo
echo "echo 'Hello, world!' | ./westley.punch 2>/dev/null"
echo 'Hello, world!' | ./westley.punch 2>/dev/null
+37
View File
@@ -0,0 +1,37 @@
#define t(a,b) t(b,a)
/* { /KC 0000 K } */
A(i ,c,j ,k) char *c; ??< for(j= -1; ++j<i; )for (k =j; k<i; )D(c ,j, k++); ??>
D(c,i,j) char c??(81??)??(81??);??<E(*(c+i),*(c+j));??>
E(r,s)char*r,*s; ??< if(t( 0,1)&& F(r,s)<0)G(r,s); ??>
F(r,s)char*r,*s; ??<return t(0,1)?H():strcmp(r,s); ??>
G(r,s)char*r,*s; ??<char t??( 81??); strcpy(t,r); strcpy(r,s); strcpy(s,t); ??>
H()??<static i=0; if (!i) ??< time(&i); srand(i); ??> return rand()-rand(); ??>
J(i,c,j)char*c; ??<for(j=t(i,0) ; j+j<i; j++)L(c,j,i-j); M(i,c); ??>
L(c,i,j)char c??(81??)??(81??);??<G(* (c+i),*(c+j));??>
M(i,c)char c??(81??)??(81??);??<i++;while(i--)t(1,0)?puts(*(c+i)):P(*(c+i));??>
P(c)char*c; ??<Q(1,0); R(c,1 ); Q(0,0); ??>
Q(t,i)??< printf(t?" ":"|"); for(; i<80; i++) printf("_"); puts(t?"_":"|"); ??>
R(c,r) char *c; ??< printf( "/%-80s|??/n" ,c); for (; r< 13; r++)S (c,r,0); ??>
S(c,r,i)char*c; ??<printf("|");for(;*(c+i); i++)putchar(T(*(c+i),r));U(c,i);??>
T(c,r) ??< return Y(c, r)?'??(' :' '; ??>
U(c,i)char*c; ??<while(i++<80)printf(" "); puts("|"); ??>
V(c,k,i) char*k; ??<for (i=0; *(k+i) &&*(k+i)!=c; i++); return *(k+i)?i:-1; ??>
W(r,a,b,c)??<return r==a||r==b||r==c; ??>
char* B,*r; X(c,k)??<return isupper(c)?0:V(*(r+k),B); ??>
char* K;Y (c ,r) ??< int i=V ( tolower (c) ,K); return(i <0)?1 :Z(c ,r, i); ??>
char* d,*m,*B; Z(c,i,k)??<return W(i, V(*(d+k), B),V(*( m+k),B) ,X(c, k)); ??>
char*B=" yz0123456789";
char*K= "gh$j|lm'pq&rv<x>z#);@_winky,.%/+*!=3-284106579 (:obfuscated??/?" ; ;
char*d= "yyzzyzz zz z0y000 zz 00yzz00y00yzz Brian Westley zyy00yy0yy 0" ; ; ;
char*m= "7831734578 9547693564569528334164263z284106579 52626423135477"; ; ; ;
char*r= "008y8yy8yyyyz8z8z88888z0yyz888 8888 88y00zz00z0088";
main(i)??<char c??(81??)??(81??);for(i=0;gets(*(c+i)); i++);A(i,c);J(i-1,c);??>
t(a,b)??<return a;??>
+16
View File
@@ -1449,6 +1449,22 @@ The author said that they compiled it with [gcc version
a certain gcc version is necessary but it might be helpful to download and a certain gcc version is necessary but it might be helpful to download and
compile that version to test it. compile that version to test it.
## [2001/westley](2001/westley/westley.c) ([README.md](2001/westley/README.md))
## STATUS: missing files - please provide them
The author referred to the file `card.gif` but this appears to be missing. Do
you have it? If you do please provide it and thank you!
## STATUS: uses gets() - change to fgets() if possible (in some cases getline() works)
The code also uses `gets()` which, without redirecting stderr to `/dev/null`,
can show an obnoxious warning every time it's run. In the script
[2001/westley/westley.sh](2001/westley/westley.sh) that [Cody Boone
Ferguson](/winners.html#Cody_Boone_Ferguson) added stderr is in fact redirected
to `/dev/null` to prevent this warning but it would probably be better if it was
changed to use `fgets()` (which he might end up doing).
# 2002 # 2002
There was no IOCCC in 2002. There was no IOCCC in 2002.