Add preview of 1984-2019

The 2020 winners are hinted it, but the source code is not there,
nor are the hints. Someone could look into the HTML and
see what was commented out, but that is not a problem because
WHO won is known and the name of their AWARD is known already.
Moreover a number of the winners have talked about what their
entirs do, so the commented out spoiler text is not a bit problem.

One will find HTML commented out with:

    <!-- XXX remove when 2020 is ready
    2020 links here
    XXX remove when 2020 is ready -->

The "XXX remove when 2020 is ready" string is found at the
start and end comment blocks.  Again, soneone could read
what was commented out, but that is OK since most of that
information is known or can be known.  The following files
have such HTML comment blocks in them.

    ./winners.html
    ./years-spoiler.html
    ./years.html

In addition, ./all/summary.txt was modified to not
include the 2020 entries for the momemt.

The 2020 winner code AND write-ups are NOT part of this set.

p.s. The all/all.tar.bz2 does not contain the 2020 source code (yet?).
This commit is contained in:
Landon Curt Noll committed 2020-12-30 16:57:03 -08:00
1 parent 28efc67f5d
commit c0663537cb
1683 files changed
+220064

No files matched your search

BIN
View File
Binary file not shown.
+214
View File
@@ -0,0 +1,214 @@
#!/bin/make
# 2000 makefile
#
# Copyright (C) Simon Cooper, Landon Curt Noll, Peter Seebach
# and Leonid A. Broukhis, 2000.
# All Rights Reserved. Permission for personal, educational or non-profit
# use is granted provided this this copyright and notice are included in its
# entirety and remains unaltered. All other uses must receive prior permission
# from the contest judges.
SHELL= /bin/sh
CAT= cat
RM= rm
SED= sed
TRUE= true
# optimization
#
# Most compiles will safely use -O2. Some can use only -O.
# A few compilers have broken optimizers and thus you may
# not want anything.
#
#OPT=
#OPT= -O
OPT= -O2
# flags for ANSI compiles
#
# NOTE: Some ANSI compilers make use of -Xa to turn on ANSI mode,
# others such as gcc may want -ansi, others (Compaq Tru64 Unix)
# want -std1, and others may want nothing at all.
# Adjust the CFLAGS line as needed.
#
# NOTE: Some compilers cannot optimize, or optimize some entries
# incorrectly. You might want to turn on -O to see if your
# compiler can handle them.
#
#
#CFLAGS= -Xa ${OPT}
#CFLAGS= -std1 $(OPT)
CFLAGS= -ansi ${OPT}
NO_ANSI_CFLAGS=
#NO_ANSI_CFLAGS=
# NOTE: On some systems, the library path does not include the location
# of the X11 libraries. You might need to use a -L/path/to/X11/lib/dir
# in order to compile with these libs.
#
X11CCFLAGS= -I/usr/X11R6/include -I/usr/X11R6/include/X11 -I/usr/include/X11
#X11CCFLAGS=
X11LDFLAGS= -L/usr/X11R6/lib
#X11LDFLAGS=
# Perl
#
PERL= perl
#PERL= perl5
# ANSI compiler
#
# Set CC to the name of your ANSI compiler.
#
# Some entries seem to need gcc. If you have gcc, set
# both CC and MAY_NEED_GCC to gcc.
#
# If you do not have gcc, set CC to the name of your ANSI compiler, and
# set MAY_NEED_GCC to either ${CC} (and hope for the best) or to just :
# to disable such programs.
#
CC= cc
MAY_NEED_GCC= gcc
# winners that compile under ANSI C
#
WINNERS= anderson schneiderwent primenum bellard bmeyer briddlebane dhyang \
dmy2jd jarijyrki dlowe natori rince robison thadgavin tomx
ALT_NAMES= schneiderwent.orig briddlebane.orig thadgavin.orig
DATA_FILES= schneiderwent_files bmeyer_files jarijyrki_files
all: ${WINNERS}
# Best use of flags
#
anderson: anderson.c
${CC} ${CFLAGS} $? -o $@
# Most Timely Output
#
schneiderwent: schneiderwent.c
${CC} ${CFLAGS} $? -o $@
schneiderwent_files: schneiderwent.data
schneiderwent.orig: schneiderwent.orig.c
${CC} ${CFLAGS} $? -o $@
# Best Abuse of CPP
#
primenum: primenum.c
${CC} ${CFLAGS} $? -o $@
# Most Specific Output
#
bellard: bellard.c
${CC} ${CFLAGS} $? -o $@
# Best Utility
#
# machines operating in 64 bit mode:
#
bmeyer: bmeyer.c
${CC} -DY= -O6 $? -o $@ -lm
#
# linux/x86, glibc 2.0, libc4/5:
#
# bmeyer: bmeyer.c
# ${CC} -DY="__setfpucw(0x127f)" -O6 $? -o $@ -lm
#
# linux/x86, glibc 2.1:
#
# bmeyer: bmeyer.c
# ${MAY_NEED_GCC} -DY='int x=0x127f; __asm__ ("fldcw %0" : : "m" (*&x))' \
# -O6 $? -o $@ -lm
bmeyer_files: lavabus.pgm lenna.glic michael.pgm
# Best Abuse of User
#
briddlebane: briddlebane.c
${CC} ${CFLAGS} $? -o $@ -lm
briddlebane.orig: briddlebane.orig.c
${CC} ${CFLAGS} $? -o $@ -lm
# Best Layout
#
dhyang: dhyang.c
${CC} ${CFLAGS} $? -o $@
dmy2jd: dmy2jd.c
${CC} ${CFLAGS} $? -o $@
# Best of Show
#
jarijyrki: jarijyrki.c
${CC} ${X11CCFLAGS} ${CFLAGS} -DNeedFunctionPrototypes \
-DU=40 -DT=98 '-Dz=(T+1)*U*U' -DQ=80 -DS=20 -DN=10 -DB=5 -DG=23 \
-Dp=7 '-DM=((p+1)*Q)+S' '-DH=(G*S)+S+S' -DC=XK_Up -DL=XK_Down \
-DO=XK_Left -DV=XK_Right -DR=XK_Escape -D_=XK_BackSpace \
$? -o $@ ${X11LDFLAGS} -lX11
jarijyrki_files: sheet1.info
# Worst Abuse of the Rules
#
# NOTE: You will need to adjust this path to the place where Perl has been
# installed on your system. Running "perl -V" may help you locate
# this place.
#
# The following bit of perl may help determining the values you need:
#
# perl -MConfig -e 'print "$Config{archlibexp}/CORE\n"'
#
#
dlowe: dlowe.c
${CC} ${NO_ANSI_CFLAGS} -DPERL_POLLUTE \
`${PERL} -MExtUtils::Embed -e ccopts` $? -o $@ \
`${PERL} -MExtUtils::Embed -e ldopts`
# Best Small Program
#
natori: natori.c
${CC} ${CFLAGS} $? -o $@ -lm
# Astronomically Obfuscated
#
rince: rince.c
${CC} ${X11CCFLAGS} ${CFLAGS} -DM_PI=3.14159265358979323846 \
$? -o $@ -lm ${X11LDFLAGS} -lX11
# Best game
#
robison: robison.c
${CC} ${CFLAGS} $? -o $@
# Most Portable Output
#
thadgavin: thadgavin.c
${CC} ${CFLAGS} $? -o $@ -lcurses -lm
thadgavin.orig: thadgavin.orig.c
${CC} ${CFLAGS} $? -o $@ -lncurses -lm
# Most Complete Program
#
tomx: tomx.c
${CC} ${CFLAGS} $? -o $@
everything: ${WINNERS} ${ALT_NAMES} ${DATA_FILES}
clean:
${RM} -f *.o a.out core ${WINNERS}
clobber: clean
${RM} -f ${WINNERS}
${RM} -f ${ALT_NAMES}
nuke: clobber
@${TRUE}
install: all
${CAT} ${WINNERS} ${ALT_NAMES} > /dev/null
+120
View File
@@ -0,0 +1,120 @@
2000 marked the "The Fifteenth International Obfuscated C Code Contest"
Copyright (C) Landon Curt Noll, Simon Cooper, Peter Seebach
and Leonid A. Broukhis, 2000.
All Rights Reserved. Permission for personal, educational or non-profit
use is granted provided this copyright and notice are included in its
entirety and remains unaltered. All other uses must receive prior permission
from the contest judges.
Standard IOCCC stuff
--------------------
Use make to compile entries. It is possible that on non-Un*x / non-Linux
systems the makefile needs to be changed. See the Makefile for details.
Look at the source and try to figure out what the programs do, and run
them with various inputs. If you want to, look at the hints files for
spoilers - this year we included most of the information included
by the submitters.
Read over the makefile for compile/build issues. Your system may
require certain changes (add or remove a library, add or remove a
#define).
Some ANSI C compilers are not quite as good as they should be. If
yours is lacking, you may need to compile using gcc instead of your
local compiler.
New Judge
---------
The judges were unable to contact Jeremy Horn for judging the 2000 contest.
As a result, Simon Cooper:
http://www.sfik.com/
joined our team. Simon is well known for being a co-author of the 2nd
edition of the Building Internet Firewalls book.
Remarks on some of the entries
------------------------------
There were some outstanding entries that did not win. Unfortunately
some very good entries lost because they:
+ depended too much on non-portable side effects in expressions;
+ depended too much on a particular byte order;
+ required the use of a special script, data file or pseudo-machine
language that was not supplied with the entry.
We hope the authors of some of those entries will fix and re-submit
them for the next IOCCC.
We believe you will be impressed with this year's winners. The
Best of Show is a fine example of compact obfuscation. But don't
ignore the shorter winners. The Best Small Program, Best Abuse of
User and Most Complete Program are well worth studying in detail.
The Worst Abuse of the Rules is technically allowed by the rules.
We gave it an award this year, but don't assume you can get away
with using it next time ... :-)
Speaking of time, be sure to check out the Astronomically Obfuscated
and the Most Timely Output.
There was no 1999 contest
-------------------------
So what happened to 1999? Landon Curt Noll was scheduled to take a
vacation from the IOCCC this year. The remaining judges were
unable to contact Jeremy Horn, so the IOCCC stalled.
But thanks to Landon's returning early from his IOCCC vacation (Landon
will take a full IOCCC vacation during some other year), Simon Cooper
joining the IOCCC judging team as well as the hard work of Peter Seebach
and Leonid A. Broukhis the judging was completed in Dec 2000.
It was decided that the 15th contest would be the year 2000 contest
(the year the judging completed) rather than year 1999 (the initial
scheduled start of the contest). That is why there is no 1999 contest.
Final Comments
--------------
Please send us comments and suggestions what we have expressed above.
Also include anything else that you would like to see in future contests.
Send such email to:
questions@ioccc.org
If you use, distribute or publish these entries in some way, please drop
us a line. We enjoy seeing who, where and how the contest is used.
You must include the words ``ioccc question'' in the subject of your EMail
message when sending EMail to the judges.
If you have problems with any of the entries, AND YOU HAVE A FIX, please
EMail the fix (patch file or the entire changed file) to the above address.
The next IOCCC is planned to start towards early spring 2001. Watch:
http://www.ioccc.org/
for news of the next contest.
=-=
p.s. The has been mentioned in an Amici Curiae for the DeCSS case. See:
http://cryptome.org/mpaa-v-2600-bac.htm
and seach on the word ioccc (twice).
+58
View File
@@ -0,0 +1,58 @@
#include <stdio.h>
char
*T="IeJKLMaYQCE]jbZRskc[SldU^V\\X\\|/_<[<:90!\"$434-./2>]s",
K[3][1000],*F,x,A,*M[2],*J,r[4],*g,N,Y,*Q,W,*k,q,D;X(){r [r
[r[3]=M[1-(x&1)][*r=W,1],2]=*Q+2,1]=x+1+Y,*g++=((((x& 7)
-1)>>1)-1)?*r:r[x>>3],(++x<*r)&&X();}E(){A||X(x=0,g =J
),x=7&(*T>>A*3),J[(x[F]-W-x)^A*7]=Q[x&3]^A*(*M)[2 +(
x&1)],g=J+((x[k]-W)^A*7)-A,g[1]=(*M)[*g=M[T+=A ,1
][x&1],x&1],(A^=1)&&(E(),J+=W);}l(){E(--q&&l ()
);}B(){*J&&B((D=*J,Q[2]<D&&D<k[1]&&(*g++=1 ),
!(D-W&&D-9&&D-10&&D-13)&&(!*r&&(*g++=0) ,*
r=1)||64<D&&D<91&&(*r=0,*g++=D-63)||D >=
97&&D<123&&(*r=0,*g++=D-95)||!(D-k[ 3]
)&&(*r=0,*g++=12)||D>k[3]&&D<=k[ 1]
-1&&(*r=0,*g++=D-47),J++));}j( ){
putchar(A);}b(){(j(A=(*K)[D* W+
r[2]*Y+x]),++x<Y)&&b();}t ()
{(j((b(D=q[g],x=0),A=W) ),
++q<(*(r+1)<Y?*(r+1): Y)
)&&t();}R(){(A=(t( q=
0),'\n'),j(),++r [2
]<N)&&R();}O() {(
j((r[2]=0,R( ))
),r[1]-=q) &&
O(g-=-q) ;}
C(){( J=
gets (K
[1]))&&C((B(g=K[2]),*r=!(!*r&&(*g++=0)),(*r)[r]=g-K[2],g=K[2
],r[
1]&&
O())
);;}
main
(){C
((l(
(J=(
A=0)
[K],
A[M]
=(F=
(k=(
M[!A
]=(Q
=T+(
q=(Y
=(W=
32)-
(N=4
))))
+N)+
2)+7
)+7)
),Y=
N<<(
*r=!
-A))
);;}
+76
View File
@@ -0,0 +1,76 @@
Best Use of Flags:
Glyn Anderson
Jl. Raya Serang KM 18.2
Desa Bojong
Cikupa, Tangerang, 15710
Indonesia
Judges' Comments:
To build:
make anderson
To run:
echo Obfuscate | ./anderson
This small program might be a nice addition to a digital personal
organizer; just in case you are stranded on a desert island and need to
signal your distress to passing ships.
The obfuscation in this program is truly masterful. The program is
very cleverly obscured without the use of a single #define!
Reformatting this program by hand :-) is the easiest way to understand
what is going on.
Selected Author's Comments:
This program is a simple filter that translates ASCII text into
semaphore code. It reads from standard input and converts all
alphanumeric characters to their corresponding semaphore codes.
Consecutive whitespace is translated as a single 'break' code. Newlines
also cause the next code to be output on a new line. All other
characters are ignored. The codes themselves are written to standard
output as a depiction of a person holding two flags, using only ASCII
characters (semaphore smileys, if you will). For example, given the
input "Hello, world!", the output will be:
<> <> <> <> <> <>
_() ()/ ()/ ()/ _\) () (/_ _\)
[] /^ |^^ /^^ /^^ [] ^^ |^^| ^^ [] [] ^^
<>[ [][ <>][ <>][ ][ [][] ][ ][
<> []
_()_ ()/ |() ()
[] ^^ [] /^^ ^^| |^^|
][ <>][ ][] [][]
The program is obfuscated without the use of the preprocessor or any
special compilation parameters. In fact, the program doesn't even
bother using any keywords, save the single 'char' at the beginning.
This program was crafted using only operator precedence rules,
short-circuit evaluation and recursion. Each function contains a
single, non-empty statement. (I did have to add a couple of empty
statements to format the code properly.) There is a single string
constant which encodes the flag positions and other data needed for
drawing the semaphore codes.
The preprocessor will provide no help in un-obfuscating this code, and a
C beautifier won't get you very far either. You just have to crunch
through it.
An ANSI C compiler will generate several warnings when it compiles this
program, as none of the functions declare their return type, nor do they
return anything. This was necessary to keep the program free of
keywords. It's valid in K&R C, and compiles in ANSI C. There are also
warnings about conversion from 'int' to 'char' and the resulting loss of
data. Again, if it's OK with K&R, it's OK with me.
This program is a great teaching tool for learning the semaphore code;
and if you don't have any flags handy you can just use two copies of the
source file.
+37
View File
@@ -0,0 +1,37 @@
int m = 754974721, N, t[1 << 22], a, *p, i, e = 1 << 22, j, s, b, c, U;
f (d)
{
for (s = 1 << 23; s; s /= 2, d = d * 1LL * d % m)
if (s < N)
for (p = t; p < t + N; p += s)
for (i = s, c = 1; i; i--)
b = *p + p[s], p[s] = (m + *p - p[s]) *
1LL * c % m, *p++ = b % m, c = c * 1LL * d % m;
for (j = 0; i < N - 1;)
{
for (s = N / 2; !((j ^= s) & s); s /= 2);
if (++i < j)
a = t[i], t[i] = t[j], t[j] = a;
}
}
main ()
{
*t = 2;
U = N = 1;
while (e /= 2)
{
N *= 2;
U = U * 1LL * (m + 1) / 2 % m;
f (362);
for (p = t; p < t + N;)
*p++ = (*p * 1LL ** p % m) * U % m;
f (415027540);
for (a = 0, p = t; p < t + N;)
a += (6972593 & e ? 2 : 1) ** p, *p++ = a % 10, a /= 10;
}
while (!*--p);
t[0]--;
while (p >= t)
printf ("%d", *p--);
}
+38
View File
@@ -0,0 +1,38 @@
Most Specific Output:
Fabrice Bellard
451 chemin du mas de Matour
34790 Grabels
France
http://www.enst.fr/~bellard
Judges' Comments:
To build:
make bellard
To run:
./bellard
This code is an nice compact example of a Modular Fast Fourier Transform.
While its output is very specific, the internal FFT has a wide variety
of uses.
Can you modify this code to produce primes such as 23523*2^70000-1,
48594^65536+1 or 6917!-1?
Selected Author's Comments:
This program prints the biggest known prime number (2^6972593-1)
in base 10. It requires a few minutes. It uses a Modular Fast
Fourier Transform to compute this number in a reasonable amount
of time (the usual method would take ages !).
The program uses >= 64 bit 'long long' type. It should run on any
system with a gcc compiler.
+60
View File
@@ -0,0 +1,60 @@
#include <stdlib.h>
#include <stdio.h>
#define a typedef
a long N;
#define i =m(p(r,o,v),e,d
N G,l,I,C,B,A,W,L,S
, R,O,c,k,s =
80, U=13
,T=169; a double P;
#define F for(
a P*E; a char*w; P sqrt(P); N H(){ F;
O=scanf(" %[#]%*[^\n]",&O); ); scanf("%ld%*c",&O);
#define D return
D O; }
#define V =malloc(sizeof(
#define M M(
#define X +=
P M N R){ s= s>=k?printf( "%ld%c"
+3*(C<1),s-k, R&7?32:10):s; D R>0?B
/2?H():getchar ():R?.9+.7*M R+1):0; }
P t(N x,P K){ D x?(x>U?0:t(x+2,K)*(x-1)
/x/K)+1/sqrt(K): t(2,K*K/U+1)*K; } N _(N
J,N x){ F*(x?&W:& A)=W+J+x; (O=x=W/(J=k*k))
||A<J||(( O=2*W/J) &&2*A/J<3); A X A-J+1){ F
J*=x+O; S--*B&&x==O ; O=x=!J){ s X x+s; M 0); }
W X W-J; S X 2; L X L-J*k+M S%8==B); } D 1; } E
p(E J,E x,E O){ F R=T; R--; )O[R]=J[R]+.8*x[R]; D O;
} P m(E W,E x,P s){ F R = U; --R; ){ E A=W+R*U; W[R]X s/
12; *W X s; *A-=*x++; F; A>W; ){ *A/=*W; F O=R; O; O--)A[O]-=
W[O]**A; A-=U; } W X 14; } D*W; } int main(int z,w*y){ N K=s,g; Y;
M z); s= B=C=15-H(); s=G= M 8); s=l=M C); G*=g=C%3?1:3; if(I=s=M 8)){ N
b=G+9,x=b*340+U,J=b*(l+5), * n V N ) * J ),*j=n+5*b; E h V P)*x),q=h+b,e=q+
b; P d=K; F; J--; )n[J]=J<b ? 0: I / 2 ; F; x; )h[--x]=0; s=M x); k=256; C
=4-C; B=C/4; s=_(_(T,0),0); F ; -- z ; ){ R=atoi(*++y); c=R>0?K=R,c :-2*R;
} z=G/K+1; z X g>z; I++; c++; F ; ++ J<l; ){ P u=0,C,y; E H =e+U,o= H+b*T,r
=o-2*T,v=r-T; F; x<G; x++){ p( H , o -T,o); o X T; H X T; q[x]= .7*(q[x-1]+h
[x] );
} p(H,
H,r );
F; x;
) { E S=
e ; w l =
" !{ ,;lf6D@"
; j X 1-g; F; *++l;
){ *S++ =*j; j X*l%3*g-
g+*l%5*b-3*b; } y =M x-G);
y =M-J)* M-x)+ M-J-1)*y+.01; y=
sqrt((u+q[--x]+.1)/y ); o-=T; C i)+
#define Z(x)(t(0,(x-C)/y)-l+1e-6*(x-Q))
.5; K=M-B); { N f=I,Q=0; F; f-Q>c; ){ P l=0
; N H = C+c/2+1; H%=c; H X(f+Q+c-2*H)/2/c*c; l=
Z(Q); O=(A-W)*Z(H)/Z(f); _(O,R=B?K>= H:L/k>O+W); *(
R?&Q:&f)=H; } Q X f; *S=*j=Q/=2; s=B?s:Q+k; f=Q+n[x/z];
n[x/z]=x%z+J%(z*2/g)?f:!putc(x?l[4*g*f/z/z/I-8]:10,stderr);
H-=U; F O=156; O--; ){ H--; *H=e[O%U]*e[O/U]/y+.8**H; } C-=Q+.5
; y i/.9)-Q-C; p(p(r+T,r,r),H,r); h[x]=.7*h[x]+C*C; u X h[x]; u*=.7
; d X C>0?-y:y; } } j X 9; } _(_(x,x),x); } D 0; }
+351
View File
@@ -0,0 +1,351 @@
Best Utility:
Bernd Meyer
Monash University, Melbourne, Australia
1/832 Blackburn Rd
Clayton, VIC 3168
Australia
http://byron.csse.monash.edu.au/
Judges' Comments:
To build:
make bmeyer
Compile with the maximum possible optimization on your system.
If your system has 80-bit internal representation of floating
point values (x86, some Motorola processors) and you want the
compressed format to be portable across platforms, you need
to set your FPU to use 64 bit mode. See the extra build lines
in the Makefile, and read the author's comments below.
If you cannot work out hwo to get into 64 bit mode, you can
try using -ffloat-store if you compile with GCC (this may have
a performance penalty). The resulting binary will have a good
chance to produce portable files, but due to the resulting
double-rounding (first internally to 80 bit, then to 64 bit
on writing the value to memory), there is a small but very real
chance any given file produced might not be portable.
To run:
In a video window (white text on black background):
./bmeyer < michael.pgm > michael.glic
Compare the michael.pgm to the screen output.
To test that you are compressing and decompressing the same way the
author was, try
./bmeyer < lenna.glic
Also try in a reverse video window:
./bmeyer < michael.pgm 2>/dev/null | ./bmeyer > new.pgm
Compare the michael.pgm to the screen output. Compare the new.pgm file
to the michael.pgm file.
Create a large reverse video xterm, say 200 columns wide and try:
./bmeyer 200 < lavabus.pgm > lavabus.glic
Produce an even smaller output:
./bmeyer -2 200 < lavabus.pgm > lavabus.glic2
Decompress that smaller glic-file:
./bmeyer -2 200 < lavabus.glic2 > new.pgm
Compare the new.pgm file to the lavabus.pgm file by viewing
them.
Don't even think of supplying different compression factors (the
dashed argument) for compression and decompression! You've been warned.
Selected Author's Comments:
GLICBAWLS
A) Function
===========
"GLICBAWLS" stands for:
"Grey Level Image Compression By Adaptive Weighted Least Squares".
And that's exactly what this program does --- feed it a .PGM file
(either raw [i.e. P5] or ascii [i.e. P2]) on stdin, and it will
output a compressed version to stdout. Feed it a compressed file
on stdin, and it will decompress it to stdout --- as either raw or
ascii .PGM, depending on what format it was compressed from. For
example:
./bmeyer < michael.pgm > michael.glic
and then
./bmeyer < michael.glic > michael.decoded.pgm
As it turns out, glicbawls compresses greyscale images (or, more
precisely, "natural" greyscale images) better than any other
program I am aware of (with the exception of the not-yet-published
program developed for my PhD thesis). Of course, this might take
some time, so a progress indicator is provided. To make things
more interesting, instead of a boring bar or percentage display,
an ASCII rendition of the image being compressed/decompressed is
output to stderr (assuming white text on black background). If you
have trouble recognizing the image, try squinting at it ;-).
If you still have trouble, simply use a terminal or xterm with
more than 80 columns, and tell glicbawls about it by giving the
number of columns as an argument. For example
./bmeyer 260 <lavabus.pgm >lavabus.glic
will allow glicbawls to use up to 260 columns, which makes things
much more recognizable.
Still running out of space? Need to compress those images just a
tad more? And maybe you can handle some loss due to the
compression? If so, you can use glicbawls' "near lossless"
compression mode. In that mode, the decoded pixel values are
allowed to differ from tbe originals, but there is an upper limit
on the magnitude of the difference. For example, if a maximum
error of 2 is allowed, an original pixel value of 37 could be
decoded as 35,36,37, 38 or 39. In order to use this mode, simply
give the maximum allowed error as an argument, with a dash ('-')
before it. For example
./bmeyer -2 < graph.pgm > graph.2.glic
will compress in a way that allows decompression with a maximum
error of two. You can combine both types of arguments, i.e.
./bmeyer -3 180 < graph.pgm >graph.3.glic
will compress with a maximum error of 3, using a 180 column
terminal for the progress display, and
./bmeyer -3 180 < graph.3.glic > graph.3maxerr.pgm
will decompress the result on such a terminal.
But wait, there is more --- you can also feed glicbawls .PPM files
(i.e. colour images), raw or ascii, your choice. Glicbawls will
compress and decompress them just fine. However, it only does
"reasonably well" on them; It beats PNG easily, but there are
certainly programs out there that can compress colour images
considerably better. And don't even *think* about using it for
so-called "artistic" images (i.e. anything that wasn't scanned
from a photo or camera)....
*****************************************************************
* *
* WARNING WARNING WARNING WARNING WARNING WARNING WARNING *
* *
* *
* Glicball is rather CPU and FPU intensive. Don't *
* run it on anything slow. Things start to be *
* usable around 300+MHz, with 600+ being highly *
* desirable. *
* *
*****************************************************************
B) Compile Instructions
=======================
Unlike most compression program, glicbawls makes heavy use of
floating point maths --- and not all FPUs are created equal. Most
importantly, the x86 and 68k FPUs use 80 bit floating point
formats internally, while most other processors use IEEE 64 bit
formats by default. If not taken care of, this means that a
glicbawls file compressed on one CPU cannot generally be
decompressed on another.
Fortunately, just about all current FPUs can be put into IEEE 64
bit mode (or at least something close enough for
glicbawls). Unfortunately, there is no standard way of doing
so. For this reason, the build file contains *three* compile
lines; One for machines that already use 64 bit mode by default
(most RISC processors), one for linux/x86 machines using libc4,
libc5 or glibc2.0, and one for linux/x86 machines using glibc2.1
(glibc2.1 no longer exports the __setfpucw function, necessitating
the use of gcc inline assembly. *Grumble*).
So, if you are building on a machine that does not, by default,
use IEEE 64 bit floating point doubles, you'll have to define Y to
be a command that switches it into that mode. If you fail to do
so, your glicbawls executable will still be able to decompress its
own compressed files, but you may be unable to exchange files with
glicbawls on other machines.
C) Obfuscation
==============
Most of the obfuscation of this program was driven by the
desperate struggle to fit all of glicbawls' features into code
that fits the IOCCC's size limits. All identifiers names are
single-character, which was only possible by ruthless exploitation
of scope. There is a function M() that handles nearly all input
from stdin, handles all output to stdout, and also recursively
calculates one of the mathematical expressions needed for error
modelling. There is a function that calculates (A^(-1)*b)*x with A
a matrix and b and x being vectors, and does so in a very
efficient way --- but one would be hard pressed to find it. There
is an arithmetic coder that is even less recognizable. A lot of
loop variables don't get initialized, but instead the code is
arranged in such a way that they just happen to have the right
value when control flow reaches the loops. Lots of functions use
the same two global scratch variables. Variables change their
meaning all the time, and the differences between compressing and
decompressing are handled in rather subtle ways all over the
program. The string that holds the ascii values for displaying the
progress image doubles as a description on how to find a pixel's
causal neighbours. And then there are a few #define's that really
are just in there to save a few characters, but as an added
"benefit" make the source ever more unreadable.
In short --- running it through the preprocessor and the
pretty-printer will give you something that looks slightly less
like line noise and slightly more like a C program, but unless you
are a true wizard, it is unlikely to gain you any insights into
what is actually going on....[0]
D) Bugs, Assumptions and TODOs
==============================
Glicbawls assumes that characters are 8 bit wide, and that the
character set used is ASCII. If one of these isn't true, all hell
will break loose.
The .PGM headers are not checked very thoroughly --- glicbawls
will happily try to encode lots of files that it shouldn't
touch. The old adage of "garbage in, garbage out" holds in that
case. Furthermore, even if glicbawls detects an incorrect input,
it fails to provide a meaningful error message, and instead
simply aborts.
When decompressing a near-losslessy encoded image, the maximum
allowed error is required as a command line parameter. This should
really be saved in the compressed file!
Glicbawls relies on the decimal representation of all integers
having less than 255 digits. While ANSI C does not guarantee this,
it seems rather unlikely that anyone in the foreseeable future
would use images with 10^255 rows, columns or different levels of
grey. Also, it is assumed that any integer used can be cast to a
double and back without loss of precision. This limits the number
of rows, columns and grey levels to 9 quintillion, which should
also be sufficient for the next few years.
There is a theoretical chance that you might get a division by
zero error. You have a MUCH better chance of getting hit by
lightning the very second you realize that you just won a few
million in a lottery. But if it happens to you, don't say I
didn't warn you! Instead, go out and buy a lightning rod and a
lottery ticket ;-)
At one point, a pointer to int is used as the target of a "%1[#]"
conversion in a scanf, which makes gcc rather unhappy, but
shouldn't really cause anyone any trouble. The same goes for a
couple of assignments which are used as truth values.
E) Algorithm
============
An exhaustive explanation of the algorithm used would go beyond
the scope of an info file, and would also be quite difficult in
pure ASCII, so the following is just a rough outline, and contains
some compression-speak...
The image is handled in scanline ordering. For each pixel, an
expected value is calculated by creating a least squares predictor
of order 12 based on all of the previously encoded/decoded
pixels. However, the contribution of each pixel is weighted
according to its Manhattan-distance from the current pixel,
D. That weight used is pow(0.8,D). [1][2][3]
In a similar way, the prediction *errors* for all previous pixels
are combined --- a weighted average (with weight pow(0.7,D)) of
the squares of all previous prediction errors is taken, and the
square root of the (appropriately scaled) result is called sigma.
The predicted value and sigma are then used as the parameters of a
Student or t-distribution (which is similar to a normal
distribution, but has more weight in the tails), providing a
probability distribution for the current pixel.
Next, the possible interval of values for the current pixel is
halved, and through integration of the probability distribution, a
probability is calculated for the pixel value being in the lower
half. During encoding, the actual value is examined, and the
result encoded using an arithmetic coder. During decoding, the
arithmetic decoder provides the information which half the actual
value is in. In both cases, the interval borders are adjusted
accordingly, the arithmetic coder/decoder updated, and the
interval halving repeated until the precise value has been
en/decoded[4].
[0] Yes, this could be seen as a challenge....
[1] Actually, the weight is pow(0.8,D)/s, where s is the sigma
used for en/decoding the particular previous pixel. Dividing
by s is a rather arbitrary action justified only by the
improvement in results. Mathematically, I can only justify
dividing by s^2, or not dividing at all....
[2] Obviously, these least squares predictors are not calculated
from scratch for each pixel. Some clever reuse of earlier
results allows O(1) calculation, rather than the
O(previous_rows*columns) this description would suggest.
[3] As anyone who has ever tried local least squares knows from
bitter experience, there is a lot of numerical instability
associated with them. So glicbawls adds a bias towards an
averaging predictor to the equation system the least squares
predictor is calculated from. The weight that is given to
this bias is constantly adjusted throughout coding/decoding,
thus justifying the 'a' in "glicbawls".
[4] In the case of near-lossless coding, the interval is not
necessarily *halved*, but rather split at a convenient point
(the split points are chosen in such a way as to minimise the
expected number of bits needed for coding). Also, the
iteration ends as soon as the interval is small enough to
guarantee decoding within the requested maximum error.
####################################################################
Photo Credit:
Lavabus was taken by the judge, Landon Curt Noll. Michael was
provided by the author. Lenna is a 1972 Playboy centerfold.
michael.pgm
The author's Godchild and nephew.
lavabus.pgm
A bus that was trapped by lava from Kilauea volcano in
Hawaii, USA. Nobody was in the bus at the time, BTW.
Photo date: 1981.
lenna.glic
A November 1972 Playboy centerfold was scanned in long ago and
has been used for image compression research since then. Playboy
originally threatened to prosecute unauthorized use, but
eventually granted that, having been in use for image compression
testing for so long, it was now a useful benchmark. (Note: This
picture doesn't show very much.)
+20
View File
@@ -0,0 +1,20 @@
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#define e(t, v, w) n t(u x, u y) { n a = sqrt(x+y); r ((v - a) * (w - a)); }
#define w while(
#define r return
typedef char u; typedef short q; typedef double n;
u *z = "Z\253\345\252\256\351\325\232\265f\256\246nyZf\253U^\266\232]z\352i\236\226i[m\266\351\252\255\246\235V\247e\235\226\276Z\371jUg\x3\362\212pX\254\251PH\253\332\225\373\235\b\v\336HO.\203Qf\201\x1d\207\211\357\367S7|)=\331n\x4!E<\233Z\246\x1flv\232d(r\263\274\375\313\305\200\361\302\327\274\375\300\201c\250-|\246]\304\253I\377W\227R^\251\350\x2""C\251\203\311O\346\242\vDh\r\357\306x\325\274\315\366c\th\325\272\376\311X+:\325\354q\263|\257\x1c\327\316g\204\266s\211\357\370A(\x11""D\321\x1d:\352\327\x1bk@\x11""E-\310s\271\235\304\273\x2+\x4I\274jT\256\363\214\307{\232a\3270\a+qm\270\aI\315\337\220\x17\x18\315G\217\371@\215\335\v[v\335\205\343\250-|\246\373:\225\f\2552Oe]\206U\272\355\x10\327)u\rY]\276>\243\333w{3\x19\v""acC8\3775\351\b\377\204lJnsy.:\330\2553rKx'\362'!%\302\271\376|\236skq\242C\251\263&\x15K\x4""fA\227\211\242r7]\371\333\200z%\277\207CJ\255^}\264\237\327\275Z\n;L\x1aN#\371N\354G\256skq\242K!\364\211E\214\x17\377\343z\340w\233\272\354eTD\262t\365\335[_\233\225J\313\2746\334\x3\b\244F&\240]\222\332\210\351\376rJs<\2265I;\203Xd\272\377\345\214\x17\263]2I\237\302\253\346\355\332\343\350G\327\"\350f}\301n\223\366\300\210\343j\247\316%\363\210\345\n\252\215c\255\314\3248\300\261\350RM7\203\261\371\265\r_\220\x17\x19\a(+u\x1d=I\235\314\331@\310Cl\x16\210\307\345\357\306\x1f""e\345R\354y\257\367\350!.\x1f`\345uW&\204\246\367>\226\335\205\353\x18\336;\302\334\266\213Fn\233\201vAE\325+qnVR\222e\237E<e\203!f\333\345[\x17#\205\273I\314\371n\340\304\205\225h\323\336\371\x1c""7\227\201%\327\201p\326\263\351f\x19\a\v\336;uI\312?\214\265I1$\302+\373\233v\336\x5\306,y\313OD\351d*\350f\357H\262]\x3\332l\365L\237Qs\320{\231\244\204d\352v\335\215\327\357\200\247\302W\x10", x, y;
n g() { r (n)rand()/18972; } n t, v; q F, B, C; e(a, 0, 3.0) e(b, 3.0, 4.125)
e(c, 4.125, 9) u f(n (*h)()) { do { t=g() * 6.283184; v = sqrt(g() * 72); y =
sin(t) * v; x=cos(t)*v; } w (h(x*x,y*y)>=0)||(fabs(x) > 5) || (fabs(y) > 5));
r ((y+5) * 11) + x + 7; } u k(q x, u l) { u o = 0; F = 0; w F < 189) { B =C =
0; w 1) { y = ((z[F/4]>>((F++%4)*2))&3) - 1; if (y&2)
break; C = (C*2)+y, ++B; } if (!(C - x | B - l)) r (o<26)?o+0x61:((2108973>>(
(o-26)*8))&47); ++o; } r 1; } u s[1079]; u *E(u v) { u *x = s; w v--)w *(x++)
); r x; } main() { q A = 0, B = 0, C = 1078; u l = 0; u *p = s; srand(time( 0
) ); w C) { A = (A*2) + ((((z[B/8+48]+114)^2)>>(7-(B++%8)))&1),++l; x = k(A,l
); if (x-1) { *(p++)=x, A=l=0, C--; } } printf("%s%s %s%s%s\n", E(0), E(f(c))
, E(f(a)), E(1), E(f(b))); }
+56
View File
@@ -0,0 +1,56 @@
Best Abuse of User:
Moxen N. Briddlebane
24 Oxtree Ave.
The Xoemn, MN 68214
Lord Zarbon
24 Oxtree Ave.
The Xoemn, MN 68214
Judges' Comments:
To build:
make briddlebane
To run:
./briddlebane
One could argue that this program was a "diseased dumpster of tripe"
but I suspect that would only result in the judges being heckled as a
"scum-encrusted congress of obscurity" (but only if it was in the early
evening of Dec 22, 2000).
Can you find out how it stores the insult strings? Can you then take
an insult and figure out when it will be uttered?
[sc] The code also contains a buffer overflow bug which I have fixed!
The array size of "s" should be 1079 characters long. (From 0 to 1078
inclusive!). Without this it results in an error in the encoding of
"decrepit" -- For a 32bit little endian machine using GCC (because of
the way it assigns variables to memory) it will terminate "decrepit"
with the character '\200' (the last value of F) instead of '\0'.
Selected Author's Comments:
This program was broadcast from deep within the Zarbonic Cluster
and received at 9:03pm on March 21st, 2000 by Moxen N. Briddlebane.
The original author, as designated by other components of the
transmission, refers to himself simply as "Lord Zarbon", though
offers no information in relation to the significance of that
post. The sole purpose of this program appears to be to degrade
and humiliate the people of this planet by calling them names.
It takes no input, only produces a single line of slanderous output.
The program appears to be rather confused, internally. It is
unclear whether or not "Lord Zarbon" truly understands the
mechanics of programming. What is particularly disturbing is
the curious method of insult-encoding employed by this program.
Furthermore, it is ambiguous how said data is arranged and why
it is necessary to resort to trigonometric functions to handle
it. One of the real mysteries involves the numbers "114" and
"2", which are, according to Lord Zarbon, very deliberate.
+20
View File
@@ -0,0 +1,20 @@
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#define e(t, v, w) n t(u x, u y) { n a = sqrt(x+y); r ((v - a) * (w - a)); }
#define w while(
#define r return
typedef char u; typedef short q; typedef double n;
u *z = "Zォ蟐ョ鰈垠fョヲnyZfォU^カ咯z麒椁i[mカ鬪ュヲ抃ァe摶セZ�Ug\x3�pXャゥPHォレ方拿b\v゙HO.ゲf―x1d㊨�S7|)=ルn\x4!E<媚ヲ\x1flv單(rウシ�ヒナ€�ラシ�タ…ィ-|ヲ]トォI�W由^ゥ鐔x2""CゥλO譴\vDh\r�xユシヘ�\thユコ�ノX+:ユ�ウ|ッ\x1cラホg┯s会�(\x11""Dム\x1d:�\x1bk@\x11""E-ネsケ敍サ\x2+\x4IシjTョ�ヌ{啾ラ0\a+qmク\aIペ申x17\x18ヘG錠@在\v[vン�ィ-|ヲ�:表fュ2Oe]�コ偆x10ラ)u\rY]セ>」ロw{3\x19\v""acC8�5饅b��Jnsy.:リュ3rKx'�'!%ツケ�|枹kq「Cゥウ&\x15K\x4""fA莱「r7]�€z%ソ④Jュ^}エ湶スZ\n;L\x1aN#��ョskq「K!�E圭x17�縻烱崋�TDイt�[_尓Jヒシ6ワ\x3\b、F&�]嬬磯�rJs<�5I;スdコ�蛹\x17ウ]2I淞ォ跫レ肛Gラ\"鑁}チn賑タ医jァホ%�藹nェ皇ュフヤ8タア鏗M7Τ�\r_申x17\x19\a(+u\x1d=I變ル@ネCl\x16杏襃ニ\x1f""e薐�ッ�!.\x1f`蛄W&┬�>餅�\x18゙;ツワカ祈n宦vAEユ+qnVR弾檸<e�!fロ藜\x17#�Iフ�狷�hモ゙�x1c""7浴%ラ}ヨウ馭\x19\a\v゙;uIハ?厳I1$ツ+蕙v゙\x5ニ,yヒOD馘*鑁�イ]\x3レl�櫺sミ{勁�黐ン細�ァツW\x10", x, y;
n g() { r (n)rand()/18972; } n t, v; q F, B, C; e(a, 0, 3.0) e(b, 3.0, 4.125)
e(c, 4.125, 9) u f(n (*h)()) { do { t=g() * 6.283184; v = sqrt(g() * 72); y =
sin(t) * v; x=cos(t)*v; } w (h(x*x,y*y)>=0)||(fabs(x) > 5) || (fabs(y) > 5));
r ((y+5) * 11) + x + 7; } u k(q x, u l) { u o = 0; F = 0; w F < 189) { B =C =
0; w 1) { y = ((z[F/4]>>((F++%4)*2))&3) - 1; if (y&2)
break; C = (C*2)+y, ++B; } if (!(C - x | B - l)) r (o<26)?o+0x61:((2108973>>(
(o-26)*8))&47); ++o; } r 1; } u s[1079]; u *E(u v) { u *x = s; w v--)w *(x++)
); r x; } main() { q A = 0, B = 0, C = 1078; u l = 0; u *p = s; srand(time( 0
) ); w C) { A = (A*2) + ((((z[B/8+48]+114)^2)>>(7-(B++%8)))&1),++l; x = k(A,l
); if (x-1) { *(p++)=x, A=l=0, C--; } } printf("%s%s %s%s%s\n", E(0), E(f(c))
, E(f(a)), E(1), E(f(b))); }
+64
View File
@@ -0,0 +1,64 @@
#define/**/X
char*d="X0[!4cM,!"
"4cK`*!4cJc(!4cHg&!4c$j"
"8f'!&~]9e)!'|:d+!)rAc-!*m*"
":d/!4c(b4e0!1r2e2!/t0e4!-y-c6!"
"+|,c6!)f$b(h*c6!(d'b(i)d5!(b*a'`&c"
")c5!'b+`&b'c)c4!&b-_$c'd*c3!&a.h'd+"
"d1!%a/g'e+e0!%b-g(d.d/!&c*h'd1d-!(d%g)"
"d4d+!*l,d7d)!,h-d;c'!.b0c>d%!A`Dc$![7)35E"
"!'1cA,,!2kE`*!-s@d(!(k(f//g&!)f.e5'f(!+a+)"
"f%2g*!?f5f,!=f-*e/!<d6e1!9e0'f3!6f)-g5!4d*b"
"+e6!0f%k)d7!+~^'c7!)z/d-+!'n%a0(d5!%c1a+/d4"
"!2)c9e2!9b;e1!8b>e/! 7cAd-!5fAe+!7fBe(!"
"8hBd&!:iAd$![7S,Q0!1 bF 7!1b?'_6!1c,8b4"
"!2b*a,*d3!2n4f2!${4 f. '!%y4e5!&f%"
"d-^-d7!4c+b)d9!4c-a 'd :!/i('`&d"
";!+l'a+d<!)l*b(d=!' m- a &d>!&d'"
"`0_&c?!$dAc@!$cBc@!$ b < ^&d$`"
":!$d9_&l++^$!%f3a' n1 _ $ !&"
"f/c(o/_%!(f+c)q*c %! * f &d+"
"f$s&!-n,d)n(!0i- c- k) ! 3d"
"/b0h*!H`7a,![7* i] 5 4 71"
"[=ohr&o*t*q*`*d *v *r ; 02"
"7*~=h./}tcrsth &t : r 9b"
"].,b-725-.t--// #r [ < t8-"
"752793? <.~;b ].t--+r / # 53"
"7-r[/9~X .v90 <6/<.v;-52/={ k goh"
"./}q; u vto hr `.i*$engt$ $ ,b"
";$/ =t ;v; 6 =`it.`;7=` : ,b-"
"725 = / o`. .d ;b]`--[/+ 55/ }o"
"`.d : - ?5 / }o`.' v/i]q - "
"-[; 5 2 =` it . o;53- . "
"v96 <7 / =o : d =o"
"--/i ]q-- [; h. / = "
"i]q--[ ;v 9h ./ < - "
"52={cj u c&` i t . o ; "
"?4=o:d= o-- / i ]q - "
"-[;54={ cj uc& i]q - -"
"[;76=i]q[;6 =vsr u.i / ={"
"=),BihY_gha ,)\0 " , o [
3217];int i, r,w,f , b ,x ,
p;n(){return r <X X X X X
768?d[X(143+ X r++ + *d ) %
768]:r>2659 ? 59: ( x = d
[(r++-768)% X 947 + 768] ) ?
x^(p?6:0):(p = 34 X X X )
;}s(){for(x= n (); ( x^ ( p
?6:0))==32;x= n () ) ;return x ; }
void/**/main X () { r = p
=0;w=sprintf (X X X X X X o
,"char*d="); for ( f=1;f < * d
+143;)if(33-( b=d [ f++ X ] )
){if(b<93){if X(! p ) o
[w++]=34;for X(i = 35 +
(p?0:1);i<b; i++ ) o
[w++]=s();o[ w++ ]
=p?s():34;} else X
{for(i=92; i<b; i
++)o[w++]= 32;} }
else o [w++ ]
=10;o [
w]=0 ;
puts(o);}
+67
View File
@@ -0,0 +1,67 @@
Best Layout:
Don Yang
UCSD
259 E. Bellbrook St.
Covina, CA 91722
USA
http://omoikane.cjb.net
Judges' Comments:
To build:
make dhyang
Try:
cc dhyang.c -o saitou
./saitou > aku.c
cat aku.c
cc aku.c -o soku
./soku > soku.c
cat soku.c
cc soku.c -o zan
./zan > zan.c
cat zan.c
cc zan.c -o aku
./aku | diff - aku.c
A beautiful combination of solving several different problems, but
mostly, the single most impressive layout we've ever seen. Many
programs have *one* interesting layout; this one has four.
It may be informative to run the code through a "beautifier", to
study it, but the layout itself is where most of the interest lies.
Selected Author's Comments:
This one is dedicated to Saitou Hajime fans ^_^x
Instead of making one self reproducing program, what I made was a
program that generates a set of mutually reproducing programs, all of
them with cool layout!
For your enjoyment:
1. Compile saitou.c
2. Run a.out and pipe output to another .c file
3. Compile that file
4. Repeat steps 2 and 3 until eventually the output cycles
To interpret the output: the saitou.c is an image of Saitou Hajime,
which eventually generates three sources files that are images of
"aku soku zan" (sin swift slay), Saitou's motto ;)
For best viewing, set tab spaces to 8 characters, and set your
terminal fonts to as close to square as possible. I hate to do this
but you know, size...
saitou.c and all its output compiles with gcc if your OS uses ASCII
character set. No file is included and all functions assume default
int return type (a source of compile warnings)
+43
View File
@@ -0,0 +1,43 @@
#include <EXTERN.h>
#include <perl.h>
#include <XSUB.h>
#include <math.h>
#define qq __FILE__
#define cc (((3)))
#define ZZ(YY,WW) XS(YY) {AV*gg\
= perl_get_av( "SS",cc-cc); SV* Ss,*uu; char \
ii=*(SvPV( perl_get_sv("_", 0*cc),na)\
) %(36+cc); ( av_len(gg) <1)?( perl_call_pv\
("__",0/cc)):(Ss =av_pop(gg), uu= av_pop(gg),(((i\
i==pow(2,cc))||( ii==(40-cc)))&&( SvNV(Ss)==0))?(\
av_push(gg,uu), av_push (gg,Ss), perl_call_pv("\
_",3-cc)):( av_push (gg, newSVnv(WW\
) ) ,1)) ; }
ZZ(uu,SvNV(uu)- (SvNV(Ss)*(SvIV( uu)/SvIV(Ss))))
ZZ(ii,SvNV (uu)-SvNV(Ss))ZZ (ff,SvNV(Ss
)+SvNV(uu))ZZ(gg ,pow(SvNV(uu), SvNV(Ss)))ZZ(Ss,
SvNV(uu)/SvNV(Ss ))ZZ(ss,SvNV(Ss) * SvNV(uu)) void
bb( ){ newXSproto("UU", ff,qq,
""); newXSproto( "W""W",ii,qq,"") ;newXSproto("TT"
,ss,qq,"") ; newXSproto("Y" "Y",Ss,qq,
""); newXSproto( "vv",uu, qq,""); newXSproto("aa",
gg,qq,""); }int main(int _,char* *__, char**ee){
PerlInterpreter* aa=perl_alloc(); char*dd[]= { "",
"-e", "0"} ; perl_construct (aa); perl_\
parse(aa, bb, cc,dd ,ee) ;perl_eval_sv
(newSVpv("_:$_= <> ; defined or exit; @ARGV"
"=split; __:$_= shift;defined or goto _; chomp "
";(m*^\\x70oO" "\\x74$*i)?(pri" "nt \"$_ w\\x"
"61s h\\145r\\x" "65!\\n\"):((m*" "^\\s\\*(-?\\d+"
"(\\.\\d+)?)\\s" "\\*$*)?(push@SS ,$1):(&{chr(((o"
"rd)%39)+3**4)x2 } )); goto __; sub ff { @SS= ("
")} sub __{print \"stack empty\\" "n\"} sub ss{$#"
"SS<0 and goto & __; print $SS[$" "#SS].\"\\n\"} "
"sub SS{ $#SS<0 and goto &__ ; print pop @SS}"
"sub _ { print \"divide by zer" "o\\n\"}sub ii{"
"map{ print\"$_" "\\n\" } reverse @SS} sub AUTOLO"
"AD { print\"un" "implemented\\n" "\"} sub gg{ $#"
"SS<0 and goto &__;push@SS,$SS[ $#SS]} sub uu{ "
"$#SS<1 and goto &__;$SS[ $#SS]+= $SS[$#SS-1];$SS"
"[$#SS-1]=$SS[$" "#SS]-$SS[$#SS-" "1]; $SS[$#SS]-"
"=$SS[$#SS-1]} ",0),0 ); exit(cc); }
+247
View File
@@ -0,0 +1,247 @@
Worst Abuse of the Rules:
David Lowe
1224 11th Avenue
San Francisco, California, 94122
USA
http://pootpoot.com/~dlowe/
Judges' Comments:
To build:
make dlowe
To run:
echo "13 14 15 16 17 + - * / p" | ./dlowe
When this entry was submitted the rules of the IOCCC did not prohibit
the use of embedded language interpreters. The judges considered
disqualifying this entry because of the use of perl, but on the other
hand it qualifies as the Worst Abuse of the Rules. As a previous winner
(*) David Lowe continues to inflict the highest quality "poot" on the
Judges.
The program also contains an undocumented command for Chad and Chongo.
The judges' comments contain a clue to the hidden command :-).
(*) The IOCCC uses an anonymous judging process which keeps the identity
of the submitters hidden until all the prize winners have been selected.
Selected Author's Comments:
Usage:
dlowe [file ...]
Synopsis:
This is a reverse polish calculator, loosely based on the dc(1) unix
calculator.
Syntax:
This program understands the following dc(1) commands:
p prints the top stack value without altering the stack.
P prints the top stack value, removing it from the stack, and
doesn't print a trailing newline.
f prints the contents of the stack, one number per line,
without modifying it.
c clears the stack.
d pushes a copy of the top stack value onto the stack.
r reverses the order of the top two stack values.
And the following arithmetic operators are supported:
+ Pops 2 values and pushes their sum.
- Pops 2 values and pushes the result of subtracting the first
from the second.
* Pops 2 values and pushes their product.
/ Pops 2 values and pushes the result of dividing the second
by the first.
^ Pops 2 values and pushes the result of raising the second
to the power of the first.
% Pops 2 values and pushes the remainder of the division that
/ would do.
The precision and range are double, like it or not, except that the
modulus operator actually returns (p1 - (p2 * (p1 / p2))), but with
the innermost division calculated at integer precision. This is
usually what you expect (e.g. echo "12 8 % p" | ./dlowe == 4)
Commands are read from stdin or from a list of files named on
the command line. Unlike dc(1), multiple commands on the same line
must be space separated. Commands are only executed when a newline
or EOF is encountered.
Diagnostics:
"stack empty" Not enough on the stack for the requested command
"divide by zero" Attempt to divide by zero
"unimplemented" Invalid input
Floating point exception (core dumped) (or something to that effect)
Bug in Perl_sv_upgrade causes this in some cases when
the results of an operation are really huge (> 10^308)
This bug appears to be fixed in perl5.6.0
Examples:
$ echo "12 13 14 15 16 + + + + f" | ./dlowe
70
$ echo "12 13 14 15 16 17 + - * / p" | ./dlowe
-0.0515873015873016
$ echo "+" | ./dlowe
stack empty
$ echo "999999999999999 1 + p" | ./dlowe
1e+15
$ echo "99999999999999 1 + p" | ./dlowe
100000000000000
$ echo "12.5 9 % 10 * 15 + f" | ./dlowe
50
$ echo "7 P 6 d P P 8 p" | ./dlowe | tr 876 tpo
poot
Code Concept:
We all know that Perl and other VHLLs (very high level languages)
are particularly well-suited for (among other things) string
handling, I/O, and powerful built-in datatypes, and (relatively)
poorly suited for number crunching and other processor-intensive
tasks - areas where C is strongest. This program takes this
knowledge to its extreme conclusion, using each language for its
strengths. Thus, it uses Perl to read and parse input, for output,
and for the easy-to-use list primitive, and uses C for mathematical
operations. Since the rules of this contest state that the program
must be generated by an ANSI C compiler, of course, the outer Perl
layer is wrapped with a thin layer of C.
In case that wasn't clear, in a nutshell: this program is C, calling
embedded Perl (contained in a C string), which in turn calls back to
C, which performs math on Perl data types and calls Perl functions for
error reporting.
Requirements:
Unfortunately, Perl is an evolving beast - that includes the
embedding API and the XS API. The code was developed under
Perl 5.005_03, successfully tested against Perl 5.6.0, Perl 5.005_02
and Perl 5.004_04, and according to the version delta documentation,
should work as-is with Perl 5.002 and later (which has been around
since February 1996). To clarify - it's not the Perl code itself
that may be non-portable, it's the C code for embedding Perl and for
calling C from Perl.
It is also important that Perl be installed cleanly and correctly.
You may have problems linking if, for example, you have multiple
overlapping versions of Perl installed (which might not be a problem
for scripts, but causes problems with embedding the interpreter).
More commonly, you may get non-fatal warnings from the linker, caused
by slight misconfigurations of Perl on your system.
Some compilers also complain that "third argument of `main' is
deprecated" or something to that effect. But in Perl prior to
5.6.0, the header file "proto.h" actually had a prototype for main,
so applications which embed Perl must use the three argument form
of main.
Aside: history...
Larry Wall wrote the original Perl in 1986-87, the same two successive
years he won the IOCCC. I hope this program helps you to realize that
this was no fluke - that Perl and Obfuscation are as inseparable as,
say, camels and humps.
Obfuscated?
. Reverse polish notation is pretty strange, in and of itself.
. The layout of the program is three roughly symmetrical "stacks"
of code. This layout is quite sensitive in places - my C indenter
actually breaks the code by inserting spaces in certain places.
. Anyone who has ever programmed in Perl can attest to the fact that
it is particularly well-suited to obfuscation; thus, the Perl is
obfuscated. (Here's my favorite legal Perl from this program:
'_:$_=<>;' - but '$SS[$#SS]-=$SS[$#SS-1]' isn't bad, either).
. I've eschewed traditional branch and loop structures such as
'if' and 'for', in favor of their oft-neglected cousins, 'goto'
and '?:', in both the Perl and C code.
. I've used some highly magical Perl incantations, such as symbolic
references, the 'goto &NAME' syntax, AUTOLOAD for exception handling,
and abuse of the default scalar ($_).
. I've also deliberately used Perl syntax that is very much unlike
C syntax: the &NAME rather than NAME() function calling syntax,
leaving off parentheses wherever possible, using print() instead
of printf(), and using the English style logic operators 'and' and
'or' rather than '&&' and '||', for example.
. The fact that all the Perl code is in double-quotes doesn't lend
any readability to the regular expressions and quoted strings
therein.
. The points and ways in which C and Perl connect are *really*
obscure. They're also incredibly poorly documented, as they're
primarily used in machine-generated code. However, there's a
wealth of example code on CPAN (www.cpan.org).
. The Perl API functions are almost all macros, so you will probably
find that preprocessor expansion will only make things worse. They
also have helpful, verbose names like SvNV, SvIV, and newSVpv. I
couldn't have done better myself!
. Figuring out how the mathematical C functions get called is a bit
tricky. Note the lack of explicit switching based on command
input.
. Because of the "interesting" way that commands are interpreted,
all of the commands have synonyms. For example, if you find it
easier to remember, '=' is synonymous with 'd'. This is makes it
possible to write (even more) obfuscated reverse polish commands
(I figure this explanation moves the synonyms from 'bug' to
'feature'!)
. The first IOCCC entry with an "easter egg"?...
Aside: on unobfuscated Perl
My original intent was to write obfuscated C and crystal-clear Perl,
to highlight my bending of the rules. Unfortunately, Perl really
doesn't lend itself to crystal-clear code...
Bending the rules?
Well, the rules never state that you can't embed another programming
language, but on the other hand, knowing Perl probably isn't high on
the list of qualifications for judges... Oh dear, I guess your C
beautifier won't help too much, either ;)
If you don't change the rules, it'll be embedded Ada next year!
AutoDefend
A. Isn't this the obfuscated C contest? What's this Perl $#_&&$_?
D. Hey, this program *is* 100% C, and does not exec an external Perl
interpreter. It simply links against the Perl language library.
The "Perl code" is just a C string constant.
A. Perl isn't portable enough, or ubiquitous enough.
D. I'd argue that it is more portable than X. According to the Perl
folks, it runs on the following platforms: Acorn, AIX, Amiga, AS/400,
BeOS, Concurrent, Debian, DEC OSF/1, Digital UNIX, EPOC, FreeBSD,
Guardian, HP-UX, IRIX, LinuxPPC, LynxOS, MacOS, MachTen, Minix, MPE/iX,
MS-DOS, MVS, NetBSD, Netware, NextStep, OpenBSD, OpenLinux, ODT, OpenVMS,
OS/2, OS390, OSR, PowerMAX, Psion, QNX, Redhat, Reliant UNIX, RISCOS,
SCO, SGI, SINIX, Slackware, Solaris, Sun, SuSE, Tandem, Tru64, UNIX,
U/WIN, Unixware, VMS, Win31, Win32, Windows 3.1, and Windows 95/98/NT/2K.
Granted, embeddable Perl isn't quite so portable, but still...
Also, Perl 5 is bundled with the following OS distributions: AIX 4.3.3+,
FreeBSD 3.0+, IRIX 6.4+, every Linux distribution, NetBSD, OpenBSD, and
DEC Tru64 5.0+, again according to the Perl people.
+46
View File
@@ -0,0 +1,46 @@
/*
* Calculates the Julian Day from any day,month,year tuple.
*
* This is valid for all dates, including both julian and gregorian calendars.
*
* The algorithm is taken from Astronomical Algorithms by Jean Meeus.
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
double dmy2jd(double d, int m, int y) {
int b;
if (m <= 2) {
y--;
m += 12;
}
/* Handle Julian dates */
if (y < 1582 || (y == 1582 && (m < 10 || (m == 10 && d <= 4)))) {
b = 0;
} else {
int a;
a = y/100;
b = 2 - a + a/4;
}
return (int)(365.25 * (y+4716)) + (int)(30.6001 * (m+1)) + d + b - 1524.5;
}
int main(int argc, char **argv) {
double jd;
if (argc != 4) {
fprintf(stderr, "usage: %s day_float month_int year_int\n", argv[0]);
return 1;
}
jd = dmy2jd(atof(argv[1]), atoi(argv[2]), atoi(argv[3]));
printf("%f\n", jd);
return 0;
}
+771
View File
@@ -0,0 +1,771 @@
14th International Obfuscated C Code Contest Guidelines, Hints and Comments |
Copyright (c) Leonid A. Broukhis, Jeremy Horn, Landon Curt Noll and |
Peter Seebach, 1998. |
All Rights Reserved. Permission for personal, education or non-profit use is |
granted provided this this copyright and notice are included in its entirety |
and remains unaltered. All other uses must receive prior permission in |
writing from the contest judges. |
ABOUT THIS FILE:
This file is intended to help people who wish to submit entries to
the International Obfuscated C Code Contest (IOCCC for short).
This is not the IOCCC rules, though it does contain comments about
them. The guidelines should be viewed as hints and suggestions.
Entries that violate the guidelines but remain within the rules are
allowed. Even so, you are safer if you remain within the guidelines.
You should read the current IOCCC rules, prior to submitting entries.
The rules are typically sent out with these guidelines.
Changes from the 1998 rules are denoted by change bars. ---> |
Not every change is marked in this file is marked, but
most are. :-)
WHAT'S NEW IN 2000:
The contest runs from 01-Feb-2000 00:00 UTC to 31-Mar-2000 23:59 UTC. |
HINTS AND SUGGESTIONS:
You are encouraged to examine the winners of previous contests. See
FOR MORE INFORMATION for details on how to get previous winners.
Keep in mind that rules change from year to year, so some winning entries
may not be valid entries this year. What was unique and novel one year
might be 'old' the next year.
An entry is usually examined in a number of ways. We typically apply
a number of tests to an entry:
* look at the original source
* convert ANSI tri-graphs to ASCII
* C pre-process the source ignoring '#include' lines
* C pre-process the source ignoring '#define' and '#include' lines
* run it through a C beautifier
* examine the algorithm
* lint it
* compile it
* execute it
You should consider how your entry looks in each of the above tests.
You should ask yourself if your entry remains obscure after it has been
'cleaned up' by the C pre-processor and a C beautifier.
Your entry need not pass all of the above tests. In certain
cases, a test is not important. Entries that compete for the
'strangest/most creative source layout' need not do as well as
others in terms of their algorithm. On the other hand, given
two such entries, we are more inclined to pick the entry that
does something interesting when you run it.
We try to avoid limiting creativity in our rules. As such, we leave
the contest open for creative rule interpretation. As in real life
programming, interpreting a requirements document or a customer request
is important. For this reason, we often award 'worst abuse of the
rules' to an entry that illustrates this point in an ironic way.
We do realize that there are holes in the rules, and invite entries
to attempt to exploit them. We will award 'worst abuse of the rules'
and then plug the hole next year. Even so, we will attempt to use
the smallest plug needed, if not smaller. :-)
Check out your program and be sure that it works. We sometimes make
the effort to debug an entry that has a slight problem, particularly
in or near the final round. On the other hand, we have seen some
of the best entries fall down because they didn't work.
We tend to look down on a prime number printer, that claims that
16 is a prime number. If you do have a bug, you are better off
documenting it. Noting "this entry sometimes prints the 4th power
of a prime by mistake" would save the above entry. And sometimes,
a strange bug/feature can even help the entry! Of course, a correctly
working entry is best.
People who are considering to just use some complex mathematical
function or state machine to spell out something such as "hello,
world!" may want to try and be more creative.
Ultra-obfuscated programs are in some cases some cases easier to
deobfuscate than subtly-obfuscated programs. Consider using
misleading or subtle tricks layered on top of or under an
appropriate level of obfuscation.
Programs that use VTxxx/ANSI sequences that are NOT limited to a
specific terminal brand and that can also work in a standard xterm
are considered portable.
OUR LIKES AND DISLIKES:
Doing masses of #defines to obscure the source has become 'old'. We
tend to 'see thru' masses of #defines due to our pre-processor tests
that we apply. Simply abusing #defines or -Dfoo=bar won't go as far
as a program that is more well rounded in confusion.
Many ANSI C compilers dislike the following code, and so do we:
#define d define
#d foo <-- don't expect this to turn into #define foo
When declaring local or global variables, you should declare the type:
int this_is_ok;
this_is_not; <-- don't use such implicit type declaration
We suggest that you compile your entry with an ANSI C compiler. If you
must use non-ANSI C, such as K&R C, you must avoid areas that result in
compile/link errors for ANSI C compilers. For example, using gcc
local function declarations, such as:
int
main() {
void blah() { printf("blah\n"); }
blah();
}
are not allowed even though their existence seems tailor made for
this contest! But for now, since they are not in wide spread use
we cannot accept entries that use them.
If your entry uses functions that have a variable number of
arguments, be careful. Systems implement va_list as a wide variety
of ways. Because of this, a number of operations using va_list are
not portable and must not be used:
* assigning a non-va_list variable to/from a va_list variable
* casting a non-va_list variable into/from a va_list variable
* passing a va_list variable to a function expecting a non-va_list arg
* passing a non-va_list variable to a function expecting a va_list arg
* performing arithmetic on va_list variables
* using va_list as a structure or union
In particular, do not treat va_list variables as if they were a char **'s.
Avoid using <varargs.h>. Use <stdarg.h> instead.
If you use C preprocessor directives (#define, #if, #ifdef, ...),
the leading '#' must be the first non-whitespace character on a line.
While some broken C preprocessors do not allow whitespace before a
'#', most do.
The exit() function returns void. On some broken systems have exit()
return int. Your entry should assume that exit() returns a void.
Small programs are best when they are short, obscure and concise.
While such programs are not as complex as other winners, they do
serve a useful purpose. They are often the only program that people
attempt to completely understand. For this reason, we look for
programs that are compact, and are instructional.
One line programs should be short one line programs, say around 80
bytes long. Getting close to 160 bytes is a bit too long in our opinion.
We tend to dislike programs that:
* are very hardware specific
* are very OS version specific
(index/strchr differences are ok, but socket/streams specific
code is likely not to be)
* dump core or have compiler warnings
(it is ok only if you warn us in the 'remark' header item)
* won't compile or run under a POSIX P1003.1/P1003.2 like systems
* depend on a utility or application not normally found on most
most POSIX P1003.1/P1003.2 like systems
* abuse the build file to get around the size limit
* obfuscate by excessive use of ANSI tri-graphs
* are longer than they need to be
* are similar to previous winners
* are identical to previous losers :-)
* are identical to future losers (Windows 95) :-)
Unless you are cramped for space, or unless you are entering the
'best one liner' category, we suggest that you format your program
in a more creative way than simply forming excessively long lines.
The build file should not be used to try and get around the size
limit. It is one thing to make use of a several -D's to help out,
but it is quite another to use 200+ bytes of -D's in order to
try and squeeze the source under the size limit. You should feel
free to make use of the build file space, but you are better off
if you show some amount of restraint.
We want to get away from source that is simply a compact blob of
characters. To help, we give a break to source that contains
whitespace, and in certain cases ; { or } characters. While the
number of characters excluding whitespace (tab, space, newline),
and excluding any ; { or } followed immediately by either whitespace
or end of file, must be <= 1536, the total size may be less than 3217
bytes. This means that one may use "free of charge" up to 1681
bytes of whitespace, or ; { or } followed by either whitespace
or end of file. [[Q: What is special about 1681?]]
Please do not use things like gzip to get around the size limit.
Given two versions of the same program, one that is a compact blob
of code, and the other that is formatted more like a typical C
program, we tend to favor the second version. Of course, a third
version of the same program that is formatted in an interesting
and/or obfuscated way, would definitely win over the first two!
We suggest that you avoid trying for the 'smallest self-replicating'
source. The smallest, a zero byte entry, won in 1994.
We do not like writable strings. That is, we don't want stuff like:
char *T = "So many primes, so little time!";
...
T[14] = ';';
Please don't make use of this feature, even if your system allows it.
X client entries should be as portable as possible. Entries that
adapt to a wide collection of environments will be favored. Don't
depend on a particular type of display. For example, don't depend
on color or a given size. Don't require backing store.
X client entries should avoid using X related libraries and
software that is not in wide spread use. We ask that such X client
entries restrict themselves to only the low level Xlib and the
Athena widget set (libX11.a, libXaw.a, libXmu.a and libXt.a).
Don't use M*tif, Xv*ew, or OpenL*ok toolkits, since not everyone
has them. Avoid depending on a particular window manager. Not
everyone has X11r5, and some people are stuck back in X11r4 (or
earlier), so try to target X11r5 without requiring X11r5. Better
yet, try to make your entry run on all version 11 X Window Systems.
X client entries should not to depend on particular items on
.Xdefaults. If you must do so, be sure to note the required lines
in the ---remark--- section.
While we recognize that UN*X is not a universal operating system, the
contest does have a bias towards such systems. In an effort to expand
the scope of the contest, we phrase our bias in terms of POSIX P1003.1
and P1003.2 standards. This will allow certain non-UN*X OS users to
submit entries. On the other hand, this is a guideline and not a rule.
We will not reject an entry based on some POSIX technicality.
When dealing with OS and application environments, we suggest that you
be reasonable with a nod towards vanilla UN*X-like systems. POSIX will
evolve but not as much as the contest, so avoid stuff like POSIX real
time, security, etc.
We like programs that:
* are as concise and small as they need to be
* do something at least quasi-interesting
* pass lint without complaint (not a requirement, but it is nice)
* are portable
* are unique or novel in their obfuscation style
* MAKE USE OF A NUMBER OF DIFFERENT TYPES OF OBFUSCATION <== HINT!!
* make us laugh and/or throw up :-) (humor helps!)
Some types of programs can't excel (tm) in some areas. Of course, your
program doesn't have to excel in all areas, but doing well in several
areas really does help.
You are better off explaining what your entry does in the
---remark--- section rather than leaving it obscure for the judges
as we might miss something and/or be too tired to notice.
We freely admit that interesting, creative or humorous comments in
the ---remark--- section help your chances of winning. If you had to
read so many twisted entries, you too would enjoy a good laugh or two.
We think the readers of the contest winners do as well. We do read
the ---remark--- section during the judging process, so it is worth
your while to write a remarkable ---remark--- section.
Be creative!
ABUSING THE RULES:
Legal abuse of the rules is somewhat encouraged. Legal rule abuse may
involve, but is not limited to, doing things that are technically
allowed by the rules and yet do not fit the spirit of what we
intended to be submitted.
Legal rule abuse is encouraged to help promote creativity. Rule
abuse entries, regardless of if they receive an award, result in
changes to the next year's rules and guidelines.
Legal abuse of the rules is NOT an invitation to violate the
rules. An entry that violates the rules in the opinion of the
judges, WILL be disqualified. RULE ABUSE CARRIES A CERTAIN LEVEL
OF RISK! If you have an entry that might otherwise be interesting,
you might want to submit two versions; one that does not abuse the
rules and one that does.
If you intend to abuse the rules, indicate so in the ---remark---
section. You must try to justify why you consider your rule abuse
to be allowed under the rules. That is, you must plead your case
as to why your entry is valid. Humor and/or creativity help plead
a case.
Abusing the entry format tends to annoy us more than amuse us.
We are often asked why the contest rules and guidelines seem too
strange or contain mistakes, flaws or grammatical errors.
One reason is that we sometimes make genuine mistakes. But in many
cases such problems, flaws or areas of confusion are deliberate.
Changes to rules and guidelines in response to rule abuses, are
done in a minimal fashion. Often we will deliberately leave
behind holes (or introduce new ones) so that future rule abuse may
continue.
At the risk of stating the obvious, this contest is a parity of the
software development process. The rules and guidelines are
only a small part of the overall contest. Even so, one may think
the contest rule and guideline process as a parody of the sometimes
tragic mismatch between what a customer (or marketing) wants and
what engineering delivers.
ENTRY FORMAT:
In order to help us process the many entries, we must request your
assistance by formatting your entries in a certain way. This format,
in addition, allows us to quickly separate information about the
author from the program itself. (see JUDGING PROCESS)
We have provided the program, mkentry, as an example of how to
format entries. You should be aware of the following warning that
is found in mkentry.c:
This program attempts to implement the IOCCC rules. Every
attempt has been made to make sure that this program produces
an entry that conforms to the contest rules. In all cases,
where this program differs from the contest rules, the
contest rules will be used. Be sure to check with the
contest rules before submitting an entry.
You are not required to use mkentry. It is convenient, however,
as it attempts to uuencode the needed files, and attempt to check
the entry against the size rules.
If you have any suggestions, comments, fixes or complaints about
the mkentry.c program, please send EMail to the judges. (see below)
The following is a sample entry (the | change bars are not part
of the example, don't add them to your entry!)
---entry---
rule: 2000 |
fix: y
title: chlejhse
entry: 0
date: Wed Feb 2 00:47:00 2000 |
host: Un*x v6, pdp11/45
2.9BSD, pdp11/70
---remark---
This is a not-very-obfuscated C program. It is likely not to win a
prize, because it doesn't have what it takes to win and because the
author plans to forget to send it in before the deadline! :-)
---author---
name: Landon Curt Noll
org: IOCCC Judging Group
addr: Toad Hall
PO Box 170608
San Francisco, California
94117-0608
USA
Earth
email: chongo@no_spam.fake.address
nobody@toad.com
url: http:///reality.sgi.com/chongo
anon: y
---author---
name: Leonid A. Broukhis
org: IOCCC Judging Group
addr: Toad Hall
PO Box 170608
San Francisco, California
94117-0608
USA
email: leob@no_spam.fake_org
url: http://www.mailcom.com/main.shtml
anon: n
---author---
name: Jeremy Horn
org: IOCCC Judging Group
addr: Toad Hall
PO Box 170608
San Francisco, California
94117-0608
USA
email: jhorn@no_spam.fake_edu
url: none
anon: n
---author---
name: Peter Seebach
org: IOCCC Judging Group
addr: Toad Hall
PO Box 170608
San Francisco, California
94117-0608
USA
email: seebs@no_spam.fake_com
url: none
anon: y
---info---
begin 444 info.file
M5&AI<R!F:6QE(&ES(&EN('1H92!P=6)L:6,@9&]M86EN+@H*:'1T<#HO+W)E
M86QI='DN<V=I+F-O;2]C:&]N9V\*:'1T<#HO+W=W=RYI;V-C8RYO<F<*"E1H
M870@=&AA="!I<RP@:7,N"E1H870@=&AA="!I<R!N;W0L"B`@("!I<R!N;W0@
M=&AA="!T:&%T(&YO="!I<RX*5&AA="!I<RP@=&AA="!T:&%T(&ES(&YO="P@
M:7,A"@H)"2TM(&-H;VYG;R`Q.3<T"@I);B`Q.3DW+"!W:&5R92!T:&5R92!W
M87,@;F\@8V]N=&5S="`Z+2@@9'5E('1O(%-R:7)A;2!D<F]P<&EN9R!O9F8@
M=&AE"F9A8V4@;V8@=&AE($5A<G1H("AA;GEO;F4@:VYO=R!W:&5R92!3<FER
M86T@4W)I;FEV87-A;B!W96YT/R`@268@=&\@<V5N9`I%36%I;"!T;R!Q=65S
M=&EO;G-`:6]C8V,N;W)G*2!A;F0@3&%R<GD@0F%S<V5L(&)E:6YG('5N86)L
M92!T;R!C;VYT:6YU90HH9'5E('1O(&AI<R!C=7)R96YT(%!H1"!W;W)K("XN
M+B!B97-T('=I<VAE<R!,87)R>2$I+"!O;F4@;6EG:'0@<V%Y.@H*"3(@:7,@
M=&AE(&=R96%T97-T(&]D9"!P<FEM92!B96-A=7-E(&ET(&ES('1H92!L96%S
M="!E=F5N('!R:6UE+@H*06YD(&9O<B`Q.3DX(&]N92!M:6=H="!S87DZ"@H)
M4V\@;6%N>2!P<FEM97,@+BXN('-O(&QI='1L92!T:6UE(0H*26X@,3DY,BP@
M;VYE('!E<G-O;B!T;VQD('5S('1H870@=&AE>2!A8W1U86QL>2!D96-O9&5D
M('1H:7,@9FEL92X@($EN"C$Y.3,@86YD(#$Y.30@82!F97<@;6]R92!D:60@
M=&AE('-A;64N("!);B`Q.3DU+"!A(&YU;6)E<B!O9B!P96]P;&4@9G)O;0I%
M87-T97)N($5U<F]P92!T;VQD('5S('1H870@=&AE>2!D96-O9&5D('1H:7,@
M9FEL92X@(%-E96US('1H97)E(&ES(&$*<VUA;&P@=75D96-O9&4@9W)O=7`@
M:6X@16%S=&5R;B!%=7)O<&4A("`Z+2D*"E=H>2!D;VXG="!Y;W4@=&5L;"!U
M<R!W:'D@>6]U(&1E8V]D960@=&AI<R!F:6QE(&)Y('-E;F1I;F<@14UA:6P@
M=&\Z"@H)<75E<W1I;VYS0&EO8V-C+F]R9PH*4&5R:&%P<R!Y;W4@;6EG:'0@
M<W5G9V5S="!A(&)E='1E<B!E>&%M<&QE(&9I;&4@86YD('!R;V=R86T@9F]R
M('1H:7,*<V%M<&QE(&5N=')Y/R`@268@>6]U(&1O('-E;F0@:7,@82!B971T
M97(@97AA;7!L92!F:6QE+"!B92!W87)N960@+BXN"G1H870@:70@8V%N;F]T
M(&)E(&-O;G-I9&5R960@87,@82!C;VYT97-T(&5N=')Y+B`@4V\@>6]U(&UI
M9VAT(&YO=`IW86YT('1O('-E;F0@:6X@>6]U<B!B97-T('=O<FL@+BXN('-A
M=F4@=&AA="!F;W(@=&AE(&-O;G1E<W0N("!/;B!T:&4@"F]T:&5R(&AA;F0@
M+BXN('EO=2!M:6=H="!W86YT('1O('-E;F0@=7,@>6]U<B!M;W-T(&AU;6]R
M;W5S('=O<FLN("`@.BTI"E5U96YC;V1E9"!C<F5D:70@=VEL;"!B92!G:79E
;;B!I9B!W92!P:6-K('EO=7(@97AA;7!L92X*
`
end
---build---
begin 444 build
K9V-C("UA;G-I('!R;V<N8R`M3R`M1%-)3$Q97T1%1DE.12`M;R!P<F]G"@``
`
end
---program---
begin 444 prog.c
M;6%I;B@I"GL*("`@("\J"B`@("`@*B!.;W0@=F5R>2!O8F9U<V-A=&5D(&)U
M="!T:&5N('=H870@9&ED('EO=2!E>'!E8W0@+BXN('1H:7,@:7,@:G5S=`H@
M("`@("H@82!P;&%C96AO;&1E<B!E>&%M<&QE+@H@("`@("HO"B`@("!P<FEN
M=&8H(E-O;65D87D@22!M:6=H="!W<FET92!A(&)E='1E<B!E>&%M<&QE+EQN
M(BD["B`@("!P<FEN=&8H(D]N('-E8V]N9"!T:&]G=6AT("XN+B!N86@A7&XB
M*3L*("`@('!R:6YT9B@B4V5N9"!U<R!A(&=O;V0@97AA;7!L92!B=70@8F4@
M=V%R;F5D+"!A;GD@97AA;7!L92!Y;W5<;B(I.PH@("`@<')I;G1F*")S96YD
M('5S('=I;&P@;F]T(&)E(&-O;G-I9&5R960@87,@86X@96YT<GD@9F]R('1H
M92!C;VYT97-T(5QN(BD["B`@("!P<FEN=&8H(E-O('EO=2!M:6=H="!N;W0@
M=V%N="!T;R!S96YD(&%N(&5X86UP;&4@;V8@>6]U<B!B97-T('=O<FM<;B(I
M.PH@("`@<')I;G1F*"(N+BX@<V%V92!T:&%T(&9O<B!T:&4@8V]N=&5S="X@
M($)U="!A(&=O;V0@:'5M;W)O=7,@<')O9R!M:6=H=%QN(BD["B`@("!P<FEN
M=&8H(F1O("XN+B!A;F0@=V4@=VEL;"!G:79E('EO=2!U=65N8V]D960@8W)E
M9&ET(&EN(')E='5R;BY<;B(I.PH@("`@+RH@14UA:6PZ('%U97-T:6]N<T!I
M;V-C8RYO<F<@*B\*(VEF("%D969I;F5D*%-)3$Q97T1%1DE.12D*("`@(&UA
F:6XH*3L*(V5N9&EF"B`@("!E>&ET*#(Q-S`Q("4@,3(W*3L*?0H`
`
end
---end---
Your entry's sections must be the same order as in the above example.
Typically the build file should assume that the source is prog.c
and will compile into prog. If an entry wins, we will rename
its source and binary to avoid filename collision. By tradition,
we use the name of the entry's title, followed by an optional
digit in case of name conflicts.
Please note that the title must match the following regexp:
^[a-zA-Z0-9_=][a-zA-Z0-9_=+-]*$
and must be 1 to 31 chars in length. Titles such as: |
foo.c
this_invalid_title_is_too_long !
/dev/null
are right out! :-)
Titles can be 31 chars long now, but please try to keep them short. |
Why 31? Because at lesst one of the judges likes Mersenne primes! |
It is suggested, but not required, that the title should incorporate
the author(s) username(s).
If the above entry somehow won the 'least likely to win' award,
we would use chonglab.c and chonglab.
If your entry depends on, or requires that your build, source
and/or binary files be a particular name, please say so in the
---remark--- section. If this case applies, it would be be helpful
if you did one of the following:
* Tell us how to change the filename(s) in your entry.
* Have the build file make copies of the files. For example:
cc prog.c -o special_name
or rm -f special_src.c
cp prog.c special_src.c
cc special_src.c -o special_name
or rm -f special_build
tail +4 build > special_build
sh < special_build
* Assume that we will use the entry title. Send us a version of
your build/program files that uses the name convention. You
should uuencode these files in ---info--- sections.
If your entry needs to modify its source, info or binary files,
please say so in the ---remark--- section. You should try to avoid
touching your original build, source and binary files. You should
arrange to make copies of the files you intend to modify. This
will allow people to re-generate your entry from scratch.
Remember that your entry may be built without a build file. We
typically incorporate the build lines into a Makefile. If the
build file must exist, say so in the ---remark--- section.
Typically the ---build--- command will contain a "cc" command.
It is also ok to use a "gcc" command (and gcc args). However keep
in mind that your entry should be compilable by any standard ANSI C
compiler and thus should not depend on a special gcc feature.
If your entry needs special info files, you should uuencode them
into ---info--- sections. In the case of multiple info files,
use multiple ---info--- sections. If no info files are needed,
then skip the ---info--- section.
Info files are intended to be input, or detailed information that
does not fit well into the ---remark--- section. For example, an
entry that implements a compiler might want to provide some sample
programs for the user to compile. An entry might want to include a
lengthy design document, that might not be appropriate for a
'hints' file.
Info files should be used only to supplement your entry. For
example, info files may provide sample input or detailed
information about your entry. Because they are supplemental,
the entry should not require them exist.
In some cases, your info files might be renamed to avoid name
conflicts. If info files should not be renamed for some reason,
say so in the ---remark--- section.
Info files must uudecode into the current directory. If they
absolutely must be renamed, or moved into a sub-directory, say
so in the ---remark--- section.
When submitting multiple entries, be sure that each entry has
a unique entry number from 0 to 7. Your first entry should
have entry number 0.
With the exception of the header, all text outside of the entry
format may be ignored. That is, don't place text outside of the
entry and expect us to see it. (Our decoding tools are not AI
progs!) If you need tell the judges something, put it in the
---remark--- section, or send a EMail to:
questions@ioccc.org (not the address for submitting entries) |
The date should be given with respect to UTC. (Some systems refer
to this as GMT or GMT0) The format of the date should be that as
returned by asctime() in the C locale. An example of such a string is:
Wed Feb 2 00:47:00 2000
This format is similar to the output of the date(1) command. The
string does not include the timezone name before the year. On many
systems, one of the following command will produce a similar string:
date -u "+%a %h %d %T 20%y" |
date -u | sed -e 's/... \(20[0-9][0-9]\)$/\1/'
sh -c 'TZ=UTC date | sed -e "s/... \(20[0-9][0-9]\)$/\1/"'
sh -c 'TZ=GMT date | sed -e "s/... \(20[0-9][0-9]\)$/\1/"'
sh -c 'TZ=GMT0 date | sed -e "s/... \(20[0-9][0-9]\)$/\1/"'
You are allowed to update/fix/revise your entry. To do so, set
the 'fix' line in the ---entry--- section to 'y' instead of 'n'.
Be sure that the resubmission uses the same title and entry number
as well, as these are used to determine which entry is to be
replaced.
JUDGING PROCESS:
Entries are judged by Leonid A. Broukhis, Jeremy Horn, Landon Curt Noll
and Peter Seebach.
Entries are unpacked into individual directories. The EMail message
is unpacked into individual files, each containing:
---entry--- section
all ---author--- sections
all ---info--- sections
---build--- section
---program--- section
any other text, including the EMail message headers
Prior to judging, the 'any other text' file is scanned to be sure
it does not contain useful information (or in case the entry was
malformed and did not unpack correctly). Information from the
---author--- sections and the title from the ---entry--- section
are not read until the judging process is complete, and then only
from entries that have won an award.
The above process helps keep us biased for/against any one particular
individual. We are usually kept in the dark as much as you are
until the final awards are given. We like the surprise of finding
out in the end, who won and where they were from.
We attempt to keep all entries anonymous, unless they win an award.
Because the main 'prize' of winning is being announced, we make all
attempts to send non-winners into oblivion. We remove all non-winning
files, and shred all related paper. By tradition, we do not even
reveal the number of entries that we received. (For the curious,
we do indicate the volume of paper consumed when presenting the IOCCC
winners at talks)
After the Usenix announcement, we attempt to send EMail to the
authors of the winning entries. One reason we do this is to give
the authors a chance to comment on the way we have presented their
entry. They are given the chance to correct mistakes and typos. We
often accept their suggestions/comments about our remarks as well.
This is done prior to posting the winners to the wide world.
Judging consists of a number of elimination rounds. During a round,
the collection of entries are divided into two roughly equal piles;
the pile that advances on to the next round, and the pile that does
not. We also re-examine the entries that were eliminated in the
previous round. Thus, an entry gets at least two readings.
A reading consists of a number of actions:
* reading the ---entry--- section
* reading the uudecoded ---build--- section
* reading the uudecoded ---program--- section
* reading the uudecoded ---info--- section(s), if any
* passing the source thru the C pre-processor
skipping over any #include files
* performing a number of C beautify/cleanup edits on the source
* passing the beautified source thru the C pre-processor
skipping over any #include files
In later rounds, other actions are performed:
* linting the source
* compiling/building the source
* running the program
* performing miscellaneous tests on the source and binary
Until we reduce the stack of entries down to about 25 entries, entries
are judged on an individual basis. An entry is set aside because it
does not, in our opinion, meet the standard established by the round.
When the number of entries thins to about 25 entries, we begin to form
award categories. Entries begin to compete with each other for awards.
An entry often will compete in several categories.
The actual award category list will vary depending on the types of entries
we receive. A typical category list might be:
* best small one line program
* best small program
* strangest/most creative source layout
* most useful obfuscated program
* best game that is obfuscated
* most creatively obfuscated program
* most deceptive C code
* best X client (see OUR LIKES AND DISLIKES)
* best abuse of ANSI C
* worst abuse of the rules
* <anything else so strange that it deserves an award>
We do not limit ourselves to this list. For example, a few entries are so
good/bad that they are declared winners at the start of the final round.
We will invent awards categories for them, if necessary.
In the final round process, we perform the difficult tasks of
reducing the remaining entries (typically about 25) down to 8 or 10
winners. Often we are confident that the entries that make it into
the final round are definitely better than the ones that do not
make it. The selection of the winners out of the final round, is
less clear cut.
Sometimes a final round entry os good enough to win, but is beat out
by a similar, but slightly better entry. For this reason, it is
sometimes worthwhile to re-enter an improved version of an entry
that failed to win in a previous year. This assumes, of course,
that the entry is worth improving in the first place!
More often than not, we select a small entry (usually one line), a
strange/creative layout entry, and an entry that abuses the contest
rules in some way.
In the end, we traditionally pick one entry as 'best'. Sometimes such
an entry simply far exceeds any of the other entries. More often, the
'best' is picked because it does well in a number of categories.
ANNOUNCEMENT OF WINNERS:
The first announcement, occurs at the main Usenix conference. By
tradition, this is done during the IOCCC BOF. Like in 1999, |
an announcement may take place on the web first in May 2000, just |
before the conference. |
Winning entries will be posted in June to the following groups: |
comp.lang.c comp.lang.c.moderated alt.sources
In addition, pointers to these postings are posted to the following
comp.sources.misc comp.windows.x comp.programming
misc.misc comp.std.c alt.folklore.computers
Winning entries will be deposited into the uunet archives. See
below for details.
Often, winning entries are published in selected magazines from around
the world. Winners have appeared in books ("The New Hackers Dictionary")
and on T-Shirts.
Last, but not least, winners receive international fame and flames! :-)
FOR MORE INFORMATION:
You may contact the judges by sending EMail to the following address:
questions@ioccc.org (not the address for submitting entries)
Questions and comments about the contest are welcome. Comments about
confusing rules and guidelines are also welcome.
The rules and the guidelines may (and often do) change from year to
year. You should be sure you have the current rules and guidelines
prior to submitting entries. To obtain them, send EMail to the address
above and use the subject 'send rules'.
Check out the IOCCC Web page:
http://www.ioccc.org
It has rules, guidelines and winners of previous contests (1984 to date).
As a last resort, previous winners may be obtained by sending EMail
to questions@ioccc.org. Please use the subject 'send YEAR winners',
where YEAR is a single 4 digit year or a year range (such as 1993-1994),
or the word 'all'.
Leonid A. Broukhis
Jeremy Horn
chongo <Landon Curt Noll> /\cc/\
Peter Seebach
+35
View File
@@ -0,0 +1,35 @@
#include<stdlib.h>
#include<Xlib.h>
#include<keysym.h>
#define b(b)XDraw##b(i,J,k,
#define l :q==
#define o if(
#define a for(
#define t(t)XSetForeground(i,k,t##Pixel(i,0));
#define i(i)o g>1&&*P==*#i){ g--; m[g-1]i##=m[g]; } else
#define n (W-r)
#define s (Z-u)
#define I n*Q-Q,(s+2)*S,Q*3,Q*3,360*A/F*64,360*e/F*64);
#define d E[X][Y]
#define e m[q]
int q,P,W,Z,X,Y,r,u; char E[U][U][T+1] ,D[T]; Window J; GC k; XEvent w;
Display*i; v(c,j ,K){ char*P=E[c][j],*X,g=0; double A=0,F=0,m[T]; a; K<U&&*
P; ){ m[g]=strtod(P ,&X); a q=-1; ++q <g; F+=*P==64? e:0,A=*P==33 ? e>A
? e:A :0); o isupper(*P)*isdigit(P[1])){ o v(*P-65 ,atoi(P+1) ,K+1))goto
i; a m[g++]=atof(D); P++&&isdigit(*P); ); } else o P-X){ g++; P=X; }
else{ i(=)i(+)i(-)i(*)i(/)o *P-32)goto i; P++; } } o !--g)return !sprintf(D,
"%10.2f",*m); i: a; A&&q--; XFillRectangle(i,J,k,(n+q)*Q+S,s*S+S-K,Q/2,K))K=Q*
e/A; a; q--&&F; A+=e){ o q%2)t(White)XFillArc(i,J,k,I t(Black)b(Arc)I}
return !!strcpy(D ,E[c][j]); } main(){ read(q,E,z); i=XOpenDisplay(0);
k=XCreateGC(i,J=RootWindow(i,W),Z,0); XSelectInput(i ,J=XCreateSimpleWindow(i,
J,P,q,M ,H ,r,u ,WhitePixel(i,X)) ,ButtonPressMask|KeyPressMask|ExposureMask);
a XMapWindow(i,J); ; b(String)S ,S,d ,P=strlen(d))){ XNextEvent(i ,&w);
XLookupString(&w.xkey,D ,1,&q,0); q & 96&&q<128 ? d[P++]=q l C ? Y-- l
L ? Y++ l V ? X++ l _ ? d[--P]=0 l O&&X ? X--:P; o w.type==ButtonPress){
X=r +(w.xbutton.x-S)/ Q; Y=u+w.xbutton.y/S-1; } X%=26; a X>r+p ? r++
:X; X<r; r--); Y%=U; o Y<1)Y=1; a; q== R; exit(write(1 ,E,z))); a Y>u+G
? u++ :u; Y<=u; u--); XClearWindow(i,J); a Z=u+1; sprintf(D ,"%3d" ,Z)&&
Z<=u+G; Z++){ b(String)0,(s+2)*S-B,D,3); a W=r; W<=r+p; b(String)n*Q+S+N,S*
2-B,D,1),W++){ b(Rectangle)n*Q+S,s*S+S,Q,S); v(W,Z,0); b(String)n*Q+S+N,(s+2)*
S-B,D ,strlen(D)); *D=65+W; } } b(Rectangle)(X-r) *Q+S+1,(Y-u) *S+S+1,Q-2,S-2);
} }
+373
View File
@@ -0,0 +1,373 @@
Best of Show:
Jari Arkko
Kauppalantie 25A7,
02700 Kauniainen,
Finland
http://www.arkko.com
Jyrki Holopainen
Forsellesintie 1-3A10,
02700 Kauniainen,
Finland
http://personal.eunet.fi/pp/halo/
Judges' Comments:
To build: (You will need X11 header files and libraries installed to
build this program)
make jarijyrki
To run: (You will need a system capable of displaying the results of
X Window programs)
./jarijyrki < sheet1.info > myedits.info
This entry is one of those that makes you wonder why some commercial
software needs tens to hundreds of megabytes to install! This entry
does not simply do the basics, it includes graphing features. All this
program needs now is a flight simulator!
Selected Author's Comments:
1. OVERVIEW
This program is an X-Windows based spreadsheet program.
The main functions it supports are:
* Text cells
* Numeric cells
* Arithmetic operations: + - * /
* Pie charts
* Histograms
* Cell editing
* Formula line
* Dynamic recalculation
* Error detection
* Recursion detection
* Movement within the spreadsheet with cursor keys
* Movement within the spreadsheet with mouse
* Scrolling
* Loading and saving spreadsheets
* Visual style configuration
2. USAGE INSTRUCTIONS
2.1. Quick Guide
Starting: ./jarijyrki < sheet1.info > myedits.info
Stopping: Esc
Movement: Click mouse or cursor keys
Editing: Currently selected cell is always in edit state.
Press any key to add a character at the end of the
formula; press BackSpace to delete the last one.
Formulas: 123.45
A1 A2 +
B1 B2 -
C1 C2 *
D1 D2 /
Pie charts: A1 A2 A3 ... An @
Histograms: A1 A2 A3 ... An !
2.2. Starting and Loading Spreadsheets
To start the spreadsheet program with an existing
spreadsheet, use the following command line:
./jarijyrki < sheet1.info
The file sheet1.info has been provided as an example.
This file contains a set of financial numbers and two
graphical entities - a pie chart and a histogram - based
on them. We recommend starting the use of the program
from this file, as a way to study and learn the formula
language supported by the program.
To start the program with an empty sheet, use
./jarijyrki < /dev/null
[Alternatively, /dev/zero could be used but that may not exist
on all systems.]
2.3. Exiting and Saving Spreadsheets
Normally the user obviously wants to edit the spreadsheet.
After the spreadsheet program finishes, it outputs the
edited spreadsheet to the standard output. Hence, when
the spreadsheet window has come up, you've made your changes,
and you press the Esc key the program finishes. To save
the results in a file, the following typical command line
would be used:
./jarijyrki < sheet1.info > myedits.info
2.4. Visual Overview
On top of the window the Formula Area shows the formula (or text)
of the currently selected cell. The program starts with A1 as
being the current cell. Below the Formula Area is the Column
Letters Area: A, B, and so on. Correspondingly, on the left
side of the window is the Row Numbers Area: 1, 2, and so on.
The rest of the window is dedicated to the actual spreadsheet
cells.
The example spreadsheet, sheet1.info, provided with this
program contains two sets of numbers in the visible area
of the spreadsheet. The top set of numbers forms the
product-by-product turnover breakdown of an imaginary
company. Below it is the yearly development of the
company profits. On the top right corner is a pie chart
showing the turnover breakdown in graphical form, and
on the bottom right corner is a histogram showing the
yearly development. If you scroll the window you can
see additional data from the spreadsheet.
2.5. Movement and Scrolling
Use cursor keys to move left, right, up, and down among the cells.
[Note that it is not possible to move around the formula; the
formula can only be edited from its end by adding or removing
characters.] You may also click the mouse on a cell to cause it
to be activated as the current one.
Going beyond the borders of the window results in scrolling
the current view. It is not possible to go up from first row
or left from the first column; but it is possible to wrap back
to start from the last row and last column.
2.6. Formula
The spreadsheet formulas operate on a stack. Operands of an
operation (e.g. plus) are first pushed to the stack and then
the operation is performed. If a formula on a cell produces
*exactly* one result then that is shown in the cell. Otherwise,
the formula is interpreted as a string and shown as it is.
An example of a simple formula, simply specifying a number
is
123.50
Another simple formula refers to a cell:
A1
This particular example formula referred to the first cell of
the first row in the spreadsheet. Arithmetic operations require
both arguments:
A1 A2 +
B1 B2 *
C1 C2 -
D1 D2 /
More complex formulae can be constructed by combining these
simple ones:
A1 A2 + 2 *
This example calculated the sum of the cells A1 and A2, and then
multiplied the result by two.
The currently selected cell is always in a state where it can
be edited. Press any key to add a character at the end of the
formula; press BackSpace to delete the last one. Any resulting
recalculations are immediately visible. [Note how much nicer
this feature is as you get used to it, compared to the behaviour
of certain commercial spreadsheet programs.]
2.7. Graphical Formulas
The program supports two types of graphical representations of the
data in the cells: pie charts and histograms. The pie chart can
consist of any number of slices, and is constructed by putting
the pie amounts in stack and using the @ operator. The program
automatically computes the relative size of the slices.
A1 A2 A3 A4 @
This example would draw a pie slice of four cells, A1 to A4.
The pie formula is shown above the pie for reference.
The histograms are drawn in a similar manner, by using the !
operator:
A1 A2 A3 A3 !
2.8. Errors in Formulas
The program detects recursive reference attempts, references
cells not containing a numerical value, attempts to define
formulas with zero, two, or more results remaining in the stack,
and syntax errors of formulas. Note that typically as the user
types in a formula, it toggles between valid and invalid forms
dynamically as all single character changes are immediately
taken in account. This is not dangerous, just complete the
formula and view the results.
Errors are signalled by showing the formula on a cell instead
of the numerical value supposedly returned by it.
Division by zero results in an IEEE Inf number.
2.9. Compilation Parameters and Configuration
This section explains the meaning and rationale for the
compile time parameters:
-DC=XK_Up
-DL=XK_Down
-DO=XK_Left
-DV=XK_Right
-DR=XK_Escape
-D_=XK_BackSpace
These definitions can be used to change the user interface
of the program with respect to special keys. The four first
ones define the movement operations and the latter two ones
define the program termination and character deletion keys.
Typical modifications to these parameters include changing
character deletion to the key the user is most familiar with,
which could also be XK_Delete. XK_Escape might be better
in some cases as one of the function keys. Likewise for the
cursor keys.
-DU=40
This parameter defines the maximum dimensions of the stored
and handled spreadsheet (but see section 4.4 for a warning
about changing this without thinking about the consequences!).
-DT=98
This parameter defines the maximum length of a formula in one
cell. Note the warning in 4.4.
-Dz="(T+1)*U*U"
Defines the number of bytes in a spreadsheet file. The number is
automatically adjusted when the spreadsheet size parameters are
changed. Note the warning in 4.4.
-DQ=80
-DS=20
These two parameters define the visual dimensions of a cell.
Changing these may be necessary on your system if the default
font sizes differ from those in the systems we've tested the
program with. S also defines the size of the left (x1) and top
margins (x2).
-DN=10
This is the x-indentation of text inside a cell. Changing
this may be necessary to suit other font sizes and
different X environments.
-DB=5
This is the y-indentation of text inside a cell. Changing
this may be necessary to suit other font sizes and
different X environments.
-DG=23
This parameter is the number of cell rows visible at one
time.
-Dp=7
This parameter is one smaller than the number of cells columns
visible at one time.
-DM="((p+1)*Q)+S"
-DH="(G*S)+S+S"
These parameters are the window x and y sizes of the spreadsheet
program window. With these definitions, they are automatically
reflecting the at-one-time-visible cell row/column amounts.
Hence, we recommend changing the G and p parameters if you want
to change the window size in normal cases. Experimentation with
M and H can be used to get other types of effect such as adding
a margin also at the bottom of the window.
3. IMPLEMENTATION
It's better to just read the code. But note the use of
stack in the implementation of @ and ! operators, and note
the use of *#i in one of the macros [can you see why?].
Extreme compression has been the key in writing this
program. With compression have come the use of ASCII code
numbers instead of character constants and so on. [This
particular obfuscation is not really a desirable one as
it is not completely portable. But it certainly was a
necessary one.]
What does or does not "i(=)" do and why?
4. WARNINGS AND CAVEATS
4.1. X11 Paths in Compilation
The given build file may have to be edited to insert correct
library and include file path names.
4.2. Font Sizes
We've tested the program with limited amount of X servers.
It is possible that other systems use default font sizes or
other parameters that cause the visual looks to be different
or perhaps even unusable; if this happens, changing compile-time
parameters explained in section 2.8 may help.
4.3. Screen Sizes
The size of the window as it comes up - a parameter as defined
in compile-time - has been set suitable for a small laptop screen.
Larger screens may benefit from setting these parameters higher.
Smaller screens require changing the parameters so that all of the
window becomes visible.
4.4. Spreadsheet Dimension Changes
The size of the read, manipulated, and stored spreadsheets is
defined by a compile time parameter. However, changing this
parameter is not entirely trivial. The following constraints
apply:
(a) Horizontal (alphabet) dimension handling will always be
A to Z regardless of the actual allocated memory area.
(b) Any change in the dimension parameter renders existing
spreadsheet files unsuitable.
4.5. ASCII Reliance
The software relies on running on ASCII-based code system.
Why? Because "32" is shorter than "' '".
4.6. Command Line Single Character Defines
The use of single character (e.g. G or p) for a -D option
may break certain systems, if those characters are used
in the included X header files in certain kinds of places.
If this happens, you may move the offending character to
a new name by exchanging it on the command line and in
the program with another character. Note that there are
*no* free characters in the program currently.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
+5
View File
@@ -0,0 +1,5 @@
P5
# CREATOR: The GIMP's PNM Filter Version 1.0
446 640
255
VWWYXWWXWVTVXXY\_acggedca^[WSTTVZ_`beghjkmnpprsvxy{}€€e�件痘囹剿昼�}wtokjiifdb`__^]]^^]\[ZZZXVTSRQRRTTTSROMKKLNNONNNMNNNLKIJJHFFGEFFEDDCCBA?====??ACFHHJLNNPRTUVYY[[\]]__`abadefffghiikmllklomnnpppqqrssttsrqqpqtsttsuvuutsvxxwwyywvz|yzyyyxxz||€~€€~~€ヤ㊧у�月克書涛箔蘭楓葡詞試詩麹麹諮書錘諮詩試給滑活�о~}|z{xwvtuuuvwwuuwvvtstrrqqqppponolljihhihegihhgihhgggihhhgghjhhhgfffccb_\\ZXXVRQNKHFCA?><;:9888777776666776666666767889;@DEHMOQTWSPMKLOSXYXYZYUWWVTWWX[^`cddffca_^\XSTTVW_aceeijkmlopqsuwyz~≠ф�藷履撼尸武奄~xvqmjihgc``__^^_^^]]\[[YYXUUTSSQQPOMLJHGFGGIHIIJKLMNMKIIHGGHHGFFFFEEEEDCA@ABBCEFHHIKLOPPSUUWXY\\\^]__aab`defghijkklnmmllonnpqqpqrstsuvutsssttuvvvvvwwvuvtuuxxyyy{z{{zy{{zz|}€~~÷×~=÷ц炎旧轟藷駐舶末粕柏刻瑞随酎試瑞草緒錘麹視糾演援��{yz{xuuuttsuvuvvutvtuttttqqrrpqoomlliljlighiijihfgefedddec`a`^]]ZZZY[YXUTRPNLKIHFDB?=<:998777776667666666666666666777789<AEGHMOOQVVRNKLOPYYXZYWTVWWTVZZ[^acdcdecb`_^ZUSTUW^aacegijmnnqqsvvy~€ュ�鵠李棧沱囑総�zwrmjjghfb_`^_``_^]][[\ZYXUTROMKKJHGGEBAABCDDEGHKLLLMLLLKKJIIGHIIIHGGHHGGFFFGGHIHIJKMPRPSSVXYZYZ]^^_a`bdaghghhjikkkmlmlnopnnpqorqsssstuurrsrssvvyywwvvvutvvxzyz{}{||{{}~~}~~~}~}~}€<х演葛去刻酎瀦迄�部駐灯涛涛草崇随血詞結克給渇��a~|yywuvtstttuwxwvusstssstursrqrsqoonljliijhhfgfeddcaa^^_\]\\[WVSROMLLMKIIHEDCCBA@?>=;::987777777776666666666556667<977888;AEHIMMNQTVTPLKNPYZXYZWUVXWVW[\[^`dcbcdda__^[USVUU[_befghiklmpqsvwz}€ユ㈱諸�棔�椢俣号+upmihgggdba____]]][YYXYVSNLLHFEEDBA@?=<=>@BCEFILMMMNNOONLKKKIJKLMKJJJJLKKKKKKJLJILMNORRTUUVWXY\]]``aacfdghhijjjijjkmmmnonooprqtsttvttsurstrttuwwwvwwvwwwxxxyy{}}~~}}~|}}~}}~~~>e演焔血詞瑞枢又楓粕崇藍覧藍蕪涛衷渚訣結牛結���≠~{zzyvxuvwvxwvxvvuutstssqrtssrsrpnnmjhggfdcc`a``]^]\]\ZYZZYZVTOKGCAAA@@@?@?@B@>???>=;:99887666777666666566666666667:878:8;@DHJMNNQTUWQMMMNYZYZZXVUYYXW[^^_`cdbbdddaa_\VTUVVZ_bdeghhklnrquyzy}€d㊨賜葺屎撩囗鱒�}wrmkihheedcb^^^^\ZYXVVTPLIFEC@??=<<=<<=>>ACFHLMMNMNOOPPOMMMLMMMMLMMMMNPOOPOMLKKKLNNNOSSRTTTUVVZ]]^_abefdfghjjgihijijjnmnopqqqsssstututtrsssttuvtuuuuuvuvvvxwxz||}}||}|}}€~~~~~}~€�g�訣旧渚誌髄酎髄草走剿沫覧葡綜渚結穴��㊥у��€=~zyyyyyyywxwxxwvxvusttuuqrsqpqnmmjjfdbb_^^]]\^]\\\\[Z[YZXYXVTQJEA=;:::;;<==?@A@@?@>=<::9977667666666565666565555555667778:>EIKNMMNSVXRNLLNYZYYZYXWYZZZ\___`bdcceddbba^WTUVWZ]`efhhiklnrruwwz{~~€ф燕数吏圀尹剳相�ysoljihgfdaa__^]ZYXUTRPLHEA@@?>=<<=>@@BCEHJKMOOOPOPRSQQRPOONMNONMMNNOOQQPQONLLLLLMNOQRTSTTUWVTYZ^]_`bbdbefihgghhiikjkmmnooppqttrututuussrsttsttuuuuuuvvvvwxwxy||z|}~€€~~€€~~|{{~~<>�焔詩訣結試書諮註飼侭劍�欄糟結糾給���モ€dモ≠×||{xzzyxwwvwwxwwwurqqqomlljgfeaa``]^^_\\\[[\\\\\[[ZZYYXYZZXVQJD@;999:;;<>?@AAAAAAA?=;::987666666666666555565555566666778:>EIMNOMNPTVTPNMOVYZY\[\Z[]]]]^^`abdcbdedca`^YTUUVY^`cfgghjlmpqstuy{|€c�諮髄曝屎屁�初【tqmiihffda^_^[[ZYVTRPLHECBABCA@AABDFHIKKNPQRRQQRQQQTSSRPRQPOOONNNNNNNQQQOMLLKLKLNOQRPTRSUUUUTUWZ^_`__ab`ddeegifikjjllooooopqrrrrrsuutsrssstvutuuuvwxwvxyyxxzz|}}}~€€~~~~}}z|~€bнg㊧轄豪級褐轟月試刻当��嵐綜滑滑炎級��=€÷a�{zxywyyxvwwvvtssrpplkgfdca_\ZYVSSTVWZ[\[]\YYZZZ[]]]\[[[[\]^\ZVMEA<989::<=>@ABCCBBBA@><;9987666666666666666556665666666778:=DKOPPOOPZVTRNNMVZ[Z[]^\\^^\\]^_aacdcddccb_^ZUTTTV]aabghiklmopqsvvwz|~d�試当囿沺棡�桁{vsokhheea^][[XZYZWVTRLHGGGGHGGFGFGILPRQQRTTUUTSTRRRSRSRRRRRQOOMNMMNNPPQPMLKJIIJLMOPPQRRRQTTUXWZYY]_a^__]``__`ceikjklmpnoqprqoqsssssssusuuuuxwvwxwwuwutwxz{xz{|{}}}~€п€€~|}~~÷a~≦��糾�炎給滑括去樗末部綜麹轟給演穴演�≠�~}}}}||xvvuututsrqpoljhfdaa^ZXVTQOLJHGGHJLMSWYZ[\[Y]^]^^aaaa```_^`^ZWMF@;989::;=@A@BDCDCBA?>=;:988866666666666666665556666666788:>EJQPQONOSVVROMNTXZZ[^_\]^^]]^__acddcddcdba`\VTTUUZ_`ddhijkjmnnoptvyzу㈲告履擅」」」�恂紙~vqolhgfc`]\\\ZZ[[ZXWVQPMLNOPONMLKLORTUUUUVVVUTTSSSSTRRRRSRQPPNMLLMMMMOLLLKJIIHJKKLNNNOOPQTUVXV[[WTVY[^b`adcddbbbeiimmooonoqroqrqsttvtutvvtuuwwywwyxxwuxyz{yzyz{}€€€}~÷€}}~€~~~€÷≦演炎滑滑給渇窮щ諮荘酎白髄曙血穴級�怨ャc€}{zzxxutsrrplikjgdca_\\ZWUQQMJIHEA@?><<<<>CFNV[\^b`^ababbbeba`ca``__[WOHB<9899;;=?ABCEEDCBA@><;:989<766666565666666656665656667779=CJPRQPOOQUVUPMNRY][[^a_]^^^^`aa_addbeedcdaa^XUUUUY^bdcgikmmnnnopuxzxャ�去副泪・・、「攪劫}sonkigeeb_]]]]\]\\[ZXXUSSUUWURPQOPRUWVVVWVVVUTTSTSSSQRQQRQPPOONKKKLLKKLJKJIHGFGGIJMMLMNOQSRTSRQRTWYYY[]_^ceegggffddhjlkkkmmnopnorstuusrttuuvwwxxwwwwvvywxwy{yyz{|}~~|z~€~||~~€≠g�血潔糾糾���去署錐髄随暑焔渇��№ム~}zxxqronllhfeb_]\ZWTSQPLLJGEBA?=<;:988777779>DNW^^`bb``abbccb`_`````_^[XQIC>:::9:<>@ABDEFDCBB@>=;:988:766666676666666666666666666779<CJRSSRPNOTTTQNMR]`^]___]^^__bcb``feddfedfcc`ZUUUVY^bdfhiloooprssvyzz|e焔雌圉」ヲヲ・、椈糸}tpnmlihhfdbb`_````^]\ZZYYZZZWUTSQRRUVWVVUVVUVVUTTTRTQRPPQQPNONNLKIIJJJLKLJJJHGFHJIJJLOQRSTTQOQQSRSTVVUTVXZaadgghhigdflonpqqqqrqqrqruvusuutvwvuvywvuvwvxuwwxyzxxyyyz{{z|{}~~}€€€��褐曙穴訣克括€≦㊥�緒血試結�㊥℡�{xvspnkhfca^]YWVSQOLHFDCB@@>=;::988777766666678=DNW]_`dc^`aababbaaab`_``^ZYSJC>;:9:;<>@ABDECDCBA@><;:9887766666666666666666666666666779<CJQUUTQOQSVVSNMOVZ^\__^\\_^^_ab`_cbcefgfffdc]XVUVV]acfhilnoppqrtuuy{z|}<㍾据棧」・「椈昼кurpkjkhggeddbabb`a`Line truncated
+1273
View File
File diff suppressed because it is too large. Load diff
+3
View File
@@ -0,0 +1,3 @@
#include <stdio.h>
#include <math.h>
double l;main(_,o,O){return putchar((_--+22&&_+44&&main(_,-43,_),_&&o)?(main(-43,++o,O),((l=(o+21)/sqrt(3-O*22-O*O),l*l<4&&(fabs(((time(0)-607728)%2551443)/405859.-4.7+acos(l/2))<1.57))[" #"])):10);}
+31
View File
@@ -0,0 +1,31 @@
Best Small Program:
NATORI Shin
Univ. of Tokyo
Rigakubu 7-goukan 311
Hongou 7-3-1, Bunkyou-ku, Tokyo
Japan
Judges' Comments:
To build:
make natori
To run:
./natori
Here is a nice compact program that changes with the phase of the moon.
Can you figure out how it does it?
Selected Author's Comments:
This program outputs a rough image of the moon in its current phase.
The main obfuscation of this entry is its complicated double recursion
(without any loop or conditional statement).
People living in the southern hemisphere may want to change acos(l/2)
into acos(-l/2).
+49
View File
@@ -0,0 +1,49 @@
#define BeginProgram void main(int argc, char *argv[])
#define CloseBrace }
#define CommandLineArgument -1
#define Declare int i,j,n,Flag=1;
#define EndOfProgram return;
#define False 0;
#define ForLoop ;for
#define GetCommandLineArgument n=atoi(argv[1]);
#define i F1ag
#define If if
#define Increment ++
#define Is ==
#define LessThan *(c&64)*
#define LessThanOrEqualTo !=
#define Modulo %
#define OpenBrace {
#define PossibleFactor j
#define PossiblePrime i
#define Possib1ePrime (c=getchar())
#define PrimeNumber (c^(!i*n%64));
#define Print putchar
#define SetTo =
#define SmallestPrime 2
#define True 1
#define Variables char c;
#define Zero i%j
BeginProgram
OpenBrace
Declare Variables
GetCommandLineArgument
ForLoop (PossiblePrime SetTo SmallestPrime ;
Possib1ePrime LessThanOrEqualTo CommandLineArgument ;
Increment PossiblePrime)
OpenBrace
F1ag SetTo True
ForLoop (PossibleFactor SetTo SmallestPrime ;
PossibleFactor LessThan PossiblePrime ;
Increment PossibleFactor)
If (PossiblePrime Modulo PossibleFactor Is Zero)
F1ag SetTo False
If (Flag Is True)
Print PrimeNumber
CloseBrace
EndOfProgram
CloseBrace
+75
View File
@@ -0,0 +1,75 @@
Best Abuse of CPP:
Raymond Cheong
[address subject to change]
MD, USA
Judges' Comments:
To build:
make primenum
To run:
./primenum n (where n is an integer)
Don't read the author comments until you're ready for the spoiler.
Just stop and read the program; it won't take long. Once you've figured
out what it does, run it. It may surprise you.
This entry won, not because the obfuscation is impenetrable, but because
it successfully fooled half of the judges, including me.
Selected Author's Comments:
Description
===========
For 15 years, IOCCC winners have obfuscated programs using esoteric,
difficult-to-interpret, confusing algorithms. This entry finally bucks
that trend and obfuscates in the most "obvious" way possible: by
painstakenly describing the algorithm in clear pseudocode. Even novice
programmers will recognize that the program should find and print prime
numbers up to a given number (as specified on the command line).
But novice programmers especially know that mistakes are often made in
translating pseudocode to real code, often resulting in programs with
unexpected and confusing output. Clearly, the program contains several
syntax "mistakes" (e.g. LessThanOrEqualTo) and blatant "errors" (e.g.
Zero). This program clearly requires "debugging."
As a result of these "bugs", the program does not primes at all.
Instead, the program reads input from stdin and returns garbled text on
stdout. Fortunately, you can recover the original message simply by
running the program a second time. Try:
./primenum n < textfile | ./primenum n > textfile2
diff textfile textfile2
where n is the same number (modulo 64). So, the prime number generator
is actually a simple text encoder/decoder! Of course, don't forget that
argument, otherwise the "bugs" in the program will cause it to crash!
Features
========
- The program attempts to mislead the reader into thinking that it
generates prime numbers. It does this by
o describing a correct algorithm in pseudocode,
o using partially correct conversion of pseudocode to real code,
o using suggestive variable names, and
o using a suggestive program name.
- The program demonstrates a novel method of abusing the C preprocessor.
- How the filter algorithm works is left as an exercise to the reader.
- OK, so running it through the preprocessor strips away the prime
number front. But ye be warned: not a11 variab1es1es are identica1 :-)
- Other features include
o useless variables
o useless if
o a for loop that's used as an if statement
o dependence on the high bit being 0
- Try also
echo THIS MESSAGE IS IN ALL CAPS | primenum 32
+56
View File
@@ -0,0 +1,56 @@
# include <X11/Xlib.h>
# include <math.h>
# include <time.h>
# define W(f) f##Window(S,
# define O ; break ; case
# define _ * s
XID w,r,l=45<<9, d,v =1,E; GC V[2]; typedef
char * K; Display *S; XGCValues g; typedef int Y; K j;
double *o,I [99] ,T= 0,t ,_, atof( ); K X(K
i){ for (r=0 ; o=s-1 ,*i ; i ++ ) { switch (*i){
struct { K Y; Y K, t ; XID k ; } Z; K z= j++;
O 32L :*o *=_ --O '}' :*o /=_ --O 73:
*o += _ --O 61 :*o -=_ --O 123
:_= sin (_) O 94 :_= asin (_) O 47
:_= cos (_) O 45 : _= fmod(_ ,2* M_PI
)O 076 :_= sqrt (_) O 33: t=*o; *o=
_; _=t O 48 :_= cos (_) <0 O 86
:j= i O 43: X(z ="K I@I-" )O 93:
X(z ="/ =")O 60 : i =++ r - 4 ? j-1 :i O 79
:XDrawArc(S, d,V [(Y )_] ,(Y ) ( 399 +14 _ [
-2] ),( Y)( *"' "+14 _ [ -1]) ,2,2 ,0,l
) ; { Z. Y = i - 127 +r/ 3*2 ; Z.K= r%3+
r/3 +1; Z.t =0; Z.k=E ; XDrawText (S,d,*V,(Y
) ( 399 +14 *1[s-= strlen(z) ]),20,
&Z,1); } O 1:default:*i>90?I[*i-32]=_--:(*++s
=I[*i+(*i<73)*r]); } } } Y main
(Y G,K*A){ *A=
" 8<$ $li >d# -d8Z'Et#)wWP]WM C\\TI)#%!DcUAvz% H2&08M\\%YaHAW}4+%g ;|XN%W|l!_Kz+$UgBix41r=H7b@_:X 4zS EFo1i}= _D.%biA xF>)k*T(7&m \"G~ )TY *.^@$0.#yl< 66,/dI ;\\[![:- $u6 VnD X+ )TY-L38 :%\" )TY%8Z$ \"G|BfCb <Il8EC} \"b \037ST I{kT I-lT I!K ImT I!K =-`LQ { !L{ I[MQ { !M{ Ip@;P=I`L]!LQ ][M]!MQ ]lLL ;; IL;Q @]>m@{;M} ^`K !T PIIIV[;I{ k;I/@{ K!=k;!={LM=M} K!=jM!}T!=k@P=`+e+f+g+hK I-[K I-pEF=Q `FG=Q k@]aK]b;]cP]d@{ EIeK{ FIf;{ GIgP{ HIhVAE{ J{AE/ E0\117<";
w = DefaultScreen ( S =
XOpenDisplay(0)); W( XMap
)d =W(XCreateSimple ) W(
Root )w),0,0,800,80 ,0,0
,BlackPixel(S,w ))) ; g.
foreground=WhitePixel (S,w
); *(Y *) &g=6; for (; v
[V ]=XCreateGC( S,d ,4 +
v, &g),!--v; ); for ( E=
XLoadFont(S,"10x20" ),81
[I]=2; I[84]=( G>2?
atof(2[A]) -2451545
:time (0 )/ 3.75
/l - 10957.5)+ (T+=G
> 1? atof(A[1]):0); ){ t
=5e4 *6013; s=I; for(j=*A
;_++ =pow (t,(j[ 2]*'_'-
3028 +3[j])/t)*pow(6e-4+
1,j[ sizeof* X(++j) ]+95
**j- 3072.)-1; )j+=4; s-=
2; W (XClear)d); XFillArc
(S,d ,*V,385,25,0x1c,28,
0,l) ; X( j+4); XSync(S,
0) ; usleep(10000); } }
+333
View File
@@ -0,0 +1,333 @@
Astronomically Obfuscated:
James Bonfield
MRC Laboratory of Molcular Biology
Hills Road,
Cambridge
CB2 2QH
England
Judges' Comments:
To build:
make rince
To run (using an X windows server):
./rince
Also try:
make dmy2jd
./rince 0.001 `./dmy2jd 7.8 1 1610`
This program may have you going around in circles :-) Try running it
first before reading the Selected Author's Comments below.
The judges verified the correctness of output for recent dates
thru visual observation.
Selected Author's Comments:
How to use it
-------------
The simplest way to run it is with no arguments. Just type:
./rince
You will need to have access to X windows, although it doesn't require
desperately high resolution and there are no known limitations on colour
depth.
The display will change slowly over time, although it may take 10 minutes
or more to be visible. For those that cannot wait that long the program
has a built in time machine. Indeed the program knows the speed of light,
which is used to ensure that we see the "live" pictures. Simply specify
the fraction of a day to skip forward for each screen refresh. I suggest:
./rince 0.01
To display the output (still guessing?) for a given date, specify two
arguments. The first argument is as before and the second argument is a
Julian day number (given as a fractional component). Eg:
./rince 0 2441193.6
./rince 0.01 2441193.6
A Julian day is defined to be the number of days since January 1st in
the year -4712 (4713BC), starting at 12 noon GMT.[1] To aid conversion
from our time (GMT) to Julian day there is a supplementary program
named: dmy2jd.c. Run it with "day_float month year" as arguments. See
below for an example.
What it does
------------
This program plots the positions of the four Galilean moons of Jupiter,
as seen from earth. It doesn't correct for your location on earth, but I
assure you that the parallax is minimal!
The moons are labelled with roman numerals from I to IV. I being the
closest to the planet and IV being the furthest. They are:
I Io
II Europa
III Ganymede
IV Callisto
Amazingly, all it takes is a pair of binoculars to see the Galilean moons,
so the results can be experimentally checked. (Note that at present, the
best views of Jupiter are over the autumn/winter.)
The positions of the moons should be correct for binoculars, but possibly
not if you have a telescope or if you are in the southern hemisphere. In
that case I suggest that to get the correct image you look at the screen
from inside the monitor whilst standing on your head. In case of
confusion, please consult the following chart (*):
N
^
|
E <---+---> W
|
v
S
(*) Not to scale.
History
-------
Galileo discovered the moons in January 1610.
"http://www-isds.jpl.nasa.gov/cwo/cwo_54ga/html/cd/galileo.htm" states
the following:
By early 1610, Galileo had further improved his telescope by
double its power, so it now enlarged objects a thousand
times. He began looking at the stars and couldn't believe how
many more he could now see! The number seemed infinite. He was
beginning to realize the fixed stars weren't a flat distant
wall on a globe, but a three-dimensional expanse bigger than
anyone had ever thought!
Then, on January 7, about an hour after sunset, Jupiter rose
in the east, and Galileo happened to turn his powerful scope
on its bright disk. It wasn't the first time he had looked at
Jupiter, but before it was with one of his lesser-powered
telescopes. This time, though, he noticed three small but
bright stars near the planet, two to one side and one to the
other. He wondered at how bright the small stars were and how
they were arranged in what seemed like a straight line. The
next night he decided to look at Jupiter again, and to his
surprise, the stars had moved. But not in such a way as he
would expect. If Jupiter was moving as it normally should, the
stars would be east of Jupiter. But all three were to the
west! The next night was cloudy, but on January 10, Galileo
was able to observe the planet again. One of the stars was
gone, and the other two were now on the east side. As the
stars moved around Jupiter on each succeeding night, and were
finally joined by a fourth star, it dawned on Galileo that
what he had found were moons orbiting Jupiter! Almost at once
he realized that this was proof that not all objects orbited
the Earth. Here were four bodies that were orbiting
Jupiter. One argument against the sun-centered theory was, if
the Earth orbited the sun, wouldn't the moon get left behind?
Here he could see for himself that somehow, a planet could
orbit the sun, and not leave a moon behind!
Thus we can plot Galileo's discoveries using the following three plots:
./rince 0 `./dmy2jd 7.8 1 1610`
./rince 0 `./dmy2jd 8.8 1 1610`
./rince 0 `./dmy2jd 10.8 1 1610`
However we can go one better by seeing what Galileo would have seen if it
wasn't cloudy on the 9th. Try "./rince 0 `./dmy2jd 9.85 1 1610`" to see
what he was missing out on. I wonder what he'd have made of that!
Galileo discovered the fourth moon a few days later.
I've tried typing these dates in to two Java based Jovian moon plotters,
but both I tried had problems dealing with dates earlier than 1900. More
professional software, such as the SkyMap program [3] gets these values
correct and this compares well with the above description and with this
IOCCC entry.
The year 4713BC was chosen by Joseph Justus Scaliger in the 16th Century,
so clearly this program has a long history :-) A more complete description
of the origins of Julian Days can be found at:
http://aa.usno.navy.mil/AA/faq/docs/millennium.html
Assumptions
-----------
1. The ASCII character set is used.
2. That an enormous comet hasn't changed the course of Jupiter (or Earth!).
3. That the date has not been specified as the gap between the Julian
and Gregorian calendar.
4. That the DISPLAY environment variable is set and the X display can
opened. If this is not the case the program will crash.
5. There is a year 2000BC problem :-)
More specifically, the plots for dates that far back are too inaccurate
to be of realistic use. Comparisons against SkyMap Pro [3] show that
there is a good similarity (but not much more) up to about 500BC.
6. The code definitely is not portable - it will produce incorrect results
if run from the surface of Mars.
Obfuscations
------------
In addition to the normal obfuscations, I feel that the code contains
some less common tricks. Taken through the standard rounds listed in the
guidelines, the code attempts to pass these as follows:
1. Look at the original source
With luck, pure casual inspection should not reveal much except
that the program contains the X Windows logo (a big clue) and
contains a date. This date may give a clue to a few people that
this is an astronomical program.
Unfortunately I was stretched for space which meant that the
large string constant could not be split up using a "partA"
"partB" method which clearly limits the code layout. However the
space saved by using a single long string constant is more than
outweighed by ability to further obfuscate.
2. convert ANSI tri-graphs to ASCII
These are not used.
3. C pre-process the source ignoring #include lines
4. C pre-process the source ignoring #define and #include lines
This does a good job of expanding out the code, but it does not
clarify things greatly. The use of #defines has been restricted
primarily to a space-saving mechanism.
Additionally, the use of typedefs means that the types used are
still obscured unless further replacement edits are made.
5. Run it through a C beautifier.
GNU indent seems to do a reasonable job, provided that the
#defines are expanded first. This doesn't lay the algorithm
particularly bare though as most of the obfuscations are not
simple code layouts.
6. Examine the algorithm.
The algorithm operates on two levels. The main visible level is
by taking a large string and breaking this down into a series of
op-codes (which I have termed J-code). These are then executed.
To get to the real method of how it works, you need to decode
the op-code string (which deliberately contains as many ; { and
} symbols as possible), which will give you a reverse-polish
notation chunk of mathematics.
Sensible people amongst you will simply refer to the referenced
book :-)
7. Lint it.
I no longer have lint, although I do have access to Purify. I'm
happy to say that purify does not detect any memory errors or
memory leaks.
See below for compilation warnings.
8. Compile it.
I'm sorry to say that there are several warnings issued by the
compiler.
Firstly, the return type for X() is not specified, so it
defaults to int. Horror of all horrors - this function does not
return an integer type (it doesn't contain any specific
returns). The return value from X() is not accessed. The same
problem occurs in main - it does not return. However main never
exits unless there is a serious error.
The 6th argument of XDrawText (which should be XTextItem) is
passed as a compatible structure, but without casting. This is
to reduce code space. A more elegant solution is to remove the
"struct {...} Z" completely and use "XTextItem
f={i-127+r/3*2,r%3+r/3+1,0,E}" at the start of XDrawText
block. Although this is accepted by several compilers, it is not
strict ANSI due to the non-constant initialisers. A pity.
Note that I make use of usleep(). This is a POSIX call (it is
BSD), but it supported on many systems. It may be implemented
using select() or poll() if required, or as a final solution you
may change the usleep(10000) to sleep(1). To compile on systems
which do not have usleep, but do have select, the following may
suffice as an additional compiler argument:
-Dusleep={time_t v[2]={0,10000};select(0,0,0,0,v);}
Gcc complains about "unreachable code at beginning of switch
statement", although removing some of this code will prevent
the algorithm from working.
Gcc also suggests that I should be using extra parenthesis, but
I'm taking this as good comment :-)
In addition to the above, the program has the following useful(?)
obfuscations:
1. The algorithm requires many floating point numbers (about
50). These are encoded as ASCII.
2. The J-code algorithm has op-codes designed to be space
saving. They are all one byte, but many are also considered as
white-space by the rules. This algorithm forms part of the same
string that the floating point constants are embedded
within. What does the ";" command do in J-code?
3. The J-code language is both stack based and variable based. This
"uncleanliness" is not ideal from a computer science angle, but
when has cleanliness been considered as good in IOCCC? :-)
4. Association of unconnected data by implied function usage. Eg
use of strlen() and sizeof() simply to return useful numerical
values, using irrelevant arguments.
5. As we already have a dependency on ASCII this has been abused
further. Specifically some integer constants are specified as
ASCII and some ASCII constants are integers. This hides the true
meaning for the values.
6. Red herrings: there's a couple of pieces of code whose
appearance is just there to mislead the unfirm of mind.
I've only tried to include such examples in places where at
first glance the code appears to be executed.
References
----------
[1] Astronomical algorithms (1st ed): page 59
Jean Meeus. Published by Willmann-Bell Inc.
[2] Astronomical algorithms (1st ed): pages 285-299.
Jean Meeus. Published by Willmann-Bell Inc.
[3] Skymap Pro, by Chris Marriott
http://www.skymap.com/
+829
View File
@@ -0,0 +1,829 @@
#define A B.
#define C if(
#define D >>E&1
#define F return
#define G typedef
#define H printf( I(
#define J(E,K) for(E=K; E--; )
#define L(M) =N(O.M)+3*N(O.M&O.P),
G
int
Q;
G
unsigned
R;
G
struct
{
Q
N,
S,
P,
T,
U,
V;
}
W;
R
_;
R
N(
R
X)
{
R
Y=
2,
Z;
for
(;
Y
;
Y*=
Y)
{
Z=
-1
/-
~Y
;
X=
(X
/Y
&Z
)+
(X
&Z
)*
(Y
*_
-~-
_)
;
}
F
X;
}
W
S(
W
a)
{
W
B;
_=
1;
A
N=
N(
a.
S)
;
A
S=
N(
a.
N)
;
A
P=
N(
a.
P)
;
A
U=
-1
<<
30
;
A
V=
-a
.U
;
F
B;
}
Q
P(
Q
Y,
Q
b,
R
c)
{
Q
E=
Y+
(b
+8
)%
10
-5
+Y
/4
%2
&31
;
F
c
D||
Y/
4-
E/
4-
~-
(b
&2
)?
-1
:E
;
}
Q
T(
W
B,
Q
a,
Q
b)
{
Q
E=
P(
a,
b,
A
N)
;
F~
E?
A
S
D?
~P
(E
,b
,A
S|
A
N)
?128
|b
*32
|a
:-
1:
b*
32
|a
:E
;
}
Q
U(
W
B,
R
c,
Q
Y)
{
Q
E,
b;
J(
E,
32
)C
(A
N&
c)
D)
J(
b,
2<<
(A
P
D)
)C
T(
B,
E,
b)
>=
Y<<
7)
F
1;
F
0;
}
W
V(
W
B,
Q
Z)
{
R
E=
Z&
31
,b
=Z
/32
&3
,Y
=A
T=
P(
E,
b,
0)
,K
=1
<<
Y;
A
N|=
K;
A
P&=
~K
;
A
P|=
(A
P
D)
<<
Y;
_=
A
S
D&&
U(
B,
K,
1)
;
A
P|=
K&-
1<<
28
;
A
N&=
E=
~(
1<<
E)
;
A
P&=
E;
A
S&=
E;
F
Z>>
7?
V(
B,
b<<
5|
Y)
:B
;
}
W
d(
W
B,
Q
b)
;
R
e;
W
f(
W
B,
Q
E,
Q
b,
Q
g)
{
Q
h,
i=
0,
I,
j,
K,
k,
Z,
Y;
J(
h,
2<<
(A
P
D)
){
j=
T(
B,
E,
h)
;
C~
j&&
j>>
7!=
!~
g)
{
++
i;
C
A
U<=
A
V)
{
W
O;
O=
V(
B,
j)
;
K=
g<
0?
j:
g;
++
e;
I=
_?
f(
O,
O.
T,
b,
K)
.U
:(
Y=
b+
U(
O=
S(
O)
,-
1,
1)
)?
-(
d(
O,
~-
Y)
.U
):
(_
=0
,Z
L(
N)
k
L(
S)
(k
-Z
<<
24
)/
(k
+Z
)+
(short
)rand
()
);
C
I>=
A
U)
{
A
U=
I;
A
T=
K;
}
}
}
}
_=
i;
F
B;
}
W
d(
W
B,
Q
b)
{
Q
E=
32
,Y
=
~U
(B
,-
1,
1)
;
for
(;
E--
&&
A
U<=
A
V;
)C
A
N
D)
{
B=
f(
B,
E,
b,
Y)
;
}
F
B;
}
char
l[
4095
],
*O
=l
,*
b;
char
*I
(char
*X
){
Q
Z=
1,
W=
0,
E,
M=
0,
B;
b=
O;
for
(;
E
=
*X
++
;
){
E=
E%
65
%6
^2
;
M+=
B=
Z+
1+
E/
4;
W=
W<<
B^
E;
Z=
E<
2;
J(
E,
M/
7)
{
M%=
7;
W^=
(*
O++=
W>>
M)
<<
M;
}
}
*O
++=
0;
F
b;
}
Q
main
()
{
Q
K,
Y,
E,
m,
n,
o=
4,
g,
b,
Z;
W
B;
srand
(clock
()
);
A
S=
(A
N=
4095
)<<
20
;
A
P=
0;
for
(;
;
){
J(
K,
8)
{
J(
Y,
8)
{
E=
K*
4+
Y/
2;
H" } { }"
)+
(K
^Y
^1
)%
2*
2,
".xoXO"
[(
A
P
D)
*2
+(
A
S
D)
*2
+(
A
N
D)
])
;
}
H" } } } } } } "
),
-~
E)
;
}
J(
g,
1)
{
O=
l;
H"} } } } { } } } } { ; ; }"
)+
o/
2*
2)
;
e=
0;
C
o<
4)
B=
S(
B)
;
C!
U(
B,
-1
,0
))
{
H" } } { ; { ; } ; } } "
))
;
F
0;
}
H" { { ; { ; ; { ; ; { { } } ; ; { } } } ; ; { ; } } } { ; { ; ; { { ; } } "
)+
(o
&1
)*
13
,I
(" } { { } ; } "
)+
U(
B,
-1
,1
))
;
C
o&
4)
{
o&
1?
scanf
("%d"
,&
n)
:(
scanf
("%d%d"
,&
m,
&n
),
--
m)
;
Z=
A
N>>
m&
1?
T(
B,
m,
n)
:-
1;
C
g=
Z>>
7!=
U(
B,
-1
,1
))
{
H"{ ; { { } { } { ; } ; { "
))
;
}
}
else
{
A
U=
-(
A
V=
1<<
30
);
for
(b
=4
;
e<
65536
&&
b<
20
;
b++
){
Z=
(o
&1
?f
(B
,m
,b
,-
2)
:d
(B
,b
))
.T
;
}
o&
1?
H" } { } "
),
Z>>
5&
3^
3)
:H
" } { } } } { } "
),
32
-(
Z&
31
),
Z>>
5&
3^
3)
;
}
}
B=
V(
B,
Z)
;
g=
o;
C
_)
{
o|=
1;
m=
A
T;
}
else
{
o=
o/
2*
2^
4;
}
C
g<
4)
{
B=
S(
B)
;
}
}
}
+172
View File
@@ -0,0 +1,172 @@
Best game:
Arch D. Robison
1406 Country Lake Drive
Champaign IL 61821
USA
Judges' Comments:
To build:
make robison
To run:
./robison
The program plays almost always reasonably, but does not always detect
illegal moves. Try "9 1" as your first move, then "13 2". Also it
tends to think for quite a while in the beginning of a game. It is
also smart enough to give up by making a losing move at the end of
a game when its position is hopeless.
Unfortunately, due to the contest rules, we're unable to grant the
author a patent he applied for. :-)
Selected Author's Comments:
TITLE OF INVENTION
Highly Compressed Program for Playing Hygienic Checkers
FIELD OF INVENTION
The present invention generally relates to checkers.
BACKGROUND OF THE INVENTION
Within the field of checkers, the problem of finding a hygienic opponent
is difficult, as good opponents are peculiar to the tavern habitat of
cracker-barrels, pot-belly stoves, tobacco, and spittoons.
BRIEF SUMMARY OF THE INVENTION
The present invention plays checkers without spitting.
BRIEF DESCRIPTION OF SEVERAL VIEWS OF THE INVENTION
FIG. 1 shows a numbering of positions.
FIG. 2 shows a numbering of directions.
FIG. 3 shows a sample board.
FIG. 4 shows a method in accordance with the present invention.
DETAILED DESCRIPTION OF THE INVENTION
Operator plays Black (x); the program plays White (o). Said Black goes
first. On operators turn, said program requests a position and direction.
FIG. 1 shows the numbering of the squares. FIG. 2 shows the numbering of
directions. As per standard rules, if one or more jumps are possible, one
of the jumps must be taken in preference to other moves. Said operator
enters the numbers for the position and direction. If after jumping over a
piece, another jump is possible, and said piece did not become a king after
said jump, standard rules require that another jump be taken. In said case,
said program requests a direction only in which to continue jumping from the
present position. Kings are denoted by upper case. FIG 3. shows a sample
board. There is a black king (X) on square 30 and a red king (O) on square
2. The numbers on the right are the numbers of the rightmost square in each
row.
A player loses if they cannot make a legal move. Said loss is trivially
true if player loses all of his/her pieces. The present invention announces
said loser.
FIG. 4 shows a C program in accordance with the present invention. Control
flow is straightforward: control enters routine ``main'', executes a
plurality of statements, and exits via return statement. FIG. 4 presumes
that type int is 32 bits and short is 16 bits, which are essential to the
preferred embodiment of the invention. FIG. 4 also presumes that the host
computer uses ASCII encoding for characters. It should be obvious that
practitioners skilled in the art of C programming can remove said
limitations.
The disclosure here describes a particular embodiment of the present
invention, and other embodiments within the spirit of this disclosure
are possible, as well as consumption of spirits while playing.
CLAIMS
I claim, by letters patently absurd:
1. A method for playing checkers on a computer-based system, where said
method's source code fits into 1536 countable bytes of source code,
where a byte is countable if
(a) it is not whitespace and
(b) it is not a {, }, or ; immediately followed by whitespace.
2. The method of claim 1, further comprising a method of alpha-beta pruning
that exploits the zero-sum nature of the game to unify alpha
and beta cuts.
3. The method of claim 1, further comprising the step of formatting the
source code with short lines, in order to impress manager with
high productivity, when measured in lines of code.
4. The method of claim 3, further comprising the step for telling
skeptical manager that this is the well-known technique of
"linear programming".
5. The method of claim 1, where ~- and -~ replace the obvious arithmetic
operations.
6. The method of claim 1, further comprising a method where
(a) strings are encrypted in a manner suitable as C strings, and
(b) 7-bit ASCII characters with uniform distribution are maximally
packed subject to the restriction that
(c) each byte is not countable.
7. A method for a computer-based system that uses a single shared code
sequence to either sum a plurality of bits in an N-bit word or reverses
them, in lg(N) time, depending upon a parameter.
DRAWINGS
FIG 1.
+--+--+--+--+--+--+--+--+
|32| |31| |30| |29| |
+--+--+--+--+--+--+--+--+
| |28| |27| |26| |25|
+--+--+--+--+--+--+--+--+
|24| |23| |22| |21| |
+--+--+--+--+--+--+--+--+
| |20| |19| |18| |17|
+--+--+--+--+--+--+--+--+
|16| |15| |14| |13| |
+--+--+--+--+--+--+--+--+
| |12| |11| |10| | 9|
+--+--+--+--+--+--+--+--+
| 8| | 7| | 6| | 5| |
+--+--+--+--+--+--+--+--+
| | 4| | 3| | 2| | 1|
+--+--+--+--+--+--+--+--+
FIG. 2.
1 0
\ /
.
/ \
3 2
FIG. 3.
o o X . 29
o . . . 25
o . . o 21
. o . o 17
x . . . 13
. . x . 9
x x . . 5
x x O x 1
FIG. 4
[See attached listing.]
+218
View File
@@ -0,0 +1,218 @@
15th International Obfuscated C Code Contest Rules |
Copyright (c) Leonid A. Broukhis, Jeremy Horn, Landon Curt Noll and |
Peter Seebach, 2000. |
All Rights Reserved. Permission for personal, education or non-profit use is |
granted provided this this copyright and notice are included in its entirety |
and remains unaltered. All other uses must receive prior permission in |
writing from the contest judges. |
Obfuscate: tr.v. -cated, -cating, -cates. 1. a. To render obscure.
b. To darken. 2. To confuse: his emotions obfuscated his
judgment. [LLat. obfuscare, to darken : ob(intensive) +
Lat. fuscare, to darken < fuscus, dark.] -obfuscation n.
obfuscatory adj.
GOALS OF THE CONTEST:
* To write the most Obscure/Obfuscated C program under the rules below.
* To show the importance of programming style, in an ironic way.
* To stress C compilers with unusual code.
* To illustrate some of the subtleties of the C language.
* To provide a safe forum for poor C code. :-)
The 15th IOCCC contest window is: |
01-Feb-2000 00:00 UTC to 31-Mar-2000 23:59:59 UTC |
NOTE: Some of the changes from the 1998 rules are denoted by change bars. ---> |
However some changes such as 1998 to 2000 are not marked. |
RULES:
To help us with the volume of entries, we ask that you follow these rules:
1) Your entry must be a complete program.
2) Your entry must be <= 3217 bytes in length. The number of characters
excluding whitespace (tab, space, newline), and excluding any ; { or }
immediately followed by whitespace or end of file, must be <= 1536.
3) Your entry must be submitted in the following format:
---entry---
rule: 2000
fix: y or n (n => this is a new entry, y => this replaces an older entry)
title: title of entry (see comments below)
entry: Entry number from 0 to 7 inclusive (your 1st entry should by 0)
date: Date/time of submission in UTC (see comments below)
host: Machine(s) and OS(s) under which your entry was tested
Use tab indented lines if needed
---remark---
Place remarks about this entry in this section. It would be helpful if
you were to indent your remarks with 4 spaces, though it is not a
requirement. Also, if possible, try to avoid going beyond the 79th
column. Blank lines are permitted.
---author---
name: your name
org: School/Company/Organization
addr: postal address
use tab indented lines to continue
don't forget to include the country
email: EMail address from a well known site or registered domain.
If you give several forms, list them on separate tab indented lines.
url: http://your/home/page.html or say none if you don't have one
anon: y or n (y => remain anonymous, n => OK to publish this info)
---info---
If your program needs an info file, place a uuencoded copy of it in
this section. In the case of multiple info files, use multiple info
sections. If your entry does not need a info file, skip this section.
---build---
Place a uuencoded copy of the command(s) used to compile/build your program
in this section. It must uudecode into a file named 'build'. The resulting
file must be 255 bytes or less.
---program---
Place a uuencoded copy of your program in this section. It must uudecode
into a file named is 'prog.c'. The resulting file must follow rule #2.
---end---
Regarding the above format:
* The title must match the expression: |
^[a-zA-Z0-9_=][a-zA-Z0-9_=+-]*$ |
and must be 1 to 31 characters in length. |
It is suggested, but not required, that the title should
incorporate the author(s) username(s).
* The date in the ---entry--- section should be given with respect
to UTC. The format of the date should be as returned by asctime()
using the C locale. (see guidelines for more info)
* You may correct/revise a previously submitted entry by sending
it to the contest email address. Be sure to set 'fix' in the
---entry--- section to 'y'. The corrected entry must use the same
title and entry number as submission that is being corrected. Be
sure that you note the re-submission in the ---remark--- as well.
* With the exception of the header, all text outside of the above
format may be ignored by the judges. If you need to tell the judges
something, put it in the ---remark--- section, or send a separate
EMail message to the judges.
* Information from the ---author--- section will be published unless
'y' was given to the respective author's 'anon' line.
* To credit multiple authors, include an ---author--- section for
each author. Each should start with ---author--- line, and
should be found between the ---entry--- and ---build--- sections.
* The home page URL in the ---author--- section must be fully |
qualified or must be the word `none'. |
* The entry's remarks should include:
- note if this entry is a re-submission of a previous entry.
- what this program does
- how to run the program (sample args or input)
- special compile or execution instructions, if any
- special filename requirements (see rule 4 and 5)
- information about any ---info--- files
- why you think the program is obfuscated
- any other remarks (humorous or otherwise)
* Do not rot13 your entry's remarks. You may suggest that certain
portions of your remarks be rot13ed if your entry wins an award.
* Info files should be used only to supplement your entry. They
should not be required to exist.
* If your entry does not need an info file, skip the ---info---
section. If your entry needs multiple info files, use multiple
---info--- sections, one per info file. You should describe
each info file in the ---remark--- section.
* Your sections must in the same order as in the above template.
4) If your entry is selected as a winner, it will be modified as follows:
'build' is incorporated into a makefile, and 'build' is removed
'prog.c' is renamed to your entry's title, followed by an optional
digit, followed by '.c'
your entry is compiled into a file with the name of your entry's
title, possibly followed by a digit
If your entry requires that a build file exist, state so in your
entry's remark section. The makefile will be arranged to execute a
build shell script containing the 'build' information. The name of
this build shell script will be your entry's title, possibly followed
by a digit, followed by '.sh'.
If needed, your entry's remarks should indicate how your entry must
be changed in order to deal with the new filenames.
5) The build file, the source and the resulting executable should be
treated as read-only files. If your entry needs to modify these files,
it should make and modify a copy of the appropriate file. If this
occurs, state so in your entry's remarks.
6) The uudecoded ---program--- section must be able to be compiled
cleanly by an ANSI C compiler, or if there are any compile errors,
they must be documented in the ---remark--- section.
7) The program must be of original work. All programs must be in the
public domain. All copyrighted programs will be rejected.
8) Entries must be received prior to 31-Mar-2000 23:59:59 UTC. (UTC is
essentially equivalent to Greenwich Mean Time) EMail your entries to:
entry@ioccc.org
We request that your message use the subject 'ioccc entry'.
If possible, we request that you hold off on EMailing your entries
until 01-Feb-2000 00:00 UTC. Early entries will be accepted, however.
We will attempt to EMail a confirmation to the sender of any entry
received after 01-Feb-2000 00:00 UTC and before the close
of the contest.
9) Each person may submit up to 8 entries per contest year. Each entry
must be sent in a separate EMail letter.
10) Entries requiring human interaction to be built are not allowed.
11) Programs that require special privileges (setuid, setgid, super-user,
special owner or group) are not allowed.
12) Legal abuse of the rules is somewhat encouraged. An entry that, in
the opinion of the judges, violates the rules will be disqualified.
Entries that attempt to abuse the rules must try to justify why
their rule abuse is legal in the ---remark--- section.
FOR MORE INFORMATION:
The judging will be done by Leonid A. Broukhis, Jeremy Horn, Landon
Curt Noll and Peter Seebach. Please send questions or comments
about the contest, to:
questions@ioccc.org (not the address for submitting entries)
Comments about confusing rules and guidelines are also welcome.
The rules and the guidelines may (and often do) change from year to
year. You should be sure you have the current rules and guidelines
prior to submitting entries. To obtain them, visit the IOCCC web page:
http://www.ioccc.org
It has rules, guidelines and winners of previous contests (1984 to date).
As a last resort, previous winners may be obtained by sending EMail
to questions@ioccc.org. Please use the subject 'send YEAR winners',
where YEAR is a single 4 digit year or a year range (such as 1993-1994),
or the word 'all'.
+103
View File
@@ -0,0 +1,103 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <setjmp.h>
#include <time.h>
#define I ??(i??)??(j??)
#define K ??(i-1??)??(j??)
#define S strtok(NULL,",\n\0")
#define P printf(
#define NB_MSGS 42
#define C( f, m ) mNb = m;\
s = setjmp( sT??( sI++ ??) );\
if (!s) goto f;
#define bck longjmp( sT??( --sI ??), 0 );
jmp_buf sT??( 256 ??);
int m5??(84??),sI=0,c1='J'%2,mNb=0,s=0,mI=0,r=1;
unsigned long m1??(32??),q=0,z;
unsigned char m??( NB_MSGS ??)??( 11 ??);
int main( int argc, char *argv??(??) )
{
time_t tmT = time( NULL );
struct tm *tmS = localtime( &tmT );
char tms??( 7 ??);
int hr,n,i=1,j=0;
FILE *info = NULL;
char iS??( 2048 ??);
if ( argc > 1 ) info = fopen( argv??(1??), "r" );
strftime( tms, 7, "%H:%M\n", tmS );
if ( info != NULL ) {
fgets( iS, 2048, info );
m5??( 0 ??) = atoi( strtok( iS, ",\0" ) );
for ( hr = 1; hr < 85; hr++ ) m5??(hr??) = atoi(S);
for ( hr = 0; hr < 32; hr++ )
m1??( hr ??) = strtoul( S, NULL, 10 );
for ( hr = 0; hr < NB_MSGS; hr++ )
for ( n = 0; n < 11; n++ )
m??(hr??)??(n??) = (unsigned char)atoi( S );
fclose( info );
hr = atoi( strtok( tms, ":\0" ) );
n = atoi( strtok( NULL, ":\0" ) );
C( mA, 0 )
C( out, 40 )
s = setjmp( sT??( sI++ ??) );
if ( s ) {
s = setjmp( sT??( sI++ ??) );
if ( s ); else goto doHr;
} else goto doMin;
} else {
P "%s", tms );
goto eoj;
doMin:
z = 22;
C( doIt, 0 )
bck
doHr:
hr = ( n >= 36 ) ? hr+1 : hr;
if ( hr == 24 ) hr=0;
if (hr&&hr!=12)(hr<12)?(P "%d ",hr)):(P "%d ",hr-12));
n = hr + 61;
q = 0;
r = 1;
z = 16;
C( doIt, 0 )
P "\n" );
bck
doIt:
if ( r & m1??( m5??(n??) ??) ) {
if (z == 22) q = q << 1;
C( out, q )
if (z == 22) q = q >> 1;
}
r = r << 1;
q++;
if ( q < z ) goto doIt;
bck
out:
mI = 0;
mNb += c1;
while ( m??( mNb ??)??( mI ??) )
P "%c", m??( mNb ??)??( mI++ ??) );
bck
mA:
129<=m I ? 137>=m I ? m K=m I-32
: 145<=m I ? 153>=m I ? m K=m I-39
: 162<=m I ? 169>=m I ? m K=m I -47
: j : j : j : 125==m I ? m K=39
: 64==m I ? m K=32 : j;
j++;
if (m I) goto mA;
i+=2;
j = 0;
if ( i < NB_MSGS ) goto mA;
bck
}
eoj: exit( 0 );
}
+2
View File
@@ -0,0 +1,2 @@
0,1,1,1,1,1,2,2,2,2,3,4,4,5,5,6,7,7,8,8,9,10,10,10,10,10,11,11,11,11,12,13,13,13,13,13,14,14,14,14,15,16,16,17,17,18,19,19,20,20,21,22,22,22,22,22,23,23,23,23,24,25,26,26,26,27,27,27,27,27,27,27,27,28,29,29,29,29,30,30,30,31,31,31,31,256,2560,561152,557312,166400,143360,139520,140800,200704,196864,199168,544768,540928,542208,331776,327936,329216,274432,270592,271872,299008,295168,296448,4096,0,1,20,68,256,1028,4100,16384,0,0,0,0,0,0,0,0,0,0,0,148,137,132,149,137,135,136,163,64,0,0,0,0,0,0,0,0,0,0,0,0,0,137,149,64,163,136,133,64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,166,133,133,64,136,150,164,153,162,64,0,0,0,0,0,0,0,0,0,0,0,0,148,150,153,149,137,149,135,64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,149,150,150,149,64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,129,134,163,133,153,149,150,150,149,64,0,0,0,0,0,0,0,0,0,0,0,0,133,165,133,149,137,149,135,64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,129,163,64,149,137,135,136,163,64,0,0,0,0,0,0,0,0,0,0,0,0,0,133,167,129,131,163,147,168,64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,145,164,162,163,64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,129,134,163,133,153,64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,151,129,162,163,64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,129,147,148,150,162,163,64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,129,64,152,164,129,153,163,133,153,64,0,0,0,0,0,0,0,0,0,0,0,0,136,129,147,134,64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,163,133,149,64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,163,166,133,149,163,168,64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,129,134,163,133,153,64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,125,163,137,147,64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,151,129,162,163,64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,137,163,125,162,64,0,0,0,0,0,0
+65
View File
@@ -0,0 +1,65 @@
Most Timely Output:
Craig Schneiderwent
WI, USA
Judges' Comments:
To build:
make schneiderwent
To run:
./schneiderwent schneiderwent.data
Very nice play by the rules and portable text obfuscation.
This far surpasses old tricks like adding or subtracting 1
from every character in a C string.
Translating the messages into your language of preference while
keeping the program portable between different encodings
(Chinese, Japanese, Russian - anyone?) may be an entertaining task.
Selected Author's Comments:
This entry displays the current time to the console, for example:
it's just after ten 'til 6 in the evening
FWIW, none of the compilers with which this entry was tested issued
any warnings or errors in compiling the source for this entry. No
doubt lint will complain about the goto statements.
The schneiderwent.data file consists of the values used by multiple
table lookups. This is simply good program design, separating
these values from the source code allows changing the behavior of
the application without recompiling.
Having learned COBOL at an early age, the pthreads of my thought
processes tend to be translated into code in a verbose manner. Some
of the #defines in this entry's code are to mitigate this personal
deficiency.
Obfuscation in this entry consists of:
> printfing console messages stored as EBCDIC character values - this
is not an attempt at encryption, but rather at cross platform
compatibility
> ASCII character values are calculated from the EBCDIC in a
particularly ugly abuse of the '?' operator
> detection of whether to print the ASCII or EBCDIC values is done by
taking the remainder of dividing the character 'J' by 2 - the ASCII
value of the character is even, the EBCDIC value is odd
> the messages to be printfed are determined via multiple table
lookups and bitmasked values
> for minutes, the bit position turned on is multiplied by two
to determine the message to be printfed
> for hours, the straight bit position is used
> this entry mostly eschews function calls for the often overlooked
setjmp/longjmp combination
> the trigraphs are not there as obfuscation nor are they there to
annoy the judges - it's just the easiest way to get around the
absence of square brackets in a normal 3270 environment
+103
View File
@@ -0,0 +1,103 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <setjmp.h>
#include <time.h>
#define I ??(i??)??(j??)
#define K ??(i-1??)??(j??)
#define S strtok(NULL,",\n\0")
#define P printf(
#define NB_MSGS 42
#define C( f, m ) mNb = m;\
s = setjmp( sT??( sI++ ??) );\
if (!s) goto f;
#define bck longjmp( sT??( --sI ??), 0 );
jmp_buf sT??( 256 ??);
int m5??(84??),sI=0,c1='J'%2,mNb=0,s=0,mI=0,r=1;
unsigned long m1??(32??),q=0,z;
unsigned char m??( NB_MSGS ??)??( 11 ??);
int main( int argc, char *argv??(??) )
{
time_t tmT = time( NULL );
struct tm *tmS = localtime( &tmT );
char tms??( 7 ??);
int hr,n,i=1,j=0;
FILE *info = NULL;
char iS??( 2048 ??);
if ( argc > 1 ) info = fopen( argv??(1??), "r" );
strftime( tms, 7, "%H:%M\0", tmS );
if ( info != NULL ) {
fgets( iS, 2048, info );
m5??( 0 ??) = atoi( strtok( iS, ",\0" ) );
for ( hr = 1; hr < 85; hr++ ) m5??(hr??) = atoi(S);
for ( hr = 0; hr < 32; hr++ )
m1??( hr ??) = strtoul( S, NULL, 10 );
for ( hr = 0; hr < NB_MSGS; hr++ )
for ( n = 0; n < 11; n++ )
m??(hr??)??(n??) = (unsigned char)atoi( S );
fclose( info );
hr = atoi( strtok( tms, ":\0" ) );
n = atoi( strtok( NULL, ":\0" ) );
C( mA, 0 )
C( out, 40 )
s = setjmp( sT??( sI++ ??) );
if ( s ) {
s = setjmp( sT??( sI++ ??) );
if ( s ); else goto doHr;
} else goto doMin;
} else {
P "%s", tms );
goto eoj;
doMin:
z = 22;
C( doIt, 0 )
bck
doHr:
hr = ( n >= 36 ) ? hr+1 : hr;
if ( hr == 24 ) hr=0;
if (hr&&hr!=12)(hr<12)?(P "%d ",hr)):(P "%d ",hr-12));
n = hr + 61;
q = 0;
r = 1;
z = 16;
C( doIt, 0 )
P "\n" );
bck
doIt:
if ( r & m1??( m5??(n??) ??) ) {
if (z == 22) q = q << 1;
C( out, q )
if (z == 22) q = q >> 1;
}
r = r << 1;
q++;
if ( q < z ) goto doIt;
bck
out:
mI = 0;
mNb += c1;
while ( m??( mNb ??)??( mI ??) )
P "%c", m??( mNb ??)??( mI++ ??) );
bck
mA:
129<=m I ? 137>=m I ? m K=m I-32
: 145<=m I ? 153>=m I ? m K=m I-39
: 162<=m I ? 169>=m I ? m K=m I -47
: j : j : j : 125==m I ? m K=39
: 64==m I ? m K=32 : j;
j++;
if (m I) goto mA;
i+=2;
j = 0;
if ( i < NB_MSGS ) goto mA;
bck
}
eoj: exit( 0 );
}
BIN
View File
Binary file not shown.
+93
View File
@@ -0,0 +1,93 @@
int
X=320 ,Y=200,
n=0,m, x,y, j=1024;
double T=44.0 /7,P[
333333 ],C[5] ={ 0,3,
0,0,8} ,p=1, B=11.0
/630, f=0,r = 3,g
=7,b =13,*q=P, D,*J;
unsigned char
U[66666],*v=U,*h,l[5555]
,c=0,*e,*a,*z;
#include <math.h>
#define R1(t) t=(int)(t\
*123456789 )%j; t/=j;
#define Rl(C,t)\
n++[C] = t*n/12;
#define RI(C) B=-B; R1\
(r)R1(g )R1(b )for(n\
=0; n<j; ){ Rl(C ,r)Rl\
(C,g)Rl(C ,b)++n; }
#ifdef __DJGPP__
#include <sys/movedata.h>
#include <dpmi.h>
#include <pc.h>
#define Q(u,v) u##portb(0x3##v
#define W ; Q(out,C9),*h++/4)
void F(int i){ __dpmi_regs r
; if(i){ for(; i>=0; i-=8)while(
~Q(in,DA)
)&8^i); for(m=0,z
=h+j; h <z; m ++){ Q(
out,C8),m )W W W; ++h; } dosmemput
(v,X*Y,0xA0000 ); } else{ r.x.ax=
0x13; __dpmi_int( 0x10,&r); } }
#elif defined(SDL)
#include "SDL/SDL.h"
SDL_Surface *s; void
F(int i){ if (i){ SDL_SetColors(
s,h,0,256); SDL_UpdateRect
(s,0,0,0, 0); } else { SDL_Init(
SDL_INIT_VIDEO); s=SDL_SetVideoMode
(X,Y,8,0); v=s->pixels; } }
#else
#include "curses.h"
void F(i){ if(i){ for(y=0;
y<X*Y ; y++)
{ move (y/X,y%X); addch
((*(v +y)/ 32) [" ."
",:+" "=@#" ]); } ; refresh
(); } else{ initscr
(),x= COLS&~1,X=x<X?x:X,y=
LINES &~1,Y=y<Y?y:Y; } }
#endif
main()
{
F(0);
for (x=-X/2,y=-Y/2;y<Y/2;++x>=X/2?x=-X/2,y++:4)
{*q++ = sqrt(x*x+y*y);
*q++ = atan2(x,y);
}for (;n<j*2;l[n++]=0);
for(;;)
{
a=l;z=l+j;e=l+j*2;
if ((p+=B)>1){p=2-p;RI(l+j)}
else if (p<0){p=-p;RI(l)}
while(a<l+j) D=p**a+++(1-p)**z++,*e++=D;
h=l+j*2;
for (J=P,z=v; z<v+X*Y;){
D = *J++;
*z++=fabs(sin((*J+++C[1])*1.5+D*C[0]+C[2]*sin(C[3]+D/C[4]))*255);
}F(8);
C[2]+=B; f+=T/360; C[3]+=f;
if (f>T)
{C[1] += (f-T)/8;
if (f>T*2)
C[0]=sin(f)+sin(f*2)/2;
}
}
}
+70
View File
@@ -0,0 +1,70 @@
Most Portable Output:
Thaddaeus Frogley
Creature Labs
164 Hornbeams,
Harlow, Essex,
UK
Gavin Buttimore
Creature Labs
9 Elizabeth Way,
Cambridge,
UK, CB4 1DE
Judges' Comments:
To build:
make thadgavin
To run:
./thadgavin
This entry is a nice play by the rules. It can use curses, if the
SDL graphic library is not present, and is quite good at that,
but the colors used in graphic mode (16 bit depth) are unfortunately
less than dazzling. We could not test this entry in DOS mode.
Selected Author's Comments:
To run under DOS:
Compile using DJGPP as follows:
gcc thadgavin.c -o thadgavin.exe -Wall -lm -O6 -mpentium -fomit-frame-pointer
-ffast-math
To run under Windows, X-Windows or MacOS using the
Simple DirectMedia Layer:
For example:
gcc -O6 -lpthread -g -o thadgavin thadgavin.c -lSDL -DSDL -lm
In gcc you may get the following warning:
prog.c:46: warning: passing arg 2 of `SDL_SetColors' from incompatible
pointer type
In Microsoft Visual Studio you may get warnings as follows:
prog.c(46) : warning C4133: 'function' : incompatible types - from 'unsigned
char *' to 'struct SDL_Color *'
prog.c(63) : warning C4026: function declared with formal parameter list
prog.c(77) : warning C4244: '=' : conversion from 'double ' to 'unsigned
char ', possible loss of data
But don't worry, this is completely normal.
Recommended dosage:
At least 3 minutes taken 3 times a day when tired.
Do not exceed 3 times recommended dose. May cause
sickness, dizziness, nausea.
+101
View File
@@ -0,0 +1,101 @@
// Initially you will be calm and serene:
int
X=320 ,Y=200,
n=0,m, x,y, j=1024;
double T=44.0 /7,P[
333333 ],C[5] ={ 0,3,
0,0,8} ,p=1, B=11.0
/630, f=0,r = 3,g
=7,b =13,*q=P, D,*J;
unsigned char
U[66666],*v=U,*h,l[5555]
,c=0,*e,*a,*z;
#include <math.h>
#define R1(t) t=(int)(t\
*123456789 )%j; t/=j;
#define Rl(C,t)\
n++[C] = t*n/12;
#define RI(C) B=-B; R1\
(r)R1(g )R1(b )for(n\
=0; n<j; ){ Rl(C ,r)Rl\
(C,g)Rl(C ,b)++n; }
// Later your brain will look more like this:
#ifdef __DJGPP__
#include <sys/movedata.h>
#include <dpmi.h>
#include <pc.h>
#define Q(u,v) u##portb(0x3##v
#define W ; Q(out,C9),*h++/4)
void F(int i){ __dpmi_regs r
; if(i){ for(; i>=0; i-=8)while(
~Q(in,DA)
)&8^i); for(m=0,z
=h+j; h <z; m ++){ Q(
out,C8),m )W W W; ++h; } dosmemput
(v,X*Y,0xA0000 ); } else{ r.x.ax=
0x13; __dpmi_int( 0x10,&r); } }
#elif defined(SDL)
#include "SDL/SDL.h"
SDL_Surface *s; void
F(int i){ if (i){ SDL_SetColors(
s,h,0,256); SDL_UpdateRect
(s,0,0,0, 0); } else { SDL_Init(
SDL_INIT_VIDEO); s=SDL_SetVideoMode
(X,Y,8,0); v=s->pixels; } }
#else
#include "curses.h"
void F(i){ if(i){ for(y=0;
y<X*Y ; y++)
{ move (y/X,y%X); addch
((*(v +y)/ 32) [" ."
",:+" "=@#" ]); } ; refresh
(); } else{ initscr
(),x= COLS&~1,X=x<X?x:X,y=
LINES &~1,Y=y<Y?y:Y; } }
#endif
main()
{
F(0);
for (x=-X/2,y=-Y/2;y<Y/2;++x>=X/2?x=-X/2,y++:4)
{*q++ = sqrt(x*x+y*y);
// store result of atan2 of x and y in *q++
*q++ = atan2(x,y);
}for (;n<j*2;l[n++]=0);
for(;;)
{
a=l;z=l+j;e=l+j*2;
if ((p+=B)>1){p=2-p;RI(l+j)}
else if (p<0){p=-p;RI(l)}
// will the maintenance programmer get this?
while(a<l+j) D=p**a+++(1-p)**z++,*e++=D;
h=l+j*2;
// best way?
for (J=P,z=v; z<v+X*Y;){
D = *J++;
*z++=fabs(sin((*J+++C[1])*1.5+D*C[0]+C[2]*sin(C[3]+D/C[4]))*255);
}F(8);
// tidy up later
C[2]+=B; f+=T/360; C[3]+=f;
// just in case
if (f>T)
{C[1] += (f-T)/8;
// sorry
if (f>T*2)
C[0]=sin(f)+sin(f*2)/2;
}
}
}
+22
View File
@@ -0,0 +1,22 @@
#include <stdio.h>
#define true
true /*:all
CC=cc
PROG=tomx
false :
make -f $0 $1
exit 0
all: $(PROG)
%:%.c
$(CC) $< -o $@
clean:
rm $(PROG)
.PHONY: /* true clean */
int main() {return!printf("Hello, world\n");}
+114
View File
@@ -0,0 +1,114 @@
Most Complete Program:
Thomas P John
Mishybi Plamoottil
Parottukonam
Nalanchira P.O, Trivandrum-695015
India
http://tomx.tripod.com/
Judges' Comments:
To build:
make tomx
Try:
rm -f ./tomx
sh tomx.c
./tomx
If sh is your shell:
rm -f ./tomx
chmod +x ./tomx.c
./tomx.c
./tomx
Also try:
rm -f ./tomx
make -f tomx.c
./tomx
Polyglots have come and gone, but this was the first one we'd seen
where one language *used* another to perform its tasks. An interesting
approach. Admittedly, it's not all that obfuscated - but there's more
to it than you might think, since you have to make sure that your
changes don't change the shell code or the makefile.
Selected Author's Comments:
Summary
-------
This program works as a C source file, a Makefile and also as a
Shell (/bin/sh) script. But unlike some other multi-language prog-
rams, this one is NOT meant to print "Hello, world" in all 3 cases
(At least in the true sense ;-)). The C, make and shell code build
upon each other to create a C program (?) which when executed as a
shell script will compile itself through the C compiler using a
makefile! - Pretty useful, Eh?.
Probably, this is the first entry ever to fully satisfy Rule #1
("Your entry must be a complete program") in the strictest sense;-)
Top 5 reasons (IMHO) why this code is an entry for IOCCC
--------------------------------------------------------
1. A glance at the source itself will tell U that most of the
Obfuscation is NOT in the C code per se, but in the comments
to the C code. (But sadly, I could not find an "International
Obfuscated C COMMENT contest". So I HAD to sent this entry
here to the IOCCC itself).
2. Of the 3 languages in the source, the least obfuscated is
C (But again, there was NO obfuscated make/shscript contest)
(Does this hint for a rule in IOCCC-2001 that the major
obfuscation should be in C and not elsewhere???. Mmmmm...)
3. Extending Argument #2... Obfuscation done in the C code
(comments?) create obfuscated code for the other 2 languages.
This opens new possibilities to be explored in depth in future
IOCCCs
4. LOOKS like a makefile, WORKS like a shell script and COMPILES
like a C program
5. Does something useful (See Notes #1, #2)
Notes
-----
1. The program could have been something other than the simple
"Hello, world" program that it is. It is possible to do
#include "prog2.c" in the place of the main(), leaving the
complexities of the C file elsewhere and making this source
still acceptable to "make" and "sh". The following modif-
ication to the last few lines will compile IOCCCs famous
"mkentry.c"
.PHONY: /* true clean */
#undef true
#include "mkentry.c"
Ain't that useful?
2. By extending this program's idea, It is possible to do some
very interesting things like generating C code on execution
by adding additional code in make/sh (open up a loop????).
This opens the possibilities of generating & compiling some
[obfuscated?] C code.(Maybe should try this if this program
fails at IOCCC 2000)
3. Changing the "%:%.c" dependency to a "$(PROG):$(PROG).c" form
can compile this program with some other make-s (I got it to
work in Windows using nmake and Gnuwin32's sh ;-)
4. Interesting things to do: try "$ ./tomx.c clean". This will
do the same as "make clean" :-)). Also: "$ ./tomx.c all"
5. Be careful about the Tabs in the source code. Removing them
or converting Tabs to spaces can be disasterous