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: known bug - please help us fix
|
||||
```
|
||||
|
||||
For more detailed information see [1994 dodsond2 in bugs.md](/bugs.md#1994-dodsond2).
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
#define M isdigit
|
||||
#define N 30
|
||||
#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;
|
||||
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++){
|
||||
@@ -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;}
|
||||
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);
|
||||
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;
|
||||
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);
|
||||
i=(W>0?W:0)+3;j+=200;k=-1;}L{E"The robber scurries away\n");do{k=D;}
|
||||
}K(l&&l==Y-X){E"You catch the robber and recover all %d arrow%s!\n",Y-X,Y-X!=1?"s":"");
|
||||
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;
|
||||
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");
|
||||
@@ -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;}
|
||||
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;
|
||||
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;
|
||||
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)){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");
|
||||
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 N 30
|
||||
#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;
|
||||
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++){
|
||||
@@ -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;}
|
||||
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);
|
||||
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;
|
||||
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");
|
||||
i=3;j+=200;k=-1;}L{E"The robber scurries away\n");do{k=D;}
|
||||
}K(l&&l==Y-X){E"You catch the robber and recover all %d arrow%s!\n",Y-X,Y-X!=1?"s":"");
|
||||
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;
|
||||
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");
|
||||
@@ -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;}
|
||||
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;
|
||||
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;
|
||||
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)){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");
|
||||
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
|
||||
fac.oo
|
||||
parse.oo
|
||||
prog.oc
|
||||
august.oc
|
||||
august.oo
|
||||
august.oo
|
||||
prog.oo
|
||||
august.orig
|
||||
prog.orig
|
||||
+20
-28
@@ -34,13 +34,7 @@ The above should print a `!` followed by a newline.
|
||||
### Try:
|
||||
|
||||
```sh
|
||||
cat august.c fac.oc | ./august > fac.oo
|
||||
./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
|
||||
./try.sh
|
||||
```
|
||||
|
||||
|
||||
@@ -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
|
||||
```
|
||||
|
||||
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
|
||||
entry as it surely will make the 'best of the IOCCC' list. It was
|
||||
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.
|
||||
|
||||
The language the compiler understands is a subset of C (the grammar
|
||||
is in grammar.small) with the functions getchar() and putchar()
|
||||
available. The subset has the types `int', `char', and pointers to
|
||||
is below) with the functions `getchar(3)` and `putchar(3)`
|
||||
available. The subset has the types `int`, `char`, and pointers to
|
||||
those (it has function pointers too, but not with the proper
|
||||
syntax). Arrays can only be global. There is a rather limited set
|
||||
of operators, and control constructs.
|
||||
@@ -117,10 +104,10 @@ of operators, and control constructs.
|
||||
The compiler has absolutely no error checking, so things
|
||||
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
|
||||
binary in prog) and that we have this in a file named `test.oc`:
|
||||
Assume that the interpreter has been compiled (source in [august.c](august.c)
|
||||
and binary in august) and that we have this in a file named `test.oc`:
|
||||
|
||||
```
|
||||
```c
|
||||
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.:
|
||||
|
||||
```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
|
||||
it does) then remove it.
|
||||
If `august.oc` contain some junk line starting with a `#` (most likely
|
||||
it does) then remove it like:
|
||||
|
||||
```sh
|
||||
sed -i'' '/^#/d' august.oc
|
||||
```
|
||||
|
||||
OK, we can now compile the interpreter:
|
||||
|
||||
```sh
|
||||
cat august.c prog.oc | ./august > prog.oo
|
||||
cat august.c august.oc | ./august > august.oo
|
||||
```
|
||||
|
||||
And we can run it:
|
||||
|
||||
```sh
|
||||
cat prog.oo test.oo | ./august
|
||||
cat august.oo test.oo | ./august
|
||||
```
|
||||
|
||||
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:
|
||||
|
||||
```sh
|
||||
cat prog.oo prog.oo test.oo | ./august
|
||||
cat august.oo august.oo test.oo | ./august
|
||||
```
|
||||
|
||||
And another...
|
||||
|
||||
```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
|
||||
size of it by about 30%. The remaining code is then LZ-compressed
|
||||
(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
|
||||
handles the unpacking of the byte code (this is a lot, but it pays
|
||||
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
|
||||
the code further with a better entropy coder (e.g. an arithmetic
|
||||
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.
|
||||
|
||||
---
|
||||
@@ -283,6 +274,7 @@ stars: "*"*
|
||||
|
||||
---
|
||||
|
||||
|
||||
Well, that is enough ranting for now.
|
||||
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ cat parse.oo fac.oc | ./august | ./august
|
||||
|
||||
rm august.oc
|
||||
make august.oc
|
||||
sed -i'' '/^#/d' august.oc
|
||||
cat august.c august.oc | ./august > august.oo
|
||||
cat august.oo test.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.
|
||||
|
||||
5. The fact that `main()` is used:
|
||||
|
||||
- to compute powers in modular arithmetic.
|
||||
|
||||
- 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?
|
||||
OO=cain(I,O,O0,OO>>!!OO,l),
|
||||
OO=cain(I-!I-!!I,O,OO,OO,l),
|
||||
OO=cain(I-!I-!!I,O,O0,OO,l),
|
||||
OO=pain(I,O,O0,OO>>!!OO,l),
|
||||
OO=pain(I-!I-!!I,O,OO,OO,l),
|
||||
OO=pain(I-!I-!!I,O,O0,OO,l),
|
||||
!(OO-!I||I)?l-1:OO
|
||||
:(OO=cain(I,O,O0,OO>>!!OO,l),
|
||||
!(OO-l+!I||I)?l-1:cain(I-!I-!!I,O,OO,OO,l))
|
||||
:(OO=pain(I,O,O0,OO>>!!OO,l),
|
||||
!(OO-l+!I||I)?l-1:pain(I-!I-!!I,O,OO,OO,l))
|
||||
:(O0+OO)%l
|
||||
:cain(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))
|
||||
:cain(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/I-I/I,O,O0,OO+OO/OO,
|
||||
pain(0,O,O0,OO,I-I-I)+I+1?1:printf("%d\n",I-I-I)+fflush(stdout))
|
||||
:pain(I-I-I-I-I,O,I+I-I+I,I,0)
|
||||
: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
|
||||
#
|
||||
CINCLUDE=
|
||||
CINCLUDE= -include stdio.h -include unistd.h
|
||||
|
||||
# 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
|
||||
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
|
||||
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
|
||||
make all
|
||||
```
|
||||
|
||||
### Original use:
|
||||
|
||||
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
|
||||
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:
|
||||
|
||||
@@ -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=
|
||||
(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)
|
||||
|
||||
@@ -39,7 +39,7 @@ include ../../var.mk
|
||||
# Common C compiler warnings to silence
|
||||
#
|
||||
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
|
||||
|
||||
# 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:
|
||||
|
||||
```sh
|
||||
PATH=.:$PATH
|
||||
./hatcat
|
||||
./cathat
|
||||
./try.sh
|
||||
```
|
||||
|
||||
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
|
||||
./cathat
|
||||
`pwd`/cathat
|
||||
```
|
||||
BTW: it is perilous to 'try' the patience of
|
||||
[Gandalf](https://www.glyphweb.com/arda/g/gandalf.html). Go ahead, 'try' it! :-)
|
||||
|
||||
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:
|
||||
|
||||
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
|
||||
#
|
||||
CINCLUDE=
|
||||
CINCLUDE= -include stdio.h
|
||||
|
||||
# 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:
|
||||
|
||||
```sh
|
||||
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:
|
||||
|
||||
```sh
|
||||
echo 'seeing or feeling is believing' | ./huffman
|
||||
echo 'CC OR NOT CC' | ./huffman
|
||||
echo 'CC OR NOT CC' | ./huffman | ./huffman
|
||||
./try.sh
|
||||
```
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
```sh
|
||||
./huffman < huffman.c
|
||||
./huffman < huffman.c 2>/dev/null
|
||||
```
|
||||
|
||||
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
|
||||
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,
|
||||
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:
|
||||
|
||||
For a good noop try:
|
||||
For a good no-op try:
|
||||
|
||||
```sh
|
||||
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
|
||||
uncompressed original file to standard output.
|
||||
|
||||
|
||||
### ObJustifications for this entry:
|
||||
|
||||
|
||||
#### The Design Trade-off Argument:
|
||||
|
||||
"The 184 characters worth of defines in the build file have been
|
||||
carefully offset by 184 redundant and unnecessary '`{`', '`}`', and '`;`'
|
||||
characters in the source file."
|
||||
|
||||
|
||||
#### The Design Review Argument:
|
||||
|
||||
"Using only 216 characters out of a maximum of 256, the build file
|
||||
meets and actually exceeds specification."
|
||||
|
||||
|
||||
#### 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
|
||||
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
|
||||
@@ -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
|
||||
source file size to execution time."
|
||||
|
||||
|
||||
#### The Whining Programmer's Argument:
|
||||
|
||||
"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:
|
||||
|
||||
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\
|
||||
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
|
||||
statement?
|
||||
|
||||
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
|
||||
spring equinox. (Also known as "Easter", defined this way by the
|
||||
Nicaean Concilium in 325 Anno Domini.) The algorithm is attributed
|
||||
to the famous mathematician Carl Friedrich Gauss ["Meyers Handbuch
|
||||
ueber das Weltall", Meyer, 5th Edition, 1973, p149] and is suitable
|
||||
for anni domini within the Gregorian Calendar, that is, from 1582 AD
|
||||
to 2199 AD:
|
||||
to the famous mathematician [Carl Friedrich
|
||||
Gauss](https://en.wikipedia.org/wiki/Carl_Friedrich_Gauss) ["Meyers Handbuch
|
||||
ueber das Weltall" 'Handbook About Space', Meyer, 5th Edition, 1973, p149] and is suitable
|
||||
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.
|
||||
@@ -70,18 +72,18 @@ with the following exceptions:
|
||||
|
||||
```
|
||||
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:
|
||||
|
||||
```
|
||||
J = 1962, M = 24, N = 5
|
||||
a = J % 19 = 5
|
||||
b = J % 4 = 2
|
||||
c = J % 7 = 2
|
||||
d = 119 % 30 = 29
|
||||
e = 191 % 7 = 2
|
||||
a = J % 19 == 5
|
||||
b = J % 4 == 2
|
||||
c = J % 7 == 2
|
||||
d = 119 % 30 == 29
|
||||
e = 191 % 7 == 2
|
||||
```
|
||||
|
||||
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
|
||||
to the definition of a translation unit. Unfortunately, due to the
|
||||
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
|
||||
how preprocessing tokens form type qualifier lists, cast expressions
|
||||
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:
|
||||
\
|
||||
|
||||
Try to be as precise as can be and no one will comprehend what you mean.
|
||||
|
||||
|
||||
#### 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)
|
||||
```
|
||||
|
||||
|
||||
#### The interpretation:
|
||||
|
||||
"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
|
||||
problems on other systems.
|
||||
|
||||
### Usage
|
||||
|
||||
### Usage:
|
||||
|
||||
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:
|
||||
|
||||
```sh
|
||||
./schweikh2 15 1 0 0/0
|
||||
./try.sh
|
||||
```
|
||||
|
||||
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
|
||||
```
|
||||
|
||||
(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:
|
||||
|
||||
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
|
||||
less 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
|
||||
beauty have your eyes half closed.
|
||||
|
||||
|
||||
### Why I think this program is obfuscated:
|
||||
|
||||
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*
|
||||
non-white space character (with the exception of preprocessor directives).
|
||||
There are no recognizable keywords anymore. There are no recognizable
|
||||
string literals any more. The main function is invisible. All operators
|
||||
longer than one character have gone. They have been replaced by macro
|
||||
string literals any more. The `main()` function is invisible. All operators
|
||||
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
|
||||
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
|
||||
one 8-character token from 8 characters ('unsigned'). BTW, C has no 9 or
|
||||
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
|
||||
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
|
||||
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
|
||||
(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'
|
||||
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:
|
||||
|
||||
1. The number of operators in the expression [default: 9]
|
||||
2. The value of the first operand [1]
|
||||
3. The (possibly negative) increment to the next operand [1]
|
||||
4. The goal value or 0/0 [42]
|
||||
1. The number of operators in the expression [default: 9].
|
||||
2. The value of the first operand [1].
|
||||
3. The (possibly negative) increment to the next operand [1].
|
||||
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)
|
||||
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
|
||||
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
|
||||
`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
|
||||
@@ -142,7 +148,7 @@ minutes (`gcc -O3`).
|
||||
|
||||
### 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:
|
||||
|
||||
```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
|
||||
|
||||
There are some layout obfuscations that hinder readability, like
|
||||
some (but not all) one character tokens in column 1. Includes,
|
||||
defines and declarations of data and functions appear intermixed.
|
||||
iso646.h is even included in the middle of an expression, how
|
||||
disgusting. Besides, requiring iso646.h will render the program
|
||||
some (but not all) one character tokens in column 1. `#include`s,
|
||||
`#define`s and declarations of data and functions appear intermixed.
|
||||
`iso646.h` is even included in the middle of an expression, how
|
||||
disgusting. Besides, requiring `iso646.h` will render the program
|
||||
uncompilable on many systems that have not yet incorporated
|
||||
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
|
||||
"switch () case 1:" or "switch () case 0:" etc. At least one
|
||||
switch has a declaration after the opening brace, booh!
|
||||
Identifiers are named after random programming languages, Basic,
|
||||
Cobol, F77, awk etc.
|
||||
`switch () case 1:` or `switch () case 0:` etc. At least one
|
||||
`switch` has a declaration after the opening brace, booh!
|
||||
Identifiers are named after random programming languages, BASIC (as `Basic`),
|
||||
COBOL, F77, awk etc.
|
||||
|
||||
You have to select maximum ANSI C conformance of your
|
||||
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
|
||||
untested :-) ).
|
||||
|
||||
Does your indent cope with backslash/newline pairs inbetween
|
||||
keywords like in "re\<newline>turn"? Solaris' indent inserts spaces\
|
||||
and thereby renders the source uncompilable...
|
||||
Does your indent cope with backslash/newline pairs in between keywords like in
|
||||
`re\turn` where the `re\` is at the end of a line? ? Solaris' indent inserts
|
||||
spaces and thereby renders the source uncompilable...
|
||||
|
||||
The indented source will exhibit different semantics when indenting
|
||||
changes the number of lines (due to using the `__LINE__` macro in an
|
||||
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.
|
||||
`strlen ("hh:mm:ss")`? -- no. It's the same as `sizeof __DATE__ -
|
||||
sizeof "no"` :-)
|
||||
@@ -114,22 +114,22 @@ possible execution paths.
|
||||
### What this program does
|
||||
|
||||
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
|
||||
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
|
||||
any arguments, malloc() will be used to allocate memory. If the
|
||||
first arg starts with c, calloc() will be used instead.
|
||||
any arguments, `malloc(3)` will be used to allocate memory. If the
|
||||
first arg starts with `c`, `calloc(3)` will be used instead.
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
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
|
||||
affected this way, the system slows down and quickly becomes totally unusable
|
||||
(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.
|
||||
|
||||
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
|
||||
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
|
||||
my program but issued by the syslog daemon.
|
||||
|
||||
|
||||
### Implementation remarks
|
||||
|
||||
How can we distinguish the three different OS types from the
|
||||
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
|
||||
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
|
||||
(using `clock()`). If a certain threshold is reached I assume the
|
||||
system is thrashing. When thrashing, however, the process does not
|
||||
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
|
||||
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
|
||||
minute or so.
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
***** SOLARIS 2.5 (sparc):
|
||||
|
||||
% prog
|
||||
% schweikh3
|
||||
Trying to malloc 2048M+0K+0 bytes..nope
|
||||
Trying to malloc 1024M+0K+0 bytes..nope
|
||||
Trying to malloc 512M+0K+0 bytes..nope
|
||||
@@ -41,7 +41,7 @@
|
||||
|
||||
***** FreeBSD 2.1 (i386):
|
||||
|
||||
% prog
|
||||
% schweikh3
|
||||
Trying to malloc 2048M+0K+0 bytes..nope
|
||||
Trying to malloc 1024M+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: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 1024M+0K+0 bytes..nope
|
||||
Trying to calloc 512M+0K+0 bytes..nope
|
||||
@@ -96,7 +96,7 @@
|
||||
|
||||
***** Linux 1.2.13 (i386):
|
||||
|
||||
% prog
|
||||
% schweikh3
|
||||
Trying to malloc 2048M+0K+0 bytes..nope
|
||||
Trying to malloc 1024M+0K+0 bytes..nope
|
||||
Trying to malloc 512M+0K+0 bytes..nope
|
||||
@@ -132,7 +132,7 @@
|
||||
Able to malloc 23M+1023K+1023 bytes
|
||||
23294 kilo bytes ok malloc lied! Thrashing
|
||||
|
||||
% prog c
|
||||
% schweikh3 c
|
||||
Trying to calloc 2048M+0K+0 bytes..nope
|
||||
Trying to calloc 1024M+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
|
||||
#
|
||||
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
|
||||
#
|
||||
@@ -109,7 +110,7 @@ ENTRY= westley
|
||||
PROG= ${ENTRY}
|
||||
#
|
||||
OBJ= ${PROG}.o
|
||||
DATA= clock1 clock2 clock3
|
||||
DATA= clock1.sh clock2.sh clock3.sh
|
||||
TARGET= ${PROG}
|
||||
#
|
||||
ALT_OBJ= westley.alt.o
|
||||
|
||||
+27
-30
@@ -4,51 +4,46 @@
|
||||
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:
|
||||
|
||||
```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:
|
||||
|
||||
```sh
|
||||
sh ./clock2
|
||||
```
|
||||
|
||||
|
||||
And for a good time, try:
|
||||
|
||||
```sh
|
||||
sh ./clock3
|
||||
./try.sh
|
||||
```
|
||||
|
||||
|
||||
## Alternate code:
|
||||
|
||||
An alternate version of this entry, [westley.alt.c](westley.alt.c), is provided.
|
||||
This version is the original code and does not contain the above mentioned
|
||||
fixes.
|
||||
The original version had a display problem in modern systems which somewhat
|
||||
affected the usability of the program. This alternate code, the original, is
|
||||
provided, to show the differences.
|
||||
|
||||
### Alternate build:
|
||||
|
||||
To compile this alternate version:
|
||||
|
||||
```sh
|
||||
make alt
|
||||
```
|
||||
|
||||
To use it with the scripts try:
|
||||
|
||||
### Alternate try:
|
||||
|
||||
```sh
|
||||
WESTLEY=./westley.alt ./clock1
|
||||
WESTLEY=./westley.alt ./clock2
|
||||
WESTLEY=./westley.alt ./clock3
|
||||
./try.alt.sh
|
||||
```
|
||||
|
||||
|
||||
@@ -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
|
||||
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
|
||||
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:
|
||||
|
||||
@@ -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 *`.
|
||||
|
||||
3. The first three elements of the struct * returned by localtime() are seconds,
|
||||
minutes, hours, and all are ints.
|
||||
3. The first three elements of the `struct *` returned by `localtime(3)` are
|
||||
seconds, minutes, hours, and all are `int`s.
|
||||
|
||||
4. My sample scripts assume ASCII, though this is not inherent in the code, just
|
||||
my sample scripts.
|
||||
@@ -83,6 +79,7 @@ my sample scripts.
|
||||
These assumptions are pretty reasonable. 2) can be eliminated but makes the code
|
||||
larger.
|
||||
|
||||
|
||||
The code is simple; the arguments passed are:
|
||||
|
||||
```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`
|
||||
string. This string is then printed.
|
||||
|
||||
The for() loop starts by calling `time()` with `argv[0]`, so
|
||||
the time value (a long) is written into the program name.
|
||||
The for() control value is `argc`, which starts at `5`, but
|
||||
the `/=2` statement is executed before the test, so the for()
|
||||
The `for()` loop starts by calling `time()` with `argv[0]`, so
|
||||
the time value (a `long`) is written into the program name.
|
||||
The `for()` control value is `argc`, which starts at `5`, but
|
||||
the `/=2` statement is executed before the test, so the `for()`
|
||||
loop is executed twice, with `h=2`, then `h=1` (for hour & minute).
|
||||
|
||||
The statement of the for() loop takes the hour or minute
|
||||
field of the struct returned by `localtime()` by casting it
|
||||
The statement of the `for()` loop takes the hour or minute
|
||||
field of the struct returned by `localtime(3)` by casting it
|
||||
to an `int *` and dereferencing element `[h]`. It is slightly
|
||||
smaller to use the trick `h[(int*)localtime(*m)]` instead of
|
||||
`((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:
|
||||
|
||||
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
|
||||
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
|
||||
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
|
||||
|
||||
@@ -1393,19 +1370,6 @@ We would appreciate anyone who has it or even just knows the name! Thank you.
|
||||
# 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
|
||||
|
||||
### 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!
|
||||
|
||||
|
||||
## 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
|
||||
|
||||
### 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
|
||||
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
|
||||
fixed that he has not had the time to fix yet; see [1991/dodsond2 in
|
||||
bugs.md](/bugs.md#1994-dodsond2) for more details.
|
||||
Cody also fixed the problem where one could only get the arrows back from the
|
||||
robber if the robber stole as many arrows as you ever found rather than that
|
||||
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))
|
||||
@@ -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]))
|
||||
|
||||
Cody fixed a segfault in this program that prevented it from working right but
|
||||
he notes that some compilers compile it into an infinite loop (an example where
|
||||
this happens is macOS).
|
||||
Cody fixed a segfault in this program that prevented it from working right and
|
||||
also fixed an infinite loop in the try commands. The problem with the infinite
|
||||
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
|
||||
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]))
|
||||
|
||||
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
|
||||
was the wrong output but as it happens the try section below was worded a bit
|
||||
confusingly. He looked at Yusuke's] analysis found
|
||||
after some discussion (though Cody changed the function name). The reason Cody
|
||||
did not do it is because he thought it was the wrong output but as it happens
|
||||
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)
|
||||
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
|
||||
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
|
||||
perhaps it should be.
|
||||
the fix was wrong.
|
||||
|
||||
Cody also made the recommended change of the author to make 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 perhaps
|
||||
it should be.
|
||||
|
||||
|
||||
## [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
|
||||
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]))
|
||||
|
||||
@@ -1961,6 +1986,26 @@ the function in the pointer assignment.
|
||||
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]))
|
||||
|
||||
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
|
||||
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]))
|
||||
|
||||
|
||||
Reference in new issue
Block a user