Merge pull request #1381 from xexyl/schweikh396
This commit is contained in:
33 files changed
+463
-229
No files matched your search
@@ -15,7 +15,6 @@ The current status of this entry is:
|
|||||||
|
|
||||||
```
|
```
|
||||||
STATUS: INABIAF - please **DO NOT** fix
|
STATUS: INABIAF - please **DO NOT** fix
|
||||||
STATUS: known bug - please help us fix
|
|
||||||
```
|
```
|
||||||
|
|
||||||
For more detailed information see [1994 dodsond2 in bugs.md](/bugs.md#1994-dodsond2).
|
For more detailed information see [1994 dodsond2 in bugs.md](/bugs.md#1994-dodsond2).
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
#define M isdigit
|
#define M isdigit
|
||||||
#define N 30
|
#define N 30
|
||||||
#define P getchar()
|
#define P getchar()
|
||||||
G a[N][3],b[N],c[N],d[N],e[N],f[N],g[N],i=W>0?W:0,j=(W>0?W:0)*20,k,l=0;
|
G a[N][3],b[N],c[N],d[N],e[N],f[N],g[N],i=W>0?W:0,j=0,X=0,Y=W>0?W:0,k,l=0;
|
||||||
main(){m();n();A;}m(){G o;srandom(getpid());do{I(o=0;
|
main(){m();n();A;}m(){G o;srandom(getpid());do{I(o=0;
|
||||||
o<N;e[o++]=3){J(o,0)=J(o,1)=J(o,2)=-1;c[o]=d[o]=g[o]=0;
|
o<N;e[o++]=3){J(o,0)=J(o,1)=J(o,2)=-1;c[o]=d[o]=g[o]=0;
|
||||||
b[o]=N*2;}r(0);s();}F(s());t();}s(){G o,p;I(o=0;o<N;o++){
|
b[o]=N*2;}r(0);s();}F(s());t();}s(){G o,p;I(o=0;o<N;o++){
|
||||||
@@ -30,11 +30,11 @@ J(x,e[x])=y;J(y,e[y])=x;K(!r(y)){J(x,e[x])=J(y,e[y])=-1;(e[y])++;
|
|||||||
(e[x])++;}L t=0;}H(1);}n(){G r,n;char v;do{r=D;}
|
(e[x])++;}L t=0;}H(1);}n(){G r,n;char v;do{r=D;}
|
||||||
F(c[r]||d[r]||(b[r]<3)||d[J(r,0)]||d[J(r,1)]||d[J(r,2)]||
|
F(c[r]||d[r]||(b[r]<3)||d[J(r,0)]||d[J(r,1)]||d[J(r,2)]||
|
||||||
c[J(r,0)]||c[J(r,1)]||c[J(r,2)]);F(1){E"You are in room %d\n",r);
|
c[J(r,0)]||c[J(r,1)]||c[J(r,2)]);F(1){E"You are in room %d\n",r);
|
||||||
K(f[r]){i++;E"You found an arrow\n");j+=20;f[r]=0;}K(b[r]==0){
|
K(f[r]){i++;E"You found an arrow\n");Y++;j+=20;f[r]=0;Y++;}K(b[r]==0){
|
||||||
E"Wumpus meat\n");j-=100;A;}K(d[r]){E"You fell in a pit\n");j-=50;
|
E"Wumpus meat\n");j-=100;A;}K(d[r]){E"You fell in a pit\n");j-=50;
|
||||||
A;}K(r==k){K(i){i--;l++;j-=20;E"You are missing an arrow!\n");
|
A;}K(r==k){K(i){i--;l++;j-=20;E"You are missing an arrow!\n");
|
||||||
}K(l==3+(W>0?W:0)){E"You catch the robber and recover all %d arrows!\n",(W>0?W:0)+3);
|
}K(l&&l==Y-X){E"You catch the robber and recover all %d arrow%s!\n",Y-X,Y-X!=1?"s":"");
|
||||||
i=(W>0?W:0)+3;j+=200;k=-1;}L{E"The robber scurries away\n");do{k=D;}
|
i=l;l=Y=X=0;j+=200;k=-1;}L{E"The robber scurries away\n");do{k=D;}
|
||||||
F((c[k])||(d[k])||(b[k]==0)||(k==r));}}K(c[r]){c[r]=0;c[D]=1;r=D;
|
F((c[k])||(d[k])||(b[k]==0)||(k==r));}}K(c[r]){c[r]=0;c[D]=1;r=D;
|
||||||
E"The bats pick you up and drop you in room %d\n",r);j-=10;}L{
|
E"The bats pick you up and drop you in room %d\n",r);j-=10;}L{
|
||||||
K(b[r]<3)E"You smell a wumpus\n");
|
K(b[r]<3)E"You smell a wumpus\n");
|
||||||
@@ -45,11 +45,11 @@ K(!g[r]){j+=10;g[r]=1;}do{v=P;K(v=='s')q(r);K(v=='l')break;
|
|||||||
K(v=='i')E"You have %d arrow%c\n",i,i-1?'s':' ');K(v=='q')A;}
|
K(v=='i')E"You have %d arrow%c\n",i,i-1?'s':' ');K(v=='q')A;}
|
||||||
F(!M(v));K(M(v)){n=v-'0';v=P;K(M(v))n=n*10+v-'0';
|
F(!M(v));K(M(v)){n=v-'0';v=P;K(M(v))n=n*10+v-'0';
|
||||||
K((J(r,0)==n)||(J(r,1)==n)||(J(r,2)==n))r=n;}}}}q(r)G r;{G z,n;
|
K((J(r,0)==n)||(J(r,1)==n)||(J(r,2)==n))r=n;}}}}q(r)G r;{G z,n;
|
||||||
char v;K(i==0){E"You have no arrows\n");H;}i--;
|
char v;K(i==0){E"You have no arrows\n");H;}i--;X++;
|
||||||
E"Shoot into which rooms? ");I(z=0;z<4;z++){j-=20*z;do{v=P;
|
E"Shoot into which rooms? ");I(z=0;z<4;z++){j-=20*z;do{v=P;
|
||||||
K((v=='\n')&&(i>0)){j-=50;E"You have %d arrow%c\n",i,i-1?'s':' ');H;}else K(i==0)H;}F(!M(v));
|
K((v=='\n')&&(i>0)){j-=50;E"You have %d arrow%c\n",i,i-1?'s':' ');H;}else K(i==0)H;}F(!M(v));
|
||||||
n=v-'0';v=P;K(M(v))n=10*n+v-'0';K((J(r,0)==n)||(J(r,1)==n)||(J(r,2)
|
n=v-'0';v=P;K(M(v))n=10*n+v-'0';K((J(r,0)==n)||(J(r,1)==n)||(J(r,2)
|
||||||
==n)){r=n;K(b[r]==0){E"You have killed the Wumpus!\n");j+=500+i*100;
|
==n)){r=n;K(b[r]==0){E"You have killed the Wumpus!\n");j+=500+i*100;
|
||||||
A;}}L K(random()%3==1){E"The arrow bounces back and kills you\n");
|
A;}}L K(random()%3==1){E"The arrow bounces back and kills you\n");
|
||||||
j-=100;A;}L{I(n=0;n<N;n++)b[n]=2*N;w(D,0);j-=100;}K(v=='\n'){j-=50;
|
j-=100;A;}L{I(n=0;n<N;n++)b[n]=2*N;w(D,0);j-=100;}K(v=='\n'){j-=50;
|
||||||
E"You have %d arrows\n",i);H;}}}
|
E"You have %d arrow%s\n",i,i!=1?"s":"");H;}}}
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
#define M isdigit
|
#define M isdigit
|
||||||
#define N 30
|
#define N 30
|
||||||
#define P getchar()
|
#define P getchar()
|
||||||
G a[N][3],b[N],c[N],d[N],e[N],f[N],g[N],i,j=0,k,l=0;
|
G a[N][3],b[N],c[N],d[N],e[N],f[N],g[N],i,j=0,X=0,Y=0,k,l=0;
|
||||||
main(){m();n();A;}m(){G o;srandom(getpid());do{I(o=0;
|
main(){m();n();A;}m(){G o;srandom(getpid());do{I(o=0;
|
||||||
o<N;e[o++]=3){J(o,0)=J(o,1)=J(o,2)=-1;c[o]=d[o]=g[o]=0;
|
o<N;e[o++]=3){J(o,0)=J(o,1)=J(o,2)=-1;c[o]=d[o]=g[o]=0;
|
||||||
b[o]=N*2;}r(0);s();}F(s());t();}s(){G o,p;I(o=0;o<N;o++){
|
b[o]=N*2;}r(0);s();}F(s());t();}s(){G o,p;I(o=0;o<N;o++){
|
||||||
@@ -30,11 +30,11 @@ J(x,e[x])=y;J(y,e[y])=x;K(!r(y)){J(x,e[x])=J(y,e[y])=-1;(e[y])++;
|
|||||||
(e[x])++;}L t=0;}H(1);}n(){G r,n;char v;do{r=D;}
|
(e[x])++;}L t=0;}H(1);}n(){G r,n;char v;do{r=D;}
|
||||||
F(c[r]||d[r]||(b[r]<3)||d[J(r,0)]||d[J(r,1)]||d[J(r,2)]||
|
F(c[r]||d[r]||(b[r]<3)||d[J(r,0)]||d[J(r,1)]||d[J(r,2)]||
|
||||||
c[J(r,0)]||c[J(r,1)]||c[J(r,2)]);F(1){E"You are in room %d\n",r);
|
c[J(r,0)]||c[J(r,1)]||c[J(r,2)]);F(1){E"You are in room %d\n",r);
|
||||||
K(f[r]){i++;E"You found an arrow\n");j+=20;f[r]=0;}K(b[r]==0){
|
K(f[r]){i++;E"You found an arrow\n");Y++;j+=20;f[r]=0;}K(b[r]==0){
|
||||||
E"Wumpus meat\n");j-=100;A;}K(d[r]){E"You fell in a pit\n");j-=50;
|
E"Wumpus meat\n");j-=100;A;}K(d[r]){E"You fell in a pit\n");j-=50;
|
||||||
A;}K(r==k){K(i){i--;l++;j-=20;E"You are missing an arrow!\n");
|
A;}K(r==k){K(i){i--;l++;j-=20;E"You are missing an arrow!\n");
|
||||||
}K(l==3){E"You catch the robber and recover all 3 arrows!\n");
|
}K(l&&l==Y-X){E"You catch the robber and recover all %d arrow%s!\n",Y-X,Y-X!=1?"s":"");
|
||||||
i=3;j+=200;k=-1;}L{E"The robber scurries away\n");do{k=D;}
|
i=l;l=Y=X=0;j+=200;k=-1;}L{E"The robber scurries away\n");do{k=D;}
|
||||||
F((c[k])||(d[k])||(b[k]==0)||(k==r));}}K(c[r]){c[r]=0;c[D]=1;r=D;
|
F((c[k])||(d[k])||(b[k]==0)||(k==r));}}K(c[r]){c[r]=0;c[D]=1;r=D;
|
||||||
E"The bats pick you up and drop you in room %d\n",r);j-=10;}L{
|
E"The bats pick you up and drop you in room %d\n",r);j-=10;}L{
|
||||||
K(b[r]<3)E"You smell a wumpus\n");
|
K(b[r]<3)E"You smell a wumpus\n");
|
||||||
@@ -45,11 +45,11 @@ K(!g[r]){j+=10;g[r]=1;}do{v=P;K(v=='s')q(r);K(v=='l')break;
|
|||||||
K(v=='i')E"You have %d arrow%c\n",i,i-1?'s':' ');K(v=='q')A;}
|
K(v=='i')E"You have %d arrow%c\n",i,i-1?'s':' ');K(v=='q')A;}
|
||||||
F(!M(v));K(M(v)){n=v-'0';v=P;K(M(v))n=n*10+v-'0';
|
F(!M(v));K(M(v)){n=v-'0';v=P;K(M(v))n=n*10+v-'0';
|
||||||
K((J(r,0)==n)||(J(r,1)==n)||(J(r,2)==n))r=n;}}}}q(r)G r;{G z,n;
|
K((J(r,0)==n)||(J(r,1)==n)||(J(r,2)==n))r=n;}}}}q(r)G r;{G z,n;
|
||||||
char v;K(i==0){E"You have no arrow\n");H;}i--;
|
char v;K(i==0){E"You have no arrow\n");H;}i--;X++;
|
||||||
E"Shoot into which rooms? ");I(z=0;z<4;z++){j-=20*z;do{v=P;
|
E"Shoot into which rooms? ");I(z=0;z<4;z++){j-=20*z;do{v=P;
|
||||||
K((v=='\n')&&(i>0)){j-=50;E"You have %d arrow%c\n",i,i-1?'s':' ');H;}else K(i==0)H;}F(!M(v));
|
K((v=='\n')&&(i>0)){j-=50;E"You have %d arrow%c\n",i,i-1?'s':' ');H;}else K(i==0)H;}F(!M(v));
|
||||||
n=v-'0';v=P;K(M(v))n=10*n+v-'0';K((J(r,0)==n)||(J(r,1)==n)||(J(r,2)
|
n=v-'0';v=P;K(M(v))n=10*n+v-'0';K((J(r,0)==n)||(J(r,1)==n)||(J(r,2)
|
||||||
==n)){r=n;K(b[r]==0){E"You have killed the Wumpus!\n");j+=500+i*100;
|
==n)){r=n;K(b[r]==0){E"You have killed the Wumpus!\n");j+=500+i*100;
|
||||||
A;}}L K(random()%3==1){E"The arrow bounces back and kills you\n");
|
A;}}L K(random()%3==1){E"The arrow bounces back and kills you\n");
|
||||||
j-=100;A;}L{I(n=0;n<N;n++)b[n]=2*N;w(D,0);j-=100;}K(v=='\n'){j-=50;
|
j-=100;A;}L{I(n=0;n<N;n++)b[n]=2*N;w(D,0);j-=100;}K(v=='\n'){j-=50;
|
||||||
E"You have %d arrows\n",i);H;}}}
|
E"You have %d arrow%s\n",i,i!=1?"s":"");H;}}}
|
||||||
@@ -3,8 +3,8 @@ august.oc
|
|||||||
test.oo
|
test.oo
|
||||||
fac.oo
|
fac.oo
|
||||||
parse.oo
|
parse.oo
|
||||||
prog.oc
|
august.oc
|
||||||
|
august.oo
|
||||||
august.oo
|
august.oo
|
||||||
prog.oo
|
|
||||||
august.orig
|
august.orig
|
||||||
prog.orig
|
prog.orig
|
||||||
+20
-28
@@ -34,13 +34,7 @@ The above should print a `!` followed by a newline.
|
|||||||
### Try:
|
### Try:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
cat august.c fac.oc | ./august > fac.oo
|
./try.sh
|
||||||
./august < fac.oo
|
|
||||||
|
|
||||||
cat august.c fac.oc | ./august | ./august
|
|
||||||
|
|
||||||
cat august.c parse.oc | ./august > parse.oo
|
|
||||||
cat parse.oo fac.oc | ./august | ./august
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
@@ -79,13 +73,6 @@ And if you have lots of spare time, you can recurse one level deeper:
|
|||||||
cat august.oo august.oo august.oo fac.oo | ./august
|
cat august.oo august.oo august.oo fac.oo | ./august
|
||||||
```
|
```
|
||||||
|
|
||||||
NOTE: to run all the commands in the above sections you can also use the
|
|
||||||
[try.sh](try.sh) script like:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
./try.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
We (the judges) recommend that you spend some time studying this
|
We (the judges) recommend that you spend some time studying this
|
||||||
entry as it surely will make the 'best of the IOCCC' list. It was
|
entry as it surely will make the 'best of the IOCCC' list. It was
|
||||||
very well received by those who attended the IOCCC BOF.
|
very well received by those who attended the IOCCC BOF.
|
||||||
@@ -108,8 +95,8 @@ compiler that compiles from OC (Obfuscated C, a subset of C) into the
|
|||||||
byte code that the interpreter understands.
|
byte code that the interpreter understands.
|
||||||
|
|
||||||
The language the compiler understands is a subset of C (the grammar
|
The language the compiler understands is a subset of C (the grammar
|
||||||
is in grammar.small) with the functions getchar() and putchar()
|
is below) with the functions `getchar(3)` and `putchar(3)`
|
||||||
available. The subset has the types `int', `char', and pointers to
|
available. The subset has the types `int`, `char`, and pointers to
|
||||||
those (it has function pointers too, but not with the proper
|
those (it has function pointers too, but not with the proper
|
||||||
syntax). Arrays can only be global. There is a rather limited set
|
syntax). Arrays can only be global. There is a rather limited set
|
||||||
of operators, and control constructs.
|
of operators, and control constructs.
|
||||||
@@ -117,10 +104,10 @@ of operators, and control constructs.
|
|||||||
The compiler has absolutely no error checking, so things
|
The compiler has absolutely no error checking, so things
|
||||||
can go wrong. But this is what seasoned C programmers are used to.
|
can go wrong. But this is what seasoned C programmers are used to.
|
||||||
|
|
||||||
Assume that the interpreter has been compiled (source in prog.c and
|
Assume that the interpreter has been compiled (source in [august.c](august.c)
|
||||||
binary in prog) and that we have this in a file named `test.oc`:
|
and binary in august) and that we have this in a file named `test.oc`:
|
||||||
|
|
||||||
```
|
```c
|
||||||
main() { putchar('!'); putchar('\n'); exit(0); }
|
main() { putchar('!'); putchar('\n'); exit(0); }
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -155,22 +142,26 @@ command from the Makefile, but add the `-E` flag and change 60000 to 40000,
|
|||||||
i.e.:
|
i.e.:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
cc -E -DZ=40000 .... august.c > prog.oc
|
cc -E -DZ=40000 .... august.c > august.oc
|
||||||
```
|
```
|
||||||
|
|
||||||
If `prog.oc` contain some junk line starting with a `#' (most likely
|
If `august.oc` contain some junk line starting with a `#` (most likely
|
||||||
it does) then remove it.
|
it does) then remove it like:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
sed -i'' '/^#/d' august.oc
|
||||||
|
```
|
||||||
|
|
||||||
OK, we can now compile the interpreter:
|
OK, we can now compile the interpreter:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
cat august.c prog.oc | ./august > prog.oo
|
cat august.c august.oc | ./august > august.oo
|
||||||
```
|
```
|
||||||
|
|
||||||
And we can run it:
|
And we can run it:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
cat prog.oo test.oo | ./august
|
cat august.oo test.oo | ./august
|
||||||
```
|
```
|
||||||
|
|
||||||
Here we have the interpreter interpreting another interpreter that runs
|
Here we have the interpreter interpreting another interpreter that runs
|
||||||
@@ -178,13 +169,13 @@ the program. Did you think that was too fast? Just throw in another
|
|||||||
level of interpretation:
|
level of interpretation:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
cat prog.oo prog.oo test.oo | ./august
|
cat august.oo august.oo test.oo | ./august
|
||||||
```
|
```
|
||||||
|
|
||||||
And another...
|
And another...
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
cat prog.oo prog.oo prog.oo test.oo | ./august
|
cat august.oo august.oo august.oo test.oo | ./august
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -199,7 +190,7 @@ Anyway, the bytecode from the compiler is first optimized in
|
|||||||
an external optimizer (not supplied here); this brings down the
|
an external optimizer (not supplied here); this brings down the
|
||||||
size of it by about 30%. The remaining code is then LZ-compressed
|
size of it by about 30%. The remaining code is then LZ-compressed
|
||||||
(roughly) with a sliding window of 255 bytes. The most common
|
(roughly) with a sliding window of 255 bytes. The most common
|
||||||
occuring bytes are then encoded using `" \n\t;{}"` to avoid having
|
occurring bytes are then encoded using `" \n\t;{}"` to avoid having
|
||||||
them counted as significant. About 200 bytes of the interpreter
|
them counted as significant. About 200 bytes of the interpreter
|
||||||
handles the unpacking of the byte code (this is a lot, but it pays
|
handles the unpacking of the byte code (this is a lot, but it pays
|
||||||
off).
|
off).
|
||||||
@@ -208,7 +199,7 @@ Despite all this work I still had to put a lot of code in the
|
|||||||
compilation command. This disturbs me. It is possible to compress
|
compilation command. This disturbs me. It is possible to compress
|
||||||
the code further with a better entropy coder (e.g. an arithmetic
|
the code further with a better entropy coder (e.g. an arithmetic
|
||||||
coder), but decompression then takes up too much code. Maybe this
|
coder), but decompression then takes up too much code. Maybe this
|
||||||
would be a way to fit it all into the 1536 bytes, but I'm don't have
|
would be a way to fit it all into the 1536 bytes, but I don't have
|
||||||
time to try it.
|
time to try it.
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -283,6 +274,7 @@ stars: "*"*
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
||||||
Well, that is enough ranting for now.
|
Well, that is enough ranting for now.
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ cat parse.oo fac.oc | ./august | ./august
|
|||||||
|
|
||||||
rm august.oc
|
rm august.oc
|
||||||
make august.oc
|
make august.oc
|
||||||
|
sed -i'' '/^#/d' august.oc
|
||||||
cat august.c august.oc | ./august > august.oo
|
cat august.c august.oc | ./august > august.oo
|
||||||
cat august.oo test.oo | ./august
|
cat august.oo test.oo | ./august
|
||||||
cat august.oo august.oo fac.oo | ./august
|
cat august.oo august.oo fac.oo | ./august
|
||||||
|
|||||||
@@ -66,9 +66,7 @@ where `a==0`.
|
|||||||
4. The fact that `main()` is a single expression and so beautifies poorly.
|
4. The fact that `main()` is a single expression and so beautifies poorly.
|
||||||
|
|
||||||
5. The fact that `main()` is used:
|
5. The fact that `main()` is used:
|
||||||
|
|
||||||
- to compute powers in modular arithmetic.
|
- to compute powers in modular arithmetic.
|
||||||
|
|
||||||
- to recursively call itself in the main loop.
|
- to recursively call itself in the main loop.
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+11
-11
@@ -1,16 +1,16 @@
|
|||||||
int cain(int I, char **O, int O0, int OO, int l)
|
int pain(int I, char **O, int O0, int OO, int l)
|
||||||
{
|
{
|
||||||
return !!I>=I?!I>=I?!!~I>=~I?!~I>=~I?!OO?!I:OO%2?
|
return !!I>=I?!I>=I?!!~I>=~I?!~I>=~I?!OO?!I:OO%2?
|
||||||
OO=cain(I,O,O0,OO>>!!OO,l),
|
OO=pain(I,O,O0,OO>>!!OO,l),
|
||||||
OO=cain(I-!I-!!I,O,OO,OO,l),
|
OO=pain(I-!I-!!I,O,OO,OO,l),
|
||||||
OO=cain(I-!I-!!I,O,O0,OO,l),
|
OO=pain(I-!I-!!I,O,O0,OO,l),
|
||||||
!(OO-!I||I)?l-1:OO
|
!(OO-!I||I)?l-1:OO
|
||||||
:(OO=cain(I,O,O0,OO>>!!OO,l),
|
:(OO=pain(I,O,O0,OO>>!!OO,l),
|
||||||
!(OO-l+!I||I)?l-1:cain(I-!I-!!I,O,OO,OO,l))
|
!(OO-l+!I||I)?l-1:pain(I-!I-!!I,O,OO,OO,l))
|
||||||
:(O0+OO)%l
|
:(O0+OO)%l
|
||||||
:cain(I-I/I-I/I,O,O0,OO+OO/OO,
|
:pain(I-I/I-I/I,O,O0,OO+OO/OO,
|
||||||
cain(0,O,O0,OO,I-I-I)+I+1?1:printf("%d\n",I-I-I)+fflush(stdout))
|
pain(0,O,O0,OO,I-I-I)+I+1?1:printf("%d\n",I-I-I)+fflush(stdout))
|
||||||
:cain(I-I-I-I-I,O,I+I-I+I,I,0)
|
:pain(I-I-I-I-I,O,I+I-I+I,I,0)
|
||||||
:cain(~!!I-!!I,O,atoi(1[O]),1,atoi(0[O]));
|
:pain(~!!I-!!I,O,atoi(1[O]),1,atoi(0[O]));
|
||||||
}
|
}
|
||||||
int main(int I, char **O) { int O0=0,OO=0,l=0; return cain(I,O,O0,OO,l); }
|
int main(int I, char **O) { int O0=0,OO=0,l=0; return pain(I,O,O0,OO,l); }
|
||||||
+1
-1
@@ -62,7 +62,7 @@ CDEFINE= -DZ=35000
|
|||||||
|
|
||||||
# Include files that are needed to compile
|
# Include files that are needed to compile
|
||||||
#
|
#
|
||||||
CINCLUDE=
|
CINCLUDE= -include stdio.h -include unistd.h
|
||||||
|
|
||||||
# Optimization
|
# Optimization
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -36,12 +36,19 @@ make CFLAGS+="-DZ=20000" clobber alt
|
|||||||
Besides the fact that modern systems make it impossible to see what this program
|
Besides the fact that modern systems make it impossible to see what this program
|
||||||
does the rapid movement can be a problem for some people. It is for these
|
does the rapid movement can be a problem for some people. It is for these
|
||||||
reasons that we recommend you first try the alternate version as described
|
reasons that we recommend you first try the alternate version as described
|
||||||
above. If however you wish to see the original version in modern systems, try:
|
above.
|
||||||
|
|
||||||
|
|
||||||
|
### Original build:
|
||||||
|
|
||||||
|
If however you wish to see the original version in modern systems, try:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
make all
|
make all
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Original use:
|
||||||
|
|
||||||
Use `./eldby` as you would `./eldby.alt` above.
|
Use `./eldby` as you would `./eldby.alt` above.
|
||||||
|
|
||||||
|
|
||||||
@@ -55,7 +62,7 @@ in a very small chunk of code.
|
|||||||
|
|
||||||
This program shows flying spheres. The program eats CPU on lesser
|
This program shows flying spheres. The program eats CPU on lesser
|
||||||
equipped systems. The program will run until termination. Terminal
|
equipped systems. The program will run until termination. Terminal
|
||||||
must be vt100 or better with 80 columns and 24 rows or more.
|
must be VT100 or better with 80 columns and 24 rows or more.
|
||||||
|
|
||||||
|
|
||||||
## Copyright and CC BY-SA 4.0 License:
|
## Copyright and CC BY-SA 4.0 License:
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
#include <stdio.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
float s=1944,x[5],y[5],z[5],r[5],j,h,a,b,d,e;int i=33,c,l,f=1;int g(){return f=
|
float s=1944,x[5],y[5],z[5],r[5],j,h,a,b,d,e;int i=33,c,l,f=1;int g(){return f=
|
||||||
(f*6478+1)%65346;}m(){x[i]=g()-l;y[i]=(g()-l)/4;r[i]=g()>>4;}main(){char t[1948
|
(f*6478+1)%65346;}m(){x[i]=g()-l;y[i]=(g()-l)/4;r[i]=g()>>4;}main(){char t[1948
|
||||||
]=" `MYmtw%FFlj%Jqig~%`jqig~Etsqnsj3stb",*p=t+3,*k="3tjlq9TX";l=s*20;while(i<s)
|
]=" `MYmtw%FFlj%Jqig~%`jqig~Etsqnsj3stb",*p=t+3,*k="3tjlq9TX";l=s*20;while(i<s)
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ include ../../var.mk
|
|||||||
# Common C compiler warnings to silence
|
# Common C compiler warnings to silence
|
||||||
#
|
#
|
||||||
CSILENCE= -Wno-error -Wno-implicit-function-declaration -Wno-keyword-macro \
|
CSILENCE= -Wno-error -Wno-implicit-function-declaration -Wno-keyword-macro \
|
||||||
-Wno-shift-op-parentheses -Wno-unused-parameter \
|
-Wno-shift-op-parentheses -Wno-unused-parameter -Wno-implicit-int \
|
||||||
-Wno-deprecated-non-prototype -Wno-strict-prototypes -Wno-unsequenced
|
-Wno-deprecated-non-prototype -Wno-strict-prototypes -Wno-unsequenced
|
||||||
|
|
||||||
# Common C compiler warning flags
|
# Common C compiler warning flags
|
||||||
|
|||||||
+6
-11
@@ -26,21 +26,16 @@ For more detailed information see [1996 gandalf in bugs.md](/bugs.md#1996-gandal
|
|||||||
### Try:
|
### Try:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
PATH=.:$PATH
|
./try.sh
|
||||||
./hatcat
|
|
||||||
./cathat
|
|
||||||
```
|
```
|
||||||
|
|
||||||
And next try:
|
As the script asks, care to guess why these execute differently? Only the
|
||||||
|
compiler knows ... ok maybe other things like the author, the judges and perhaps
|
||||||
|
you too?
|
||||||
|
|
||||||
```sh
|
BTW: it is perilous to 'try' the patience of
|
||||||
./cathat
|
[Gandalf](https://www.glyphweb.com/arda/g/gandalf.html). Go ahead, 'try' it! :-)
|
||||||
`pwd`/cathat
|
|
||||||
```
|
|
||||||
|
|
||||||
Care to guess why these execute differently? Only the
|
|
||||||
compiler knows ... ok maybe other things like the author,
|
|
||||||
the judges and maybe you too?
|
|
||||||
|
|
||||||
|
|
||||||
## Judges' remarks:
|
## Judges' remarks:
|
||||||
|
|||||||
Executable
+104
@@ -0,0 +1,104 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
make all 1>/dev/null || exit 1
|
||||||
|
|
||||||
|
# remove temporary files to show later
|
||||||
|
rm -f hatcat.txt cathat.txt hatcat2.txt cathat2.txt hatcat3.txt cathat3.txt
|
||||||
|
|
||||||
|
trap 'rm -f hatcat.txt cathat.txt hatcat2.txt cathat2.txt hatcat3.txt cathat3.txt; exit' 0 1 2 3 15
|
||||||
|
|
||||||
|
delete_tmp_files()
|
||||||
|
{
|
||||||
|
rm -f hatcat.txt cathat.txt hatcat2.txt cathat2.txt hatcat3.txt cathat3.txt
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
press_any_key()
|
||||||
|
{
|
||||||
|
echo 1>&2
|
||||||
|
read -r -n 1 -p "Press any key to continue (q = quit): " 1>&2
|
||||||
|
test "$REPLY" = "q" && delete_tmp_files && echo 1>&2 && exit
|
||||||
|
}
|
||||||
|
|
||||||
|
show_diff()
|
||||||
|
{
|
||||||
|
if [[ "$#" -ne 2 ]]; then
|
||||||
|
echo "$0: show_diff expects two args, got: $#" 1>&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "$ diff $1 $2" 1>&2
|
||||||
|
diff "$1" "$2" && echo "$1 and $2 are identical"
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "Notice how the programs are the same:" 1>&2
|
||||||
|
diff -s hatcat cathat
|
||||||
|
press_any_key
|
||||||
|
|
||||||
|
echo "Now notice how running both cathat and hatcat in different ways" 1>&2
|
||||||
|
echo "shows different output." 1>&2
|
||||||
|
press_any_key
|
||||||
|
|
||||||
|
echo "Running hatcat without a path:" 1>&2
|
||||||
|
echo "$ PATH=.:\$PATH" 1>&2
|
||||||
|
PATH=.:$PATH
|
||||||
|
echo "$ hatcat | tee hatcat.txt" 1>&2
|
||||||
|
hatcat | tee hatcat.txt
|
||||||
|
press_any_key
|
||||||
|
|
||||||
|
echo "Running cathat without a path:" 1>&2
|
||||||
|
echo "$ cathat | tee cathat.txt" 1>&2
|
||||||
|
cathat | tee cathat.txt
|
||||||
|
press_any_key
|
||||||
|
|
||||||
|
echo "Showing diff between the above two commands, 'hatcat' and './cathat':" 1>&2
|
||||||
|
show_diff hatcat.txt cathat.txt
|
||||||
|
press_any_key
|
||||||
|
|
||||||
|
echo "Now watch ./hatcat:" 1>&2
|
||||||
|
./hatcat | tee hatcat2.txt
|
||||||
|
press_any_key
|
||||||
|
|
||||||
|
echo "Now watch ./cathat:" 1>&2
|
||||||
|
./cathat | tee cathat2.txt
|
||||||
|
press_any_key
|
||||||
|
|
||||||
|
echo "Showing diff between running 'hatcat' and './hatcat':" 1>&2
|
||||||
|
show_diff hatcat.txt hatcat2.txt
|
||||||
|
press_any_key
|
||||||
|
|
||||||
|
echo "Now watch \$(pwd)/cathat" 1>&2
|
||||||
|
"$(pwd)"/cathat | tee cathat3.txt
|
||||||
|
press_any_key
|
||||||
|
|
||||||
|
echo "Finally, watch \$(pwd)/hatcat" 1>&2
|
||||||
|
"$(pwd)"/hatcat | tee hatcat3.txt
|
||||||
|
press_any_key
|
||||||
|
|
||||||
|
echo "Showing diff between running './hatcat' and './cathat':" 1>&2
|
||||||
|
show_diff hatcat2.txt cathat2.txt
|
||||||
|
press_any_key
|
||||||
|
|
||||||
|
echo "Showing diff between running '\$(pwd)/hatcat' and '\$(pwd)/cathat':" 1>&2
|
||||||
|
show_diff hatcat3.txt cathat3.txt
|
||||||
|
press_any_key
|
||||||
|
|
||||||
|
echo "Showing diff between running '\$(pwd)/hatcat' and 'hatcat':" 1>&2
|
||||||
|
show_diff hatcat3.txt hatcat.txt
|
||||||
|
press_any_key
|
||||||
|
|
||||||
|
echo "Showing diff between running '\$(pwd)/hatcat' and './hatcat':" 1>&2
|
||||||
|
show_diff hatcat3.txt hatcat2.txt
|
||||||
|
press_any_key
|
||||||
|
|
||||||
|
echo "Showing diff between running '\$(pwd)/cathat' and 'cathat':" 1>&2
|
||||||
|
show_diff cathat3.txt cathat.txt
|
||||||
|
press_any_key
|
||||||
|
|
||||||
|
echo "Showing diff between running '\$(pwd)/cathat' and './cathat':" 1>&2
|
||||||
|
show_diff cathat3.txt cathat2.txt
|
||||||
|
press_any_key
|
||||||
|
|
||||||
|
# remove temporary files
|
||||||
|
rm -f hatcat.txt cathat.txt hatcat2.txt cathat2.txt hatcat3.txt cathat3.txt
|
||||||
|
|
||||||
|
echo 1>&2
|
||||||
|
echo "Now answer: why did some of the same programs execute differently?" 1>&2
|
||||||
@@ -62,7 +62,7 @@ CDEFINE=
|
|||||||
|
|
||||||
# Include files that are needed to compile
|
# Include files that are needed to compile
|
||||||
#
|
#
|
||||||
CINCLUDE=
|
CINCLUDE= -include stdio.h
|
||||||
|
|
||||||
# Optimization
|
# Optimization
|
||||||
#
|
#
|
||||||
|
|||||||
+14
-8
@@ -5,22 +5,28 @@ make all
|
|||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### Bugs and (Mis)features:
|
||||||
|
|
||||||
|
The current status of this entry is:
|
||||||
|
|
||||||
|
```
|
||||||
|
STATUS: uses gets() - change to fgets() if possible
|
||||||
|
```
|
||||||
|
|
||||||
|
For more detailed information see [1996 huffman in bugs.md](/bugs.md#1996-huffman).
|
||||||
|
|
||||||
|
|
||||||
## To use:
|
## To use:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
echo 'Huffman Decoding' | ./huffman
|
echo 'Huffman Decoding' | ./huffman
|
||||||
```
|
```
|
||||||
|
|
||||||
NOTE: this program uses `gets()` so you will likely get a warning when compiling
|
|
||||||
and/or running on modern systems.
|
|
||||||
|
|
||||||
|
|
||||||
### Try:
|
### Try:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
echo 'seeing or feeling is believing' | ./huffman
|
./try.sh
|
||||||
echo 'CC OR NOT CC' | ./huffman
|
|
||||||
echo 'CC OR NOT CC' | ./huffman | ./huffman
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
@@ -34,7 +40,7 @@ And for a misleading hint, consider who won! :-)
|
|||||||
And if you really can't see what is going on, here is an extra spoiler:
|
And if you really can't see what is going on, here is an extra spoiler:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
./huffman < huffman.c
|
./huffman < huffman.c 2>/dev/null
|
||||||
```
|
```
|
||||||
|
|
||||||
This entry was very well received at the IOCCC BOF.
|
This entry was very well received at the IOCCC BOF.
|
||||||
@@ -46,7 +52,7 @@ This filter program is really not obfuscated code. It compiles cleanly
|
|||||||
with an ANSI C compiler and comes with user documentation that even a
|
with an ANSI C compiler and comes with user documentation that even a
|
||||||
blind person could read.
|
blind person could read.
|
||||||
|
|
||||||
The program is a bidirectional filter with the output of the program\
|
The program is a bidirectional filter with the output of the program
|
||||||
suitable for its input. The output of this program, when used as input,
|
suitable for its input. The output of this program, when used as input,
|
||||||
undoes the original program filtering.
|
undoes the original program filtering.
|
||||||
|
|
||||||
|
|||||||
Executable
+13
@@ -0,0 +1,13 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
make all >/dev/null || exit 1
|
||||||
|
|
||||||
|
|
||||||
|
echo "$ echo 'seeing or feeling is believing' | ./huffman" 1>&2
|
||||||
|
echo 'seeing or feeling is believing' | ./huffman 2>/dev/null
|
||||||
|
|
||||||
|
echo "$ echo 'CC OR NOT CC' | ./huffman" 1>&2
|
||||||
|
echo 'CC OR NOT CC' | ./huffman 2>/dev/null
|
||||||
|
|
||||||
|
echo "$ $ echo 'CC OR NOT CC' | ./huffman | ./huffman" 1>&2
|
||||||
|
echo 'CC OR NOT CC' | ./huffman 2>/dev/null | ./huffman 2>/dev/null
|
||||||
+8
-2
@@ -23,7 +23,7 @@ For more information try:
|
|||||||
|
|
||||||
## Judges' remarks:
|
## Judges' remarks:
|
||||||
|
|
||||||
For a good noop try:
|
For a good no-op try:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
gzip -c < rcm.c | ./rcm
|
gzip -c < rcm.c | ./rcm
|
||||||
@@ -39,22 +39,27 @@ similar unimportant fluff, this program is a fully compliant
|
|||||||
`gzip` compressed file on standard input, and it will write the fully
|
`gzip` compressed file on standard input, and it will write the fully
|
||||||
uncompressed original file to standard output.
|
uncompressed original file to standard output.
|
||||||
|
|
||||||
|
|
||||||
### ObJustifications for this entry:
|
### ObJustifications for this entry:
|
||||||
|
|
||||||
|
|
||||||
#### The Design Trade-off Argument:
|
#### The Design Trade-off Argument:
|
||||||
|
|
||||||
"The 184 characters worth of defines in the build file have been
|
"The 184 characters worth of defines in the build file have been
|
||||||
carefully offset by 184 redundant and unnecessary '`{`', '`}`', and '`;`'
|
carefully offset by 184 redundant and unnecessary '`{`', '`}`', and '`;`'
|
||||||
characters in the source file."
|
characters in the source file."
|
||||||
|
|
||||||
|
|
||||||
#### The Design Review Argument:
|
#### The Design Review Argument:
|
||||||
|
|
||||||
"Using only 216 characters out of a maximum of 256, the build file
|
"Using only 216 characters out of a maximum of 256, the build file
|
||||||
meets and actually exceeds specification."
|
meets and actually exceeds specification."
|
||||||
|
|
||||||
|
|
||||||
#### The Program Metrics Argument:
|
#### The Program Metrics Argument:
|
||||||
|
|
||||||
"The program source is less than 3,100 characters in length and uncompresses file
|
"The program source is less than 3,100 characters in length and uncompresses the
|
||||||
|
file
|
||||||
[emacs-19.34b.tar.gz](https://ftp.gnu.org/old-gnu/emacs/emacs-19.34b.tar.gz) in
|
[emacs-19.34b.tar.gz](https://ftp.gnu.org/old-gnu/emacs/emacs-19.34b.tar.gz) in
|
||||||
about 130 seconds on my HP 9000/735. The now obsolete source file `inflate.c'
|
about 130 seconds on my HP 9000/735. The now obsolete source file `inflate.c'
|
||||||
from the GNU gzip source tree is 31,613 characters in length and uncompresses
|
from the GNU gzip source tree is 31,613 characters in length and uncompresses
|
||||||
@@ -67,6 +72,7 @@ the emacs distribution file in slightly under 25 seconds. Thus:
|
|||||||
which represents a better than 530% improvement in the ratio of
|
which represents a better than 530% improvement in the ratio of
|
||||||
source file size to execution time."
|
source file size to execution time."
|
||||||
|
|
||||||
|
|
||||||
#### The Whining Programmer's Argument:
|
#### The Whining Programmer's Argument:
|
||||||
|
|
||||||
"The inflate algorithm requires that over 400 characters worth
|
"The inflate algorithm requires that over 400 characters worth
|
||||||
|
|||||||
+20
-15
@@ -23,8 +23,8 @@ To find the day that Easter falls on in the current year:
|
|||||||
|
|
||||||
## Judges' remarks:
|
## Judges' remarks:
|
||||||
|
|
||||||
Look at the source. There is something very odd going on here.\
|
Look at the source. There is something very odd going on here.
|
||||||
Where does the real code come from if everything is a C pre-processor\
|
Where does the real code come from if everything is a C pre-processor
|
||||||
statement?
|
statement?
|
||||||
|
|
||||||
Clearly this is either the Best Use or the Worst Abuse of the
|
Clearly this is either the Best Use or the Worst Abuse of the
|
||||||
@@ -39,10 +39,12 @@ This program is an implementation of an algorithm that calculates
|
|||||||
the date of the Sunday following the first full moon after the
|
the date of the Sunday following the first full moon after the
|
||||||
spring equinox. (Also known as "Easter", defined this way by the
|
spring equinox. (Also known as "Easter", defined this way by the
|
||||||
Nicaean Concilium in 325 Anno Domini.) The algorithm is attributed
|
Nicaean Concilium in 325 Anno Domini.) The algorithm is attributed
|
||||||
to the famous mathematician Carl Friedrich Gauss ["Meyers Handbuch
|
to the famous mathematician [Carl Friedrich
|
||||||
ueber das Weltall", Meyer, 5th Edition, 1973, p149] and is suitable
|
Gauss](https://en.wikipedia.org/wiki/Carl_Friedrich_Gauss) ["Meyers Handbuch
|
||||||
for anni domini within the Gregorian Calendar, that is, from 1582 AD
|
ueber das Weltall" 'Handbook About Space', Meyer, 5th Edition, 1973, p149] and is suitable
|
||||||
to 2199 AD:
|
for anni domini within the [Gregorian
|
||||||
|
Calendar](https://en.wikipedia.org/wiki/Gregorian_calendar), that is, from ad 1582
|
||||||
|
to ad 2199:
|
||||||
|
|
||||||
```
|
```
|
||||||
Let J be the year.
|
Let J be the year.
|
||||||
@@ -70,18 +72,18 @@ with the following exceptions:
|
|||||||
|
|
||||||
```
|
```
|
||||||
April 26 must always be changed to April 19
|
April 26 must always be changed to April 19
|
||||||
April 25 must be changed to April 18 if d is 28 and a greater than 10
|
April 25 must be changed to April 18 if d is 28 and a is greater than 10
|
||||||
```
|
```
|
||||||
|
|
||||||
### Example:
|
### Example:
|
||||||
|
|
||||||
```
|
```
|
||||||
J = 1962, M = 24, N = 5
|
J = 1962, M = 24, N = 5
|
||||||
a = J % 19 = 5
|
a = J % 19 == 5
|
||||||
b = J % 4 = 2
|
b = J % 4 == 2
|
||||||
c = J % 7 = 2
|
c = J % 7 == 2
|
||||||
d = 119 % 30 = 29
|
d = 119 % 30 == 29
|
||||||
e = 191 % 7 = 2
|
e = 191 % 7 == 2
|
||||||
```
|
```
|
||||||
|
|
||||||
March 53 is invalid, so the result is April 22 1962.
|
March 53 is invalid, so the result is April 22 1962.
|
||||||
@@ -101,7 +103,7 @@ Nobody can learn that by heart so I gently remind the reader by
|
|||||||
defining a macro that expresses this clearly (line 25). This goes up
|
defining a macro that expresses this clearly (line 25). This goes up
|
||||||
to the definition of a translation unit. Unfortunately, due to the
|
to the definition of a translation unit. Unfortunately, due to the
|
||||||
IOCCC's size restrictions, I had to abbreviate some syntactic
|
IOCCC's size restrictions, I had to abbreviate some syntactic
|
||||||
elements. "ae" actually reads "assignment expression". I had to stop
|
elements. `ae` actually reads "assignment expression". I had to stop
|
||||||
at some arbitrary point, so don't waste your time trying to find out
|
at some arbitrary point, so don't waste your time trying to find out
|
||||||
how preprocessing tokens form type qualifier lists, cast expressions
|
how preprocessing tokens form type qualifier lists, cast expressions
|
||||||
or direct abstract declarators. Assuming the reader knows about
|
or direct abstract declarators. Assuming the reader knows about
|
||||||
@@ -109,9 +111,10 @@ these easy to remember language elements is justified in my opinion.
|
|||||||
|
|
||||||
|
|
||||||
### The moral:
|
### The moral:
|
||||||
\
|
|
||||||
Try to be as precise as can be and no one will comprehend what you mean.
|
Try to be as precise as can be and no one will comprehend what you mean.
|
||||||
|
|
||||||
|
|
||||||
#### The formula:
|
#### The formula:
|
||||||
|
|
||||||
|
|
||||||
@@ -119,6 +122,7 @@ Try to be as precise as can be and no one will comprehend what you mean.
|
|||||||
comprehension = 1/(2**precision)
|
comprehension = 1/(2**precision)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
#### The interpretation:
|
#### The interpretation:
|
||||||
|
|
||||||
"Say nothing and everybody will understand."
|
"Say nothing and everybody will understand."
|
||||||
@@ -130,7 +134,8 @@ This leads to an error due to the redefinition of main. The `-I` option makes
|
|||||||
sure the working /usr/include/errno.h is found first, which shouldn't cause any
|
sure the working /usr/include/errno.h is found first, which shouldn't cause any
|
||||||
problems on other systems.
|
problems on other systems.
|
||||||
|
|
||||||
### Usage
|
|
||||||
|
### Usage:
|
||||||
|
|
||||||
The program is run without arguments. It prints all dates in order.
|
The program is run without arguments. It prints all dates in order.
|
||||||
|
|
||||||
|
|||||||
+22
-16
@@ -25,7 +25,7 @@ The program accepts up to 4 parameters:
|
|||||||
### Try:
|
### Try:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
./schweikh2 15 1 0 0/0
|
./try.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
What happens if you pass only three parameters like the below?
|
What happens if you pass only three parameters like the below?
|
||||||
@@ -40,15 +40,20 @@ The author also suggests:
|
|||||||
while :; do grep -v '#' schweikh2.c; done
|
while :; do grep -v '#' schweikh2.c; done
|
||||||
```
|
```
|
||||||
|
|
||||||
(and we do too) which works with `sh`, `bash`, `ksh` and `zsh` as well.
|
(and we do too) which works with `sh`, `bash`, `ksh` and `zsh` as well. Press
|
||||||
|
ctrl-c to stop it. Observe how the [try.sh](try.sh) script does this a number of
|
||||||
|
times.
|
||||||
|
|
||||||
|
|
||||||
## Judges' remarks:
|
## Judges' remarks:
|
||||||
|
|
||||||
The original program, with only slight obfuscations, may be found
|
The original program, with only slight obfuscations, may be found
|
||||||
in `hunni.c`. The perl script, obfuscates it appropriately:
|
in [hunni.c](hunni.c). The perl script, [hunni.pl](hunni.pl), obfuscates it
|
||||||
|
appropriately. Try:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
|
less hunni.c
|
||||||
|
|
||||||
perl ./hunni.pl < hunni.c
|
perl ./hunni.pl < hunni.c
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -60,6 +65,7 @@ This entry was another crowd pleaser at the IOCCC BOF.
|
|||||||
Note: the source must be viewed with tabstop 8. To appreciate the
|
Note: the source must be viewed with tabstop 8. To appreciate the
|
||||||
beauty have your eyes half closed.
|
beauty have your eyes half closed.
|
||||||
|
|
||||||
|
|
||||||
### Why I think this program is obfuscated:
|
### Why I think this program is obfuscated:
|
||||||
|
|
||||||
C is a free format language. It is therefore a question of style how
|
C is a free format language. It is therefore a question of style how
|
||||||
@@ -69,16 +75,16 @@ I put spaces around operators, after opening braces and before closing
|
|||||||
braces. I have generalized this rule by putting whitespace after *any*
|
braces. I have generalized this rule by putting whitespace after *any*
|
||||||
non-white space character (with the exception of preprocessor directives).
|
non-white space character (with the exception of preprocessor directives).
|
||||||
There are no recognizable keywords anymore. There are no recognizable
|
There are no recognizable keywords anymore. There are no recognizable
|
||||||
string literals any more. The main function is invisible. All operators
|
string literals any more. The `main()` function is invisible. All operators
|
||||||
longer than one character have gone. They have been replaced by macro
|
longer than one character are gone. They have been replaced by macro
|
||||||
calls with quite a number of arguments. The keys are the token pasting
|
calls with quite a number of arguments. The keys are the token pasting
|
||||||
and stringizing macros e and O. The "arcane rules of token pasting"
|
and stringizing macros `e` and `O`. The "arcane rules of token pasting"
|
||||||
[K&R2] are used up to three levels, `H(O,r)R(O,r)` (!) which is needed to make
|
[K&R2] are used up to three levels: `H(O,r)R(O,r)` (!) which is needed to make
|
||||||
one 8-character token from 8 characters ('unsigned'). BTW, C has no 9 or
|
one 8-character token from 8 characters (`unsigned`). BTW, C has no 9 or
|
||||||
more character reserved words, so a fourth level is only required if
|
more character reserved words, so a fourth level is only required if
|
||||||
you intend to generate object names from 9 or more components. The final
|
you intend to generate object names from 9 or more components. The final
|
||||||
round even swaps the tokens, so all keywords must be spelled backwards
|
round even swaps the tokens, so all keywords must be spelled backwards
|
||||||
(sort of, can you spot printf in the P macro?).
|
(sort of, can you spot `printf` in the `P` macro?).
|
||||||
|
|
||||||
Try to indent the source. The unbalanced parentheses confuse Solaris'
|
Try to indent the source. The unbalanced parentheses confuse Solaris'
|
||||||
indent to the max (although the result does compile):
|
indent to the max (although the result does compile):
|
||||||
@@ -112,18 +118,18 @@ divided by their greatest common divisor.
|
|||||||
|
|
||||||
The program accepts up to 4 parameters:
|
The program accepts up to 4 parameters:
|
||||||
|
|
||||||
1. The number of operators in the expression [default: 9]
|
1. The number of operators in the expression [default: 9].
|
||||||
2. The value of the first operand [1]
|
2. The value of the first operand [1].
|
||||||
3. The (possibly negative) increment to the next operand [1]
|
3. The (possibly negative) increment to the next operand [1].
|
||||||
4. The goal value or 0/0 [42]
|
4. The goal value or 0/0 [42].
|
||||||
|
|
||||||
On ANSI/ISO C conformant systems (where long is at least 32 bits)
|
On ANSI/ISO C conformant systems (where `long` is at least 32 bits)
|
||||||
overflow will occur in the default case (first operand 1, increment 1)
|
overflow will occur in the default case (first operand 1, increment 1)
|
||||||
only for more than 11 operators. Because a bit mask is used that needs
|
only for more than 11 operators. Because a bit mask is used that needs
|
||||||
twice the number of operands in bits (plus a sentinel value) on those
|
twice the number of operands in bits (plus a sentinel value) on those
|
||||||
systems the first parameter must not exceed 15.
|
systems the first parameter must not exceed 15.
|
||||||
|
|
||||||
If long is at least 64 bits overflow will occur for more than 19
|
If `long` is at least 64 bits overflow will occur for more than 19
|
||||||
operators but you will probably wait quite some time for every of the
|
operators but you will probably wait quite some time for every of the
|
||||||
`4^19 = 274,877,906,944` combinations to be evaluated... While I'm at it,
|
`4^19 = 274,877,906,944` combinations to be evaluated... While I'm at it,
|
||||||
on a 50 MHz SPARC, `4^11` expressions are evaluated in about 3 cpu
|
on a 50 MHz SPARC, `4^11` expressions are evaluated in about 3 cpu
|
||||||
@@ -142,7 +148,7 @@ minutes (`gcc -O3`).
|
|||||||
|
|
||||||
### Miscellaneous
|
### Miscellaneous
|
||||||
|
|
||||||
The diamond pattern can be continued without a break.\
|
The diamond pattern can be continued without a break.
|
||||||
For a nice printout try this on your Bourne compatible shell:
|
For a nice printout try this on your Bourne compatible shell:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
|
|||||||
Executable
+18
@@ -0,0 +1,18 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
make all >/dev/null || exit 1
|
||||||
|
|
||||||
|
|
||||||
|
read -r -n 1 -p "Press any key to to run ./schweikh2: " 1>&2
|
||||||
|
./schweikh2
|
||||||
|
echo >&2
|
||||||
|
|
||||||
|
read -r -n 1 -p "Press any key to run: ./schweikh2 15 1 0 0/0 | head -n 15: " 1>&2
|
||||||
|
./schweikh2 15 1 0 0/0 | head -n 15
|
||||||
|
echo >&2
|
||||||
|
|
||||||
|
read -r -n 1 -p "Press any key one more time: " 1>&2
|
||||||
|
i=0
|
||||||
|
while ((i++<15)); do
|
||||||
|
grep -v '#' schweikh2.c
|
||||||
|
done
|
||||||
+30
-27
@@ -47,19 +47,19 @@ NOTE: On some systems such as SunOS, one may need to compile with:
|
|||||||
### Why I think my entry is obfuscated
|
### Why I think my entry is obfuscated
|
||||||
|
|
||||||
There are some layout obfuscations that hinder readability, like
|
There are some layout obfuscations that hinder readability, like
|
||||||
some (but not all) one character tokens in column 1. Includes,
|
some (but not all) one character tokens in column 1. `#include`s,
|
||||||
defines and declarations of data and functions appear intermixed.
|
`#define`s and declarations of data and functions appear intermixed.
|
||||||
iso646.h is even included in the middle of an expression, how
|
`iso646.h` is even included in the middle of an expression, how
|
||||||
disgusting. Besides, requiring iso646.h will render the program
|
disgusting. Besides, requiring `iso646.h` will render the program
|
||||||
uncompilable on many systems that have not yet incorporated
|
uncompilable on many systems that have not yet incorporated
|
||||||
Amendment One to The Standard. If you, dear reader, suffer from
|
Amendment One to The Standard. If you, dear reader, suffer from
|
||||||
this disease, just read iso646.h.
|
this disease, just read `iso646.h`.
|
||||||
|
|
||||||
There are no `if' statements. They have been replaced by
|
There are no `if' statements. They have been replaced by
|
||||||
"switch () case 1:" or "switch () case 0:" etc. At least one
|
`switch () case 1:` or `switch () case 0:` etc. At least one
|
||||||
switch has a declaration after the opening brace, booh!
|
`switch` has a declaration after the opening brace, booh!
|
||||||
Identifiers are named after random programming languages, Basic,
|
Identifiers are named after random programming languages, BASIC (as `Basic`),
|
||||||
Cobol, F77, awk etc.
|
COBOL, F77, awk etc.
|
||||||
|
|
||||||
You have to select maximum ANSI C conformance of your
|
You have to select maximum ANSI C conformance of your
|
||||||
compiler. The source fails to compile under a C++ compiler due to
|
compiler. The source fails to compile under a C++ compiler due to
|
||||||
@@ -94,15 +94,15 @@ The source fails to compile on obsolete systems with obsolete
|
|||||||
memory models due to the identifier `far` (to be honest: this is
|
memory models due to the identifier `far` (to be honest: this is
|
||||||
untested :-) ).
|
untested :-) ).
|
||||||
|
|
||||||
Does your indent cope with backslash/newline pairs inbetween
|
Does your indent cope with backslash/newline pairs in between keywords like in
|
||||||
keywords like in "re\<newline>turn"? Solaris' indent inserts spaces\
|
`re\turn` where the `re\` is at the end of a line? ? Solaris' indent inserts
|
||||||
and thereby renders the source uncompilable...
|
spaces and thereby renders the source uncompilable...
|
||||||
|
|
||||||
The indented source will exhibit different semantics when indenting
|
The indented source will exhibit different semantics when indenting
|
||||||
changes the number of lines (due to using the `__LINE__` macro in an
|
changes the number of lines (due to using the `__LINE__` macro in an
|
||||||
expression).
|
expression).
|
||||||
|
|
||||||
And what about sizeof `__TIME__`? This one's for the philosophers\
|
And what about `sizeof __TIME__`? This one's for the philosophers
|
||||||
and physicists among us programmers. What is it? `sizeof (char *)`? -- no.
|
and physicists among us programmers. What is it? `sizeof (char *)`? -- no.
|
||||||
`strlen ("hh:mm:ss")`? -- no. It's the same as `sizeof __DATE__ -
|
`strlen ("hh:mm:ss")`? -- no. It's the same as `sizeof __DATE__ -
|
||||||
sizeof "no"` :-)
|
sizeof "no"` :-)
|
||||||
@@ -114,22 +114,22 @@ possible execution paths.
|
|||||||
### What this program does
|
### What this program does
|
||||||
|
|
||||||
This program tests your operating system's allocation honesty. It
|
This program tests your operating system's allocation honesty. It
|
||||||
forks a child that will allocate as much as possible with byte
|
forks a child that will allocate as much memory as possible with byte
|
||||||
granularity and then write to every 1024th byte, at the same time
|
granularity and then write to every 1024th byte, at the same time
|
||||||
writing a status report on stdout. This way each page of the
|
writing a status report on `stdout`. This way each page of the
|
||||||
allocated virtual memory will eventually be referenced. Without
|
allocated virtual memory will eventually be referenced. Without
|
||||||
any arguments, malloc() will be used to allocate memory. If the
|
any arguments, `malloc(3)` will be used to allocate memory. If the
|
||||||
first arg starts with c, calloc() will be used instead.
|
first arg starts with `c`, `calloc(3)` will be used instead.
|
||||||
|
|
||||||
I distinguish three different behaviours:
|
I distinguish three different behaviours:
|
||||||
|
|
||||||
1. OS without memory overcommit: malloc does not lie -- you can use all memory
|
1. OS without memory overcommit: `malloc(3)` does not lie -- you can use all memory
|
||||||
the OS granted to you.
|
the OS granted to you.
|
||||||
|
|
||||||
2. OS with memory overcommit: malloc lies -- any program may get killed at
|
2. OS with memory overcommit: `malloc(3)` lies -- any program may get killed at
|
||||||
random when the OS can not acquire a free page.
|
random when the OS can not acquire a free page.
|
||||||
|
|
||||||
3. OS with pseudo memory overcommit: malloc lies -- The OS puts processes to
|
3. OS with pseudo memory overcommit: `malloc(3)` lies -- The OS puts processes to
|
||||||
sleep for which it can not acquire a free page. Because other processes are also
|
sleep for which it can not acquire a free page. Because other processes are also
|
||||||
affected this way, the system slows down and quickly becomes totally unusable
|
affected this way, the system slows down and quickly becomes totally unusable
|
||||||
(also known as "thrashing"). Because more and more processes wait for memory
|
(also known as "thrashing"). Because more and more processes wait for memory
|
||||||
@@ -137,31 +137,34 @@ returned by other exiting processes the system eventually enters a deadlock
|
|||||||
situation and effectively halts.
|
situation and effectively halts.
|
||||||
|
|
||||||
I had the pleasure and pain to find all three behaviours on the
|
I had the pleasure and pain to find all three behaviours on the
|
||||||
platforms I use regularly. What follows are the outputs for
|
platforms I use regularly.
|
||||||
|
|
||||||
|
The file [schweikh3.info](schweikh3.info) has output for
|
||||||
Solaris, FreeBSD and Linux. The Linux case is interesting in that
|
Solaris, FreeBSD and Linux. The Linux case is interesting in that
|
||||||
the behaviour changes when calloc is used instead of malloc.
|
the behaviour changes when `calloc(3)` is used instead of `malloc(3)`.
|
||||||
For FreeBSD, the last two lines are not messages stemming from
|
For FreeBSD, the last two lines are not messages stemming from
|
||||||
my program but issued by the syslog daemon.
|
my program but issued by the syslog daemon.
|
||||||
|
|
||||||
|
|
||||||
### Implementation remarks
|
### Implementation remarks
|
||||||
|
|
||||||
How can we distinguish the three different OS types from the
|
How can we distinguish the three different OS types from the
|
||||||
table above?
|
table above?
|
||||||
|
|
||||||
Obviously, type 1), no overcommit, is easy.
|
Obviously, type (1), no overcommit, is easy.
|
||||||
|
|
||||||
For type 2), random kill, we need to fork a child that can be killed
|
For type (2), random kill, we need to fork a child that can be killed
|
||||||
and whose exit status the parent collects and decodes. Here's
|
and whose exit status the parent collects and decodes. Here's
|
||||||
where POSIX enters the scene.
|
where POSIX enters the scene.
|
||||||
|
|
||||||
Type 3), thrashing, was the hardest part. The first attempt was to
|
Type (3), thrashing, was the hardest part. The first attempt was to
|
||||||
measure the elapsed processor time it takes to write a single byte
|
measure the elapsed processor time it takes to write a single byte
|
||||||
(using `clock()`). If a certain threshold is reached I assume the
|
(using `clock()`). If a certain threshold is reached I assume the
|
||||||
system is thrashing. When thrashing, however, the process does not
|
system is thrashing. When thrashing, however, the process does not
|
||||||
consume processor time in a noticeable amount any longer and I lose.
|
consume processor time in a noticeable amount any longer and I lose.
|
||||||
So I switched to measuring wall clock time using `time()`. On the one
|
So I switched to measuring wall clock time using `time(3)`. On the one
|
||||||
system that I observe thrashing (Linux) this works (although the
|
system that I observe thrashing (Linux) this works (although the
|
||||||
value returned by time seems to 'hang' sometimes when the OS thrashes.
|
value returned by `time(3)` seems to 'hang' sometimes when the OS thrashes.
|
||||||
Exceeding a threshold of 5 seconds may be detected only after half a
|
Exceeding a threshold of 5 seconds may be detected only after half a
|
||||||
minute or so.
|
minute or so.
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
***** SOLARIS 2.5 (sparc):
|
***** SOLARIS 2.5 (sparc):
|
||||||
|
|
||||||
% prog
|
% schweikh3
|
||||||
Trying to malloc 2048M+0K+0 bytes..nope
|
Trying to malloc 2048M+0K+0 bytes..nope
|
||||||
Trying to malloc 1024M+0K+0 bytes..nope
|
Trying to malloc 1024M+0K+0 bytes..nope
|
||||||
Trying to malloc 512M+0K+0 bytes..nope
|
Trying to malloc 512M+0K+0 bytes..nope
|
||||||
@@ -41,7 +41,7 @@
|
|||||||
|
|
||||||
***** FreeBSD 2.1 (i386):
|
***** FreeBSD 2.1 (i386):
|
||||||
|
|
||||||
% prog
|
% schweikh3
|
||||||
Trying to malloc 2048M+0K+0 bytes..nope
|
Trying to malloc 2048M+0K+0 bytes..nope
|
||||||
Trying to malloc 1024M+0K+0 bytes..nope
|
Trying to malloc 1024M+0K+0 bytes..nope
|
||||||
Trying to malloc 512M+0K+0 bytes..nope
|
Trying to malloc 512M+0K+0 bytes..nope
|
||||||
@@ -82,7 +82,7 @@
|
|||||||
Nov 24 18:11:56 /kernel: swap_pager: out of space
|
Nov 24 18:11:56 /kernel: swap_pager: out of space
|
||||||
Nov 24 18:11:57 /kernel: Process 5 killed by vm_fault -- out of swap
|
Nov 24 18:11:57 /kernel: Process 5 killed by vm_fault -- out of swap
|
||||||
|
|
||||||
% prog c
|
% schweikh3 c
|
||||||
Trying to calloc 2048M+0K+0 bytes..nope
|
Trying to calloc 2048M+0K+0 bytes..nope
|
||||||
Trying to calloc 1024M+0K+0 bytes..nope
|
Trying to calloc 1024M+0K+0 bytes..nope
|
||||||
Trying to calloc 512M+0K+0 bytes..nope
|
Trying to calloc 512M+0K+0 bytes..nope
|
||||||
@@ -96,7 +96,7 @@
|
|||||||
|
|
||||||
***** Linux 1.2.13 (i386):
|
***** Linux 1.2.13 (i386):
|
||||||
|
|
||||||
% prog
|
% schweikh3
|
||||||
Trying to malloc 2048M+0K+0 bytes..nope
|
Trying to malloc 2048M+0K+0 bytes..nope
|
||||||
Trying to malloc 1024M+0K+0 bytes..nope
|
Trying to malloc 1024M+0K+0 bytes..nope
|
||||||
Trying to malloc 512M+0K+0 bytes..nope
|
Trying to malloc 512M+0K+0 bytes..nope
|
||||||
@@ -132,7 +132,7 @@
|
|||||||
Able to malloc 23M+1023K+1023 bytes
|
Able to malloc 23M+1023K+1023 bytes
|
||||||
23294 kilo bytes ok malloc lied! Thrashing
|
23294 kilo bytes ok malloc lied! Thrashing
|
||||||
|
|
||||||
% prog c
|
% schweikh3 c
|
||||||
Trying to calloc 2048M+0K+0 bytes..nope
|
Trying to calloc 2048M+0K+0 bytes..nope
|
||||||
Trying to calloc 1024M+0K+0 bytes..nope
|
Trying to calloc 1024M+0K+0 bytes..nope
|
||||||
Trying to calloc 512M+0K+0 bytes..nope
|
Trying to calloc 512M+0K+0 bytes..nope
|
||||||
|
|||||||
@@ -39,7 +39,8 @@ include ../../var.mk
|
|||||||
# Common C compiler warnings to silence
|
# Common C compiler warnings to silence
|
||||||
#
|
#
|
||||||
CSILENCE= -Wno-char-subscripts -Wno-error -Wno-implicit-function-declaration \
|
CSILENCE= -Wno-char-subscripts -Wno-error -Wno-implicit-function-declaration \
|
||||||
-Wno-int-to-pointer-cast -Wno-empty-body -Wno-deprecated-non-prototype
|
-Wno-int-to-pointer-cast -Wno-empty-body -Wno-deprecated-non-prototype\
|
||||||
|
-Wno-implicit-int
|
||||||
|
|
||||||
# Common C compiler warning flags
|
# Common C compiler warning flags
|
||||||
#
|
#
|
||||||
@@ -109,7 +110,7 @@ ENTRY= westley
|
|||||||
PROG= ${ENTRY}
|
PROG= ${ENTRY}
|
||||||
#
|
#
|
||||||
OBJ= ${PROG}.o
|
OBJ= ${PROG}.o
|
||||||
DATA= clock1 clock2 clock3
|
DATA= clock1.sh clock2.sh clock3.sh
|
||||||
TARGET= ${PROG}
|
TARGET= ${PROG}
|
||||||
#
|
#
|
||||||
ALT_OBJ= westley.alt.o
|
ALT_OBJ= westley.alt.o
|
||||||
|
|||||||
+27
-30
@@ -4,51 +4,46 @@
|
|||||||
make all
|
make all
|
||||||
```
|
```
|
||||||
|
|
||||||
|
There is another version which is the original entry. See [alternate
|
||||||
|
version](#alternate-code) for details as to how to use and why it was made the
|
||||||
|
alt version.
|
||||||
|
|
||||||
|
|
||||||
## To use:
|
## To use:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
sh ./clock1
|
./clock1.sh
|
||||||
|
./clock2.sh
|
||||||
|
./clock3.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
NOTE: the original version had a display problem in modern systems which
|
|
||||||
somewhat affected the usability of the program. See the Alternate code section
|
|
||||||
for details on the original version.
|
|
||||||
|
|
||||||
|
|
||||||
### Try:
|
### Try:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
sh ./clock2
|
./try.sh
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
And for a good time, try:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
sh ./clock3
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## Alternate code:
|
## Alternate code:
|
||||||
|
|
||||||
An alternate version of this entry, [westley.alt.c](westley.alt.c), is provided.
|
The original version had a display problem in modern systems which somewhat
|
||||||
This version is the original code and does not contain the above mentioned
|
affected the usability of the program. This alternate code, the original, is
|
||||||
fixes.
|
provided, to show the differences.
|
||||||
|
|
||||||
|
### Alternate build:
|
||||||
|
|
||||||
To compile this alternate version:
|
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
make alt
|
make alt
|
||||||
```
|
```
|
||||||
|
|
||||||
To use it with the scripts try:
|
|
||||||
|
### Alternate try:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
WESTLEY=./westley.alt ./clock1
|
./try.alt.sh
|
||||||
WESTLEY=./westley.alt ./clock2
|
|
||||||
WESTLEY=./westley.alt ./clock3
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
@@ -66,7 +61,8 @@ This 1-line program allows various analog ASCII clocks to print out the time;
|
|||||||
the ASCII clock is built from the command line arguments, so many different
|
the ASCII clock is built from the command line arguments, so many different
|
||||||
types of clocks can be generated. Three different scripts are supplied to print
|
types of clocks can be generated. Three different scripts are supplied to print
|
||||||
out a grandfather clock, a mantle clock that runs backwards, and a linear-style
|
out a grandfather clock, a mantle clock that runs backwards, and a linear-style
|
||||||
clock. (they are `clock1`, `clock2`, and `clock3`)
|
clock. (they are [clock1.sh](clock1.sh), [clock2.sh](clock2.sh), and
|
||||||
|
[clock3.sh](clock3.sh))
|
||||||
|
|
||||||
The program makes the following (possibly non-portable) assumptions:
|
The program makes the following (possibly non-portable) assumptions:
|
||||||
|
|
||||||
@@ -74,8 +70,8 @@ The program makes the following (possibly non-portable) assumptions:
|
|||||||
|
|
||||||
2. `argv[0]` can be written to as if it were a `long *`.
|
2. `argv[0]` can be written to as if it were a `long *`.
|
||||||
|
|
||||||
3. The first three elements of the struct * returned by localtime() are seconds,
|
3. The first three elements of the `struct *` returned by `localtime(3)` are
|
||||||
minutes, hours, and all are ints.
|
seconds, minutes, hours, and all are `int`s.
|
||||||
|
|
||||||
4. My sample scripts assume ASCII, though this is not inherent in the code, just
|
4. My sample scripts assume ASCII, though this is not inherent in the code, just
|
||||||
my sample scripts.
|
my sample scripts.
|
||||||
@@ -83,6 +79,7 @@ my sample scripts.
|
|||||||
These assumptions are pretty reasonable. 2) can be eliminated but makes the code
|
These assumptions are pretty reasonable. 2) can be eliminated but makes the code
|
||||||
larger.
|
larger.
|
||||||
|
|
||||||
|
|
||||||
The code is simple; the arguments passed are:
|
The code is simple; the arguments passed are:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
@@ -94,14 +91,14 @@ values, looks up the offsets in `minute_map` and `hour_map`
|
|||||||
and writes the `hand_symbol` for each into the `clock_image`
|
and writes the `hand_symbol` for each into the `clock_image`
|
||||||
string. This string is then printed.
|
string. This string is then printed.
|
||||||
|
|
||||||
The for() loop starts by calling `time()` with `argv[0]`, so
|
The `for()` loop starts by calling `time()` with `argv[0]`, so
|
||||||
the time value (a long) is written into the program name.
|
the time value (a `long`) is written into the program name.
|
||||||
The for() control value is `argc`, which starts at `5`, but
|
The `for()` control value is `argc`, which starts at `5`, but
|
||||||
the `/=2` statement is executed before the test, so the for()
|
the `/=2` statement is executed before the test, so the `for()`
|
||||||
loop is executed twice, with `h=2`, then `h=1` (for hour & minute).
|
loop is executed twice, with `h=2`, then `h=1` (for hour & minute).
|
||||||
|
|
||||||
The statement of the for() loop takes the hour or minute
|
The statement of the `for()` loop takes the hour or minute
|
||||||
field of the struct returned by `localtime()` by casting it
|
field of the struct returned by `localtime(3)` by casting it
|
||||||
to an `int *` and dereferencing element `[h]`. It is slightly
|
to an `int *` and dereferencing element `[h]`. It is slightly
|
||||||
smaller to use the trick `h[(int*)localtime(*m)]` instead of
|
smaller to use the trick `h[(int*)localtime(*m)]` instead of
|
||||||
`((int*)localtime(*m))[h]`.
|
`((int*)localtime(*m))[h]`.
|
||||||
|
|||||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
Executable
+14
@@ -0,0 +1,14 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
make everything 1>/dev/null || exit 1
|
||||||
|
|
||||||
|
echo "Showing alt grandfather clock:" 1>&2
|
||||||
|
WESTLEY=./westley.alt ./clock1.sh
|
||||||
|
read -r -n 1 -p "Press any key to continue: " 1>&2
|
||||||
|
|
||||||
|
echo "Showing alt mantle clock that runs backwards:" 1>&2
|
||||||
|
WESTLEY=./westley.alt ./clock2.sh
|
||||||
|
read -r -n 1 -p "Press any key to continue: " 1>&2
|
||||||
|
|
||||||
|
echo "Showing alt linear style clock:" 1>&2
|
||||||
|
WESTLEY=./westley.alt ./clock3.sh
|
||||||
Executable
+14
@@ -0,0 +1,14 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
make everything 1>/dev/null || exit 1
|
||||||
|
|
||||||
|
echo "Showing grandfather clock:" 1>&2
|
||||||
|
WESTLEY=./westley ./clock1.sh
|
||||||
|
read -r -n 1 -p "Press any key to continue: " 1>&2
|
||||||
|
|
||||||
|
echo "Showing mantle clock that runs backwards:" 1>&2
|
||||||
|
WESTLEY=./westley ./clock2.sh
|
||||||
|
read -r -n 1 -p "Press any key to continue: " 1>&2
|
||||||
|
|
||||||
|
echo "Showing linear style clock:" 1>&2
|
||||||
|
WESTLEY=./westley ./clock3.sh
|
||||||
@@ -31,7 +31,7 @@ make
|
|||||||
|
|
||||||
## Judges' remarks:
|
## Judges' remarks:
|
||||||
|
|
||||||
We were able to write our own program performing the same trick using the (still
|
We were able to [write our own program](rand.c) performing the same trick using the (still
|
||||||
non-standard, for some reason) library function `memmem()`, but that way it
|
non-standard, for some reason) library function `memmem()`, but that way it
|
||||||
works too fast regardless of the context length, and it's much less fun.
|
works too fast regardless of the context length, and it's much less fun.
|
||||||
|
|
||||||
|
|||||||
@@ -1126,29 +1126,6 @@ _before you choose where to shoot_.
|
|||||||
When you shoot it will move you to that room so if you end up shooting into a
|
When you shoot it will move you to that room so if you end up shooting into a
|
||||||
pit room you will end up dying even though you didn't explicitly move there.
|
pit room you will end up dying even though you didn't explicitly move there.
|
||||||
|
|
||||||
### STATUS: known bug - please help us fix
|
|
||||||
|
|
||||||
A (mis)feature is that one must have had all arrows stolen in order to recover
|
|
||||||
all the arrows from the robber. This means that if you end up shooting an arrow
|
|
||||||
you can never recover all the arrows from the robber because the count of arrows
|
|
||||||
stolen can never be high enough. There are a number of ways this might be fixed,
|
|
||||||
some of which Cody notes:
|
|
||||||
|
|
||||||
- If you have zero arrows and you come across the robber you could give them all
|
|
||||||
back. This is not correct though because if you never had that many arrows you
|
|
||||||
would end up getting arrows back that you never had in the first place.
|
|
||||||
- A new variable, an `int`, could be added that keeps track of the number of
|
|
||||||
arrows you have fired and then if you come across the robber and they took the
|
|
||||||
number of arrows with the difference of the number fired then you would give
|
|
||||||
back how many (the difference) the robber stole rather than all the arrows. This
|
|
||||||
would be the right approach but there are certainly other ways to go about it.
|
|
||||||
|
|
||||||
A tip is that the number of arrows stolen is `l` and the number of arrows you
|
|
||||||
have is `i`. For the alt version that Cody added the starting number of arrows
|
|
||||||
is in the constant `W`, defaulting to 3.
|
|
||||||
|
|
||||||
You are welcome to try and fix this (mis)feature.
|
|
||||||
|
|
||||||
|
|
||||||
## 1994 ldb
|
## 1994 ldb
|
||||||
|
|
||||||
@@ -1393,19 +1370,6 @@ We would appreciate anyone who has it or even just knows the name! Thank you.
|
|||||||
# 1996
|
# 1996
|
||||||
|
|
||||||
|
|
||||||
## 1996 august
|
|
||||||
|
|
||||||
### STATUS: doesn't work with some compilers - please provide alternative code or fix for more compilers
|
|
||||||
### Source code: [1996/august/august.c](1996/august/august.c)
|
|
||||||
### Information: [1996/august/README.md](1996/august/README.md)
|
|
||||||
|
|
||||||
[Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) fixed a segfault in
|
|
||||||
this program that prevented it from working in gcc. It is known, however, that
|
|
||||||
some compilers will compile the code so that it enters an infinite loop (an
|
|
||||||
example is in macOS).
|
|
||||||
|
|
||||||
If you can fix this we welcome it!
|
|
||||||
|
|
||||||
## 1996 gandalf
|
## 1996 gandalf
|
||||||
|
|
||||||
### STATUS: missing or dead link - please provide them
|
### STATUS: missing or dead link - please provide them
|
||||||
@@ -1418,6 +1382,47 @@ it was instead requiring a login / password.
|
|||||||
Do you have an updated link? We welcome your help!
|
Do you have an updated link? We welcome your help!
|
||||||
|
|
||||||
|
|
||||||
|
## 1996 huffman
|
||||||
|
|
||||||
|
### STATUS: uses gets() - change to fgets() if possible
|
||||||
|
### Source code: [1996/huffman/huffman.c](1996/huffman/huffman.c)
|
||||||
|
### Information: [1996/huffman/README.md](1996/huffman/README.md)
|
||||||
|
|
||||||
|
The changing to using `fgets(3)` in this entry is a bit more complicated. It can
|
||||||
|
almost be done except that some of the output of the
|
||||||
|
[try.sh](1996/huffman/try.sh) is wrong, especially the last one.
|
||||||
|
|
||||||
|
This diff almost does it but not quite:
|
||||||
|
|
||||||
|
```diff
|
||||||
|
diff --git i/1996/huffman/huffman.c w/1996/huffman/huffman.c
|
||||||
|
index a5745bc7f4fa28b834c004f4cf19633e40ad9165..5e5e5334f33f9dbd95c70eddece3189d9bcff5e9 100644
|
||||||
|
--- i/1996/huffman/huffman.c
|
||||||
|
+++ w/1996/huffman/huffman.c
|
||||||
|
@@ -1,15 +1,16 @@
|
||||||
|
#define x char
|
||||||
|
#define z else
|
||||||
|
#define w gets
|
||||||
|
+#define gets(b) ((b)[0]='\0',(fgets((b), 100, stdin)))
|
||||||
|
#define r if
|
||||||
|
#define u int
|
||||||
|
#define s main
|
||||||
|
#define v putchar
|
||||||
|
#define y while
|
||||||
|
#define t " A?B?K?L?CIF?MSP?E?H?O?R?DJG?NTQ?????U?V?????X???????Z????W??Y??"
|
||||||
|
- s ( ) { x* c , b[ 5 * 72 ]; u a, e , d [ 9
|
||||||
|
+ s ( ) { x* c , b[ 5 * 72 ]; u a, e , d [ 9
|
||||||
|
*9 *9 ] ; y (w ( b) ){ r ( 0 [ b] -7 *
|
||||||
|
5 ) { c = b ; y ( (* c - 6
|
||||||
|
* 7 )* * c )c = c+ 1 ; r (( -0 ) [ c ] && w ( b +
|
||||||
|
8 * 5* 3 ) && w (b +8 *5 * 6) )
|
||||||
|
{ a = 0; y ( a [ b ]
|
||||||
|
```
|
||||||
|
|
||||||
|
But since it does not for the time being it is advisable to just redirect stderr
|
||||||
|
to /dev/null (`2>/dev/null`).
|
||||||
|
|
||||||
|
|
||||||
## 1996 jonth
|
## 1996 jonth
|
||||||
|
|
||||||
### STATUS: INABIAF - please **DO NOT** fix
|
### STATUS: INABIAF - please **DO NOT** fix
|
||||||
|
|||||||
+65
-13
@@ -1758,9 +1758,16 @@ As in some places it would properly say that you have '1 arrow' or else, if you
|
|||||||
have any other number of arrows (including 0), it would say 'arrows', Cody fixed
|
have any other number of arrows (including 0), it would say 'arrows', Cody fixed
|
||||||
a place where it always said 'arrows'. A minor fix and not that important.
|
a place where it always said 'arrows'. A minor fix and not that important.
|
||||||
|
|
||||||
Cody notes that there is a (mis)feature in the program that might want to be
|
Cody also fixed the problem where one could only get the arrows back from the
|
||||||
fixed that he has not had the time to fix yet; see [1991/dodsond2 in
|
robber if the robber stole as many arrows as you ever found rather than that
|
||||||
bugs.md](/bugs.md#1994-dodsond2) for more details.
|
minus how many you have shot. In other words if you had three arrows and shot
|
||||||
|
one and found no more you could never get the arrows back from the robber
|
||||||
|
because you could never lose all three since you spent one. This bug manifested
|
||||||
|
itself in another way too: once you got the arrows back the counter was not
|
||||||
|
reset so you could only get the arrows back once even if the robber stole more.
|
||||||
|
Now the counters are reset. The way this bug was fixed is that there is now a
|
||||||
|
counter for how many you have found and how many you shot in addition to the two
|
||||||
|
that already existed, how many you had and how many were stolen.
|
||||||
|
|
||||||
|
|
||||||
## [1994/horton](1994/horton/horton.c) ([README.md](1994/horton/README.md))
|
## [1994/horton](1994/horton/horton.c) ([README.md](1994/horton/README.md))
|
||||||
@@ -1912,9 +1919,12 @@ are created by the entry or the entry decrypts the text or whatever else.
|
|||||||
|
|
||||||
## [1996/august](1996/august/august.c) ([README.md](1996/august/README.md]))
|
## [1996/august](1996/august/august.c) ([README.md](1996/august/README.md]))
|
||||||
|
|
||||||
Cody fixed a segfault in this program that prevented it from working right but
|
Cody fixed a segfault in this program that prevented it from working right and
|
||||||
he notes that some compilers compile it into an infinite loop (an example where
|
also fixed an infinite loop in the try commands. The problem with the infinite
|
||||||
this happens is macOS).
|
loop is that the file `august.oc` had to have lines starting with `#` removed
|
||||||
|
and it was not being done. After this is done with say `sed(1)` (like `sed -i''
|
||||||
|
'/^#/d' august.oc` which has been added to both the remarks and the try.sh
|
||||||
|
script as described below) the code can proceed. This problem existed in macOS.
|
||||||
|
|
||||||
Cody also added the [try.sh](1996/august/try.sh) script that runs all the
|
Cody also added the [try.sh](1996/august/try.sh) script that runs all the
|
||||||
commands given in the try section to simplify it as there are quite a lot of
|
commands given in the try section to simplify it as there are quite a lot of
|
||||||
@@ -1924,15 +1934,18 @@ commands.
|
|||||||
## [1996/dalbec](1996/dalbec/dalbec.c) ([README.md](1996/dalbec/README.md]))
|
## [1996/dalbec](1996/dalbec/dalbec.c) ([README.md](1996/dalbec/README.md]))
|
||||||
|
|
||||||
Cody proposed a fix for this to compile with clang and Landon implemented it
|
Cody proposed a fix for this to compile with clang and Landon implemented it
|
||||||
after some discussion. The reason Cody did not do it is because he thought it
|
after some discussion (though Cody changed the function name). The reason Cody
|
||||||
was the wrong output but as it happens the try section below was worded a bit
|
did not do it is because he thought it was the wrong output but as it happens
|
||||||
confusingly. He looked at Yusuke's] analysis found
|
the try section below was worded a bit confusingly. He looked at Yusuke's
|
||||||
|
analysis found
|
||||||
[here](https://mame-github-io.translate.goog/ioccc-ja-spoilers/1996/dalbec.html?_x_tr_sl=auto&_x_tr_tl=en&_x_tr_hl=en-US&_x_tr_pto=wapp)
|
[here](https://mame-github-io.translate.goog/ioccc-ja-spoilers/1996/dalbec.html?_x_tr_sl=auto&_x_tr_tl=en&_x_tr_hl=en-US&_x_tr_pto=wapp)
|
||||||
but he missed that Yusuke added a '...' after the result which made him think
|
but he missed that Yusuke added a '...' after the result which made him think
|
||||||
the fix was wrong. Cody also made the recommended change of the author to make
|
the fix was wrong.
|
||||||
it so that each number is printed on a line by itself rather than having a long
|
|
||||||
string of numbers on the same line. This was not put in an alternate version but
|
Cody also made the recommended change of the author to make it so that each
|
||||||
perhaps it should be.
|
number is printed on a line by itself rather than having a long string of
|
||||||
|
numbers on the same line. This was not put in an alternate version but perhaps
|
||||||
|
it should be.
|
||||||
|
|
||||||
|
|
||||||
## [1996/eldby](1996/eldby/eldby.c) ([README.md](1996/eldby/README.md]))
|
## [1996/eldby](1996/eldby/eldby.c) ([README.md](1996/eldby/README.md]))
|
||||||
@@ -1951,6 +1964,18 @@ Cody fixed this to compile and work with modern systems. As he loved the
|
|||||||
references in the code that could not compile he just commented out as little as
|
references in the code that could not compile he just commented out as little as
|
||||||
possible to get this to compile.
|
possible to get this to compile.
|
||||||
|
|
||||||
|
Cody also added the rather useful [try.sh](1996/gandalf/try.sh) script to
|
||||||
|
really demonstrate the different ways of running the program ends up showing
|
||||||
|
either different output or the same output that we briefly pointed out.
|
||||||
|
|
||||||
|
BTW: it is perilous to try the patience of
|
||||||
|
[Gandalf](https://www.glyphweb.com/arda/g/gandalf.html). Go ahead, try it! :-)
|
||||||
|
|
||||||
|
|
||||||
|
## [1996/huffman](1996/huffman/huffman.c) ([README.md](1996/huffman/README.md]))
|
||||||
|
|
||||||
|
Cody added the [try.sh](1996/huffman/try.sh) script.
|
||||||
|
|
||||||
|
|
||||||
## [1996/jonth](1996/jonth/jonth.c) ([README.md](1996/jonth/README.md]))
|
## [1996/jonth](1996/jonth/jonth.c) ([README.md](1996/jonth/README.md]))
|
||||||
|
|
||||||
@@ -1961,6 +1986,26 @@ the function in the pointer assignment.
|
|||||||
NOTE: if there is no X server running this program will still crash.
|
NOTE: if there is no X server running this program will still crash.
|
||||||
|
|
||||||
|
|
||||||
|
## [1996/schweikh1](1996/schweikh1/schweikh1.c) ([README.md](1996/schweikh1/README.md]))
|
||||||
|
|
||||||
|
The author stated that `-I/usr/include` is needed by gcc in Solaris because
|
||||||
|
`errno.h` has two identical extern declarations of `errno`. That leads to an
|
||||||
|
error due to the redefinition of `main` but the `-I` option makes sure the
|
||||||
|
working `/usr/include/rrno.h` is found first, which shouldn't cause any problems
|
||||||
|
on other systems (the other file is
|
||||||
|
`gcc-lib/sparc-sun-solaris2.5/2.7.2/include/errno.h`). Thus Cody added this to
|
||||||
|
the Makefile despite the fact that very few probably use Solaris nowadays.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [1996/schweikh2](1996/schweikh2/schweikh2.c) ([README.md](1996/schweikh2/README.md]))
|
||||||
|
|
||||||
|
Cody added the [try.sh](1996/schweikh2/try.sh) script with a few commands to try
|
||||||
|
along with a shorter version of something the author suggested one try (it is
|
||||||
|
suggested that one try the longer version too but it will run in an infinite
|
||||||
|
loop so having it in a script is less desired).
|
||||||
|
|
||||||
|
|
||||||
## [1996/westley](1996/westley/westley.c) ([README.md](1996/westley/README.md]))
|
## [1996/westley](1996/westley/westley.c) ([README.md](1996/westley/README.md]))
|
||||||
|
|
||||||
Cody fixed a segfault in this entry as well as it displaying environmental
|
Cody fixed a segfault in this entry as well as it displaying environmental
|
||||||
@@ -1974,6 +2019,13 @@ Note that you should check the [westley.alt.c](1996/westley/westley.alt.c) file
|
|||||||
when reading the author's comments. To see how to use the original, see the
|
when reading the author's comments. To see how to use the original, see the
|
||||||
README.md file.
|
README.md file.
|
||||||
|
|
||||||
|
Cody also added the two scripts, [try.sh](1996/westley/try.sh) and
|
||||||
|
[try.alt.sh](1996/westley/try.alt.sh) to show automate showing the different
|
||||||
|
clocks, both with the fixed version and the original (alt) version.
|
||||||
|
|
||||||
|
Also, to fix any potential problem with displaying in GitHub the scripts
|
||||||
|
provided by the author, Cody added '.sh'.
|
||||||
|
|
||||||
|
|
||||||
## [1998/chaos](1998/chaos/chaos.c) ([README.md](1998/chaos/README.md]))
|
## [1998/chaos](1998/chaos/chaos.c) ([README.md](1998/chaos/README.md]))
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user