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
westley2
westley2.c
westley3
westley3.c
westley.punch
westley.sort
+6 -2
View File
@@ -63,7 +63,7 @@ CDEFINE=
# Include files that are needed to compile
#
CINCLUDE=
CINCLUDE= -include stdio.h
# Optimization
#
@@ -113,7 +113,7 @@ PROG= ${ENTRY}
#
OBJ= ${PROG}.o
DATA=
TARGET= ${PROG}
TARGET= ${PROG} ${PROG}.sort ${PROG}.punch
#
ALT_OBJ= ${PROG}.alt.o
ALT_TARGET= ${PROG}.alt
@@ -143,6 +143,10 @@ westley2: westley2.c
westley3: westley3.c
${CC} ${CFLAGS} $< -o $@ ${LIBS}
${PROG}.sort: ${PROG}.sort.c
${CC} ${CFLAGS} $< -o $@ ${LIBS}
# alternative executable
#
alt: data ${ALT_TARGET}
+77 -53
View File
@@ -1,12 +1,8 @@
# Best position-independent code
Brian Westley
Firesign Theatre webmaster
1906 James Ave
St. Paul, MN 55105
US
http://www.westley.org
Brian Westley
US
<http://www.westley.org>
## To build:
@@ -22,20 +18,20 @@ make
## 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
./westley < westley.c > westley2.c
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
./westley.sh
```
### 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:
@@ -45,7 +41,27 @@ make alt
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
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
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! :-)
## 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
as C was becoming more popular*; this is rather 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".
## Author's remarks:
[Punch cards](https://en.wikipedia.org/wiki/Punched_card), or Hollerith cards,
were becoming obsolete just as C was becoming more popular\*; this is rather
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:
@@ -76,7 +95,7 @@ c(){printf("C");}
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
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:
@@ -96,9 +115,9 @@ test(a,b){return a;}
main(){if (test(0,1)) printf("T"); else printf("F");}
```
This program will print out "T" if the #define statement
falls between the declaration of test() and its use in
main(), otherwise it will print out "F". Furthermore,
This program will print out `T` if the `#define` statement
falls between the declaration of `test()` and its use in
`main()`, otherwise it will print out `F`. Furthermore,
you can use the same call to test() repeatedly in
different lines to return different values:
@@ -120,16 +139,20 @@ number generator...
Of course, there are drawbacks to C programming on punch
cards; an 80-character line limit can be restricting, and
(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).
My C program entry does the following:
1) reads in lines
2) rearranges the lines, or not
2a) if it rearranges the lines, they are sorted or scrambled
3) reverses the order of the lines, or not
4) prints out the lines as either text or EBCDIC punch cards.
1. Reads in lines.
2. Rearranges the lines, or not.
- if it rearranges the lines, they are sorted or scrambled.
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
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
sort with a random number, so some variants are more common
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
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
piping it through "sed s/...$//"). If you use this on the
original code, you will see that it spells out "HOLLERITH"
piping it through `sed s/...$//`). If you use this on the
original code, you will see that it spells out `HOLLERITH`
when punched on cards (you can see the tall, thin letters
spelling out "HOLLERITH" if you turn the C code sideways).
You will also see why "/KC 0000 K" is a "Hollerith emoticon".
spelling out `HOLLERITH` if you turn the C code sideways).
You will also see why `/KC 0000 K` is a `Hollerith emoticon`.
Unrecognized characters are punched as a lace column.
(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
@@ -158,29 +181,30 @@ For a nice test pattern, try
```
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
the routines in the code are in a sensible order.
This program should work on EBCDIC computers. It assumes
that the time_t ptr param to time() will work with an int
ptr, and that "passing through" a char[][] array as a simple
char* is ok. Your compiler MUST understand trigraphs, or it
that the `time_t` ptr param to `time()` will work with an `int`
ptr, and that "passing through" a `char[][]` array as a simple
`char *` is OK. Your compiler MUST understand trigraphs, or it
will miss the trigraph backslash before the double quote in
the K string and complain about a malformed string; for GNU
C, use -ansi or -trigraphs. Entering a line of more than 80
the `K` string and complain about a malformed string; for GNU
C, use `-ansi` or `-trigraphs`. Entering a line of more than 80
characters, or more than 81 lines, will jam the card reader.
I've used the a[b] ==> *(a+b) trick, because this is
actually shorter than the trigraph version of a??(b??).
I've used the `a[b]` ==> `*(a+b)` trick, because this is
actually shorter than the trigraph version of `a??(b??)`.
With 28 lines of code (not counting the blank lines or the
comment), there are technically 28! different programs, or
304,888,344,611,713,860,501,504,000,000 different versions,
comment), there are technically `28!` different programs, or
`304,888,344,611,713,860,501,504,000,000` different versions,
all legal C.
*except in Florida voting machines
**all cards must be face down, nine-edge first, of course.
\* except in Florida voting machines
\*\* all cards must be face down, nine-edge first, of course.
## 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
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
There was no IOCCC in 2002.