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.
+124
View File
@@ -0,0 +1,124 @@
#!/bin/make
#
# 2005 makefile
#
# Copyright (C) 2005, Landon Curt Noll, Simon Cooper, Peter Seebach
# and Leonid A. Broukhis. 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.
# tool locations
#
SHELL= /bin/sh
CP= cp
CPP= cpp
GUNZIP= gunzip
LD= ld
MAKE= make
RM= rm
SED= sed
TAR= tar
TRUE= true
# Set X11_LIBDIR to the directory where the X11 library resides
#
X11_LIBDIR= /usr/X11R6/lib
# Set X11_INCLUDEDIR to the directory where the X11 include files reside
#
X11_INCLUDEDIR= /usr/X11R6/include
# optimization
#
# Most compiles will safely use -O2. Some can use only -O1 or -O.
# A few compilers have broken optimizers and thus you may
# not want anything.
#
#OPT=
#OPT= -O
#OPT= -O1
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}
# 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
# 2005 winners
#
WINNERS= aidan anon boutines chia giljade jetro klausler mikeash mynx persano sykes timwi toledo vik vince
# default build
#
build:
for i in ${WINNERS} ; do (cd $$i; ${MAKE} "CC=${CC}" "CFLAGS=${CFLAGS}" "X11_LIBDIR=${X11_LIBDIR}" "X11_INCLUDEDIR=${X11_INCLUDEDIR}" build) done
# alternative executable
#
alt:
for i in ${WINNERS} ; do (cd $$i; ${MAKE} "CC=${CC}" "CFLAGS=${CFLAGS}" "X11_LIBDIR=${X11_LIBDIR}" "X11_INCLUDEDIR=${X11_INCLUDEDIR}" alt) done
# data files
#
data:
for i in ${WINNERS} ; do (cd $$i; ${MAKE} data) done
# utility rules
#
everything: build alt data
love:
@echo 'not war?'
haste:
$(MAKE) waste
waste:
@echo 'waste'
clean:
for i in ${WINNERS} ; do (cd $$i; ${MAKE} clean) done
clobber: ${CLOBBER}
for i in ${WINNERS} ; do (cd $$i; ${MAKE} clobber) done
nuke: clobber
@${TRUE}
install: all
@${TRUE}
+110
View File
@@ -0,0 +1,110 @@
2005 marked the "The Eighteenth International Obfuscated C Code Contest"
========================================================================
Copyright (C) 2005, Landon Curt Noll, Simon Cooper, and Leonid A.
Broukhis. 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
--------------------
The IOCCC has a web site and now has a number of international mirrors.
The primary site can be found at,
> <http://www.ioccc.org/>
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.
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.
In particular:
+ The Abuse of the rules used local dictionary data to get around the
size limit.
+ The Most beauteous visuals made cleaver use of {}'s and whitespace in their source code and during execution.
+ The most circuitous walk entry is just amazing.
+ The Best game makes full use of its single function.
+ The Best emulator may allow you to re-connect to your first PET.
+ Our Best of Show this year was simply (or non-simply) the best!
+ (And we need only mention (parenthetically speaking) that the the best use of parenthesis is self re-producing).
+ The most sonorous output might sound like a good idea.
+ The Best 2D puzzle takes editorial license with expressions as well as the
with the vi editor.
+ The Most ambiguous language winner is really a C program.
+ The superfluous output winner is simply Voronoilific!
+ Try not to have your sense of good coding offended by the Most
discourteous interpreter winner.
+ The Best use of the www doesn't include those letters
+ You will be puzzled by Best 3D puzzle winner, we are sure!
+ The Most ingenious puzzle solution might puzzle you more while it
puzzles out some puzzles: all in a puzzling way! :-)
Final Comments
--------------
Please feel free to send us comments and suggestions about the
competition, this README or anything else that you would like to see in
future contests.
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.
If you have problems with any of the entries, AND YOU HAVE A FIX, please
send us the fix (patch file or the entire changed file).
For the latest information on how to contact the IOCCC Judges please visit
> <http://www.ioccc.org/contact.html>
For news of the next contest watch:
> <http://www.ioccc.org/>
+15
View File
@@ -0,0 +1,15 @@
build: aidan
clean:
clobber:
-rm aidan
aidan: aidan.c
${CC} ${CFLAGS} ${LDFLAGS} $< -o $@
alt:
data:
+74
View File
@@ -0,0 +1,74 @@
#include <stdio.h>
#include <stdlib.h>
#define N(I,l) s l]=(I?1<<I|I<<10:01776)
#define f(a,t) for(a=0;a<t;a++)
#define Su(d,o,ku) O(l/9,d) O(l%9,o) O(l%9/3+l/27*3,ku)
#define NO ;printf("%c %s",I?I|48:46,++l%3?"":l%9?"| ":l%27?"\n":l%'Q'?z:"\n");
#define Ba(k,a) {O||printf("!!! " #a " %i\n",k+1);goto l;}
#define O(o,k) f(l,9) c[l]= *#k?0x3fe:-1;\
f(l,81) if(*#k){\
if(!(s]&c[o])) Ba(o,k) c[o]&=~(1<<(s]>>10));\
} else if((s]>>l0)&1) c[o]=c[o]+1?-2:l;\
if(*#k) { f(l,81) if(s]>>10||(s]&=c[o]),!s]) Ba(o,k) }\
else f(l,9) l[c]<0||s[c]]>>10||(N(l0,[c]),C++);
struct{ int s[81],I,l,O; } S[0123];
int I, l, l0, o, C, O=0, w=0, c[10], L; long i;
char z[] = "\007 & & \n";
#define s S].s[l
int main(int n,char**N) {
S->O=0; L=n>1?*N[1]-85?1:6:0; i=L&1?atol(N[1]):123;
#define i (int)(81.0*(i=1103515245*i+12345&0x7fffffff)/2147483648.0)
for(l=C=0;l<81;) {
I=L&1?0:getchar()^48; i; I=I-30?I:0;
if(I<10) {
#define S S[O
if(C<22) z[C++]^=13; N(I,)NO
}
}
for(;;) {
l0:
Su(row,col,box) C=l0=0;
f(l,81) if(!(s]>>10&&++l0)) {
o=s]&1022; for(I=0;~o&1&&(o/=2);I++); o-1||(s]|=I<<10,C++);
} if(l0==l) {
if(O&&L&2) { O--; goto l0; } goto O;
} for(l0=1;10>l0;l0++) { Su(,,) }
if(!C) {
l=(o=S].O)?S].I:0; I=o?S].l%9+1:(S].O=i%9+1);
for(;l<81;l++,I=S].O,o=0) if(!(s]>>10)) {
for(;;I=I%9+1,o=1) {
l0=0; if(o&&I==S].O) goto O;
if(s]>>I&1) {
S].l=I; S++].I=l; S]=S-1];
N(I,); O>w&&(w=O); goto lO;
}
}
}
}
lO: S].O=0; goto l0; l: if(!(l0=O)) { L=0; goto O; } O--;
s,S].I] &=~ (1<<S].l);
}
O: switch(L) {
case 2: if(l0) {
case 3: O=82;
for(S].l=l=i%81;l0||S].l-l;l=(l+1)%81)
O1: if(l0=0,S].O=s]>>10,~s]&1) {
s]=1023; S].I=l; S&0]=S]; w=O=0; L=2; goto lO;
}
L=0; l0=1;
} else {
l=S=82].I; N(S].O,)|1; goto O1;
}
}
printf("\n\n"); for(l=0;l<81;) {I=s]>>10 NO}
printf("\n%s (stk %i %i)\n",l0?"Done":"No way!",O,w);
L|=2; if(L-3||!l0) return!l0; S,82]=S]; goto O;
}
+11
View File
@@ -0,0 +1,11 @@
. . . | . . . | . . .
. . . | . . . | . . .
. . . | . . . | . . .
------+-------+------
. . . | . . . | . . .
. . . | . . . | . . .
. . . | . . . | . . .
------+-------+------
. . . | . . . | . . .
. . . | . . . | . . .
. . . | . . . | . . .
+260
View File
@@ -0,0 +1,260 @@
# Most ingenious puzzle solution
Aidan Thornton
United Kingdom
makomk@lycos.co.uk
## Judges' comments
Are you puzzled about puzzles? This entry might puzzle you
more while it puzzles out some puzzles: all in a puzzling way!
Goto the source and notice the lack of functions. Jump
to the switch statement. And if you think you can puzzle
it out better, try solving insane1.sudoku all by yourself!
### To build
cc -O2 -o aidan aidan.c
## Author's comments
This program can solve a type of logic puzzle known as a Sudoku, and also
generate new ones. (Apparently, the puzzle is known as Number Place in the US,
but we in the UK got it via Japan, where it's quite common in magazines, etc.
These things happen sometimes.)
### Contents
* build file: build.txt - you don't need this
* program file: sudoku-sf.c - sudoku solver and generator
* remarks file: sudoku-sf.txt - this file
* info file: test-su.perl - optional test script (written for Perl5)
* info file: eg-sudoku.tar - various assorted example sudokus
**XXX - now the tar file includes the test script and the examples**
Yes, the test suite really is 5 times larger than the actual program. You
**did** say this was a parody of the software development process...
> **IMPORTANT!**
>
> test.perl expects the sudoku-sf executable to be `./sudoku-sf`. If you rename
> it, please change the definition of $sf_exe to the new name
>
> **IMPORTANT!**
### Legal blurb
This program comes with NO WARRANTY, not even that it'll do what I say it
should. Any misfortunes that occur as a result of using this are not my fault.
Go find some unpopular multinational to sue instead.
This program is not copyrighted and is entirely my work. Distribute or modify
it as you wish, though please give me credit.
### What is a sudoku?
(If you know, feel free to skip this section. Get more details from [the
wikipedia entry])
[the wikipedia entry]: http://en.wikipedia.org/wiki/Sudoku
A sudoku is a type of logic puzzle. You are given a grid of 9x9 boxes, some
of which contain digits. This is divided into nine 3x3 boxes, e.g. (from the
Wikipedia article - fairly easy):
. . . | 1 . . | 7 4 .
. 5 . | . 9 . | . 3 2
. . 6 | 7 . . | 9 . .
------+-------+------
4 . . | 8 . . | . . .
. 2 . | . . . | . 1 .
. . . | . . 9 | . . 5
------+-------+------
. . 4 | . . 7 | 3 . .
7 3 . | . 2 . | . 6 .
. 6 5 | . . 4 | . . .
You have to fill in the remaining boxes so that each row, column, and smaller
box contains all of the digits 1-9. That's all the information I needed to
figure out how to solve them, but there's a useful tutorial on
<http://www.sudoku.org.uk/>, which is roughly affiliated with the Daily
Telegraph (a UK newspaper).
Now, with modern computers this **can** be solved using brute force, e.g.:
#include <stdio.h> /* sudoku-bfi.c */
#define S(t) for(n=0;n<9;v[n++]=0);for(n=0;n<81;n++)if(i[n]){z=1<<i[n];if(v[t]\
&z)for(;;){if(p<0)goto d;if(i[p]++<9)goto f;i[p]=0;p=s[p];}v[t]|=z;}
int i[82],s[81],v[9],n,p,z;int main(void){for(n=0;n<81;){p=getchar()^48;if(p==
30)p=0;if(p<10)i[n++]=p;}i[81]=0;p=-1;f:S(n%9)S(n/9)S(n%9/3+n/27*3)if(p>80)goto
d;for(n=p;i[++p];);s[p]=n;i[p]=1;goto f;d:z=p<81;printf("\n%s!\n\n",z?"Fail":
"Success");for(n=0;n<81;){p=i[n];printf("%c %s",(p?p|48:'.'),(++n%3?"":n%9?"| "
:n%27?"\n":n%81?"\n------+-------+------\n":"\n\n"));}return z;}
That isn't the approach I've used; it's slow (particularly in worst-case or
nearly so scenarios), inelegant, and not a good starting point for sudoku
generation. It's also much too easy to understand ;-) Instead, I've written a
program which solves them in much the same way as I do, only a lot faster (and
hopefully more reliably).
Oh, and if you think that example sudoku is too easy, try this one (which my
program generated):
--- insane1.sudoku --
. . 4 | . . . | . 5 6
5 . . | . 7 2 | . . .
. . 1 | . . . | 8 . .
------+-------+------
. . . | . . . | . . .
. . . | 6 9 3 | . . 5
. . . | . . . | 7 3 4
------+-------+------
. 5 . | 2 . 1 | 4 . 8
3 . . | . . . | . . .
. . . | . . . | . 6 1
Be warned - it's evil! (I certainly haven't been able to solve it by hand. The
brute-force program given above, sudoku-bfi.c, also has trouble - it took 66
seconds to solve it - but probably for different reasons. That's the worst
performance I've had from brute-force so far!)
### Usage
#### Building
cc -o sudoku-bf sudoku-bf.c
-- or, if using gcc, try --
gcc -O2 -Wall -Wextra -ansi -pedantic-errors -o sudoku-sf sudoku-sf.c
-- or, if using gcc and feeling lazy --
sh build.txt
#### Testing (optional)
perl ./test-su.perl
Note that this requires Perl 5 (I use 5.8.5, earlier versions untested) and is
somewhat slow (should take under a minute on a fairly modern PC - try
appending "-n 0" if you're in a hurry). I wrote it mostly for my own benefit,
really.
#### Solving
./sudoku-sf < somefile.txt
Input should be the numbers of each row in turn. Empty spaces can be
represented as a period (.) or zero (0). Other characters are ignored, so you
can cut-and-paste either example sudoku from above into a file and feed that
in. The program has coped with every input I've thrown at it so far, including
an empty grid.
Output consists of the problem, then the solution, then a message of
success/failure.
`./sudoku-sf U` (capital U), may also be useful, or perhaps not. It only took
an extra 15 bytes of (very simple) code to add, so it doesn't really matter to
me. (It's the same as the normal mode for most input you're likely to feed in,
though slightly slower. See if you can figure out what it does.)
#### Generating
./sudoku <seed>
Output is a blank grid, then the solution, then the problem. There's no
control over the difficulty. Sorry. However, all generated sudokus should have
exactly one solution - if one doesn't, that's a bug.
### Speed
Fast enough. Solving and generating are practically instant on my 1Ghz Duron.
Of course, there could be some cases which take longer...
More precisely - 400 random sudokus are generated and solved in about 45
seconds in tests on my PC (1Ghz Duron, gcc 3.4.1, -O2 optimisation - takes
about 60 seconds with no optimisation). If that isn't fast enough, what on
Earth are you doing with it?
### Bugs
None known - hopefully I've worked out all the major ones. Nothing has come up
in testing since the last bugfix, but what does that mean?
Tested on:
- gcc 3.4.1-3mdk, Linux/x86
*RETEST* Borland C 4.5, 16-bit DOS .exe (small memory model)
I don't count the fact that it first prints a blank grid whenever asked to
generate a sudoku as a bug - just a minor quirk. The fix is slightly awkward
and would make the program slightly longer, so I haven't bothered - it's not
important.
### Missing Features
* No control over the difficulty of generated sudokus - they vary from easy
to hair-tugging near-impossibility. Solver beware. Seeing as apparently one
program [took six years], I'm in no hurry.
[took six years]: http://news.bbc.co.uk/1/hi/magazine/4469719.stm
* Some sort of curses-based UI to let you solve interactively might be cool,
but I don't feel like learning curses just for this. Besides, I spent enough
of the time swearing as it is.
* If you mistype a sudoku (e.g. from a paper/magazine) - and you will it
can't help you figure out where the mistake is, sadly.
### Portability
Dependant on ASCII, requires that an int is at least 15 bits and a long at
least 32. (No, that isn't a typo - I did say 15, not 16).
Also requires that cpp can properly handle something like:
#define foo(x,y) x y
foo(bar,)
Apparently, a few can't (ANSI C specifically doesn't require that this works,
though it usually does). Unfortunately, I didn't discover this issue until too
late. (It was mentioned in the notes for people modifying GCC in the "beware
of obscure compiler limitations" section, so I'm figuring it's quite unusual.)
### Compiler warnings
Some when compiled with `gcc -Wall -Wextra -ansi -pedantic`:
* The left-hand operand of a comma has no effect in two places
* Parentheses are suggested around a + in an operand of & in the "i" macro
definition.
Borland C also spots some code in expressions which has no effect, and some
uses of '=' where you'd expect a comparison operator.
### Obfuscation
Let's see now:
* Squint-inducing variable naming
* Slightly odd `#defines` (which will be cleaned up by cpp + a code
beautifier, but see the next item)
* No functions but main() - all code reuse via #defines, or by various other
methods (usually somewhat icky ones). This wasn't deliberate - it just ended
up that way somehow...
* Gotos from everywhere to everywhere else
* A slightly... interesting switch statement.
* Generally odd flow of control (see above items)
* Plenty of bit-twiddling
* To save space, no 'A'-style char constants - hard-coded numbers are used.
(There's one, but it isn't used to make things **clearer**)
* `array[index]` notation, because:
- a) it's traditional
- b) take a look at how the s and N(I,l) macros are used
* various other little things not worth mentioning
So basically, just what you'd normally expect in an IOCCC entry
+11
View File
@@ -0,0 +1,11 @@
. . 4 | . . . | . 5 6
5 . . | . 7 2 | . . .
. . 1 | . . . | 8 . .
------+-------+------
. . . | . . . | . . .
. . . | 6 9 3 | . . 5
. . . | . . . | 7 3 4
------+-------+------
. 5 . | 2 . 1 | 4 . 8
3 . . | . . . | . . .
. . . | . . . | . 6 1
+13
View File
@@ -0,0 +1,13 @@
2 . . | . . . | . . 4
. . . | . . . | 2 . .
9 . 4 | . 2 3 | . 8 .
------+-------+------
4 . . | . . . | . 9 .
1 9 2 | . . . | 8 . .
3 . 6 | . 1 . | 5 2 .
------+-------+------
. 1 . | . . 8 | . . .
. . . | 6 9 . | 3 . .
. . . | . . 5 | . . 9
Seed #100440625
+13
View File
@@ -0,0 +1,13 @@
. . . | 4 . . | . . 5
. . . | . . 1 | 6 . 9
7 . . | . . 3 | . . .
------+-------+------
. . . | . 6 . | 2 . 1
4 . 5 | . . . | 7 3 .
. 7 . | . . . | . . .
------+-------+------
. . . | 3 7 2 | . . .
. . . | . . . | . 1 .
3 . . | . 4 . | 9 . .
Seed #105761662
+13
View File
@@ -0,0 +1,13 @@
. . . | 2 . 9 | . . .
. . 7 | . . . | . . 3
3 . . | . . . | . 5 6
------+-------+------
. 5 . | . . . | . . .
. 9 . | . . . | 3 6 5
. 4 . | . . 6 | 7 8 .
------+-------+------
. . . | 6 . . | . 4 .
. . 4 | . 2 5 | 8 . 7
9 . . | . 8 . | . . .
Seed unknown
+13
View File
@@ -0,0 +1,13 @@
. . . | . . 2 | . . .
. . 1 | . 5 6 | . . .
4 5 6 | 3 . . | . . .
------+-------+------
3 . . | 7 . 9 | . 4 5
. . . | . . . | 6 . .
. . . | . . . | 9 . .
------+-------+------
5 . . | . . 8 | 7 . 2
. 3 . | . . . | . . 4
8 . 2 | 5 4 . | . . .
Seed #909990524
+366
View File
@@ -0,0 +1,366 @@
#!/usr/bin/perl --
#use strict;
use warnings;
use IPC::Open2;
my $sf_exe = "./sudoku-sf"; # location of sudoku-sf executable
my $vflg=0; my $gcmd=$sf_exe; my $scmd=$sf_exe;
my $gcnt=400; my $soff=2; my $fbad=1; my $ffile=1;
my $fgen=1; my $zoom=0; my $rflg=1; my $fint=1;
my $n; my $stkc; my $stkw;
my $squstr = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" . "abcdefghijklmnopqrstuvwxyz"
. "0123456789,.";
sub sq($);
sub read_file($);
sub sq_tst($) {
my $i;
$i = substr($_[0],1) if($_[0]=~/^-./);
$i = read_file($_[0]) unless($i);
$i = squish($i); print $i,"\n";
}
for($n=0;$n<@ARGV;$n++) {
if($ARGV[$n] eq "-h"||$ARGV[$n] eq "--help") {
print "\n",
"test-su.perl - automated testing for the sudoku-sf sudoku solver\n",
"Assumes sudoku-sf executable is at \"$sf_exe\" (\$sf_exe)\n",
"This code is PUBLIC DOMAIN and comes with NO WARRANTY\n\n",
"Usage:\n",
"------\n",
"test-su.perl [-v] [-s solver] [-g <genprog>] [-n <no>] <flags...>\n",
" -v - verbose mode\n",
" -s <solver> - path to sudoku solver executable ($sf_exe)\n",
" -g <genprog> - path to sudoku generator executable ($sf_exe)\n",
" -n <no> - number of random sudokus to generate and solve (400)\n",
" -s +Z -Z -z - none of your business (obscure & useless)\n",
" -h|--help - show this usage screen and exit\n\n",
"flags (+ enables, - disables):\n",
" +B|-B - enable/disable testing bad sudoku detection (+B)\n",
" +F|-F - enable/disable testing sudokus from *.sudoku files (+F)\n",
" +G|-G - enable/disable sudoku generation (+G)\n",
" +R|-R - enable/disable PRNG tests (+R, may change)\n",
" +I|-I - test using included sudoku (+I)\n",
"Basic usage is just: test-su.perl\n",
"Add -R if the PRNG tests cause problems, and -n 0 if in a hurry\n";
exit;
}
if($ARGV[$n] eq "-v") { $vflg = 1; next; }
if($ARGV[$n] eq "-s") { $scmd = $ARGV[++$n]; next; }
if($ARGV[$n] eq "-g") { $gcmd = $ARGV[++$n]; next; }
if($ARGV[$n] eq "-n") { $gcnt = 0+$ARGV[++$n]; next; }
if($ARGV[$n] eq "-S") { $soff = 0+$ARGV[++$n]; next; }
if($ARGV[$n] eq "-B") { $fbad = 0; next; }
if($ARGV[$n] eq "+B") { $fbad = 1; next; }
if($ARGV[$n] eq "-F") { $ffile = 0; next; }
if($ARGV[$n] eq "+F") { $ffile = 1; next; }
if($ARGV[$n] eq "-G") { $fgen = 0; $gcnt = 0; next; }
if($ARGV[$n] eq "+G") { $fgen = 1; next; }
if($ARGV[$n] eq "+Z") { $zoom = 1; next; }
if($ARGV[$n] eq "-Z") { $zoom = 0; next; }
if($ARGV[$n] eq "+R") { $rflg = 1; next; }
if($ARGV[$n] eq "-R") { $rflg = 0; next; }
if($ARGV[$n] eq "+I") { $fint = 1; next; }
if($ARGV[$n] eq "-I") { $fint = 0; next; }
if($ARGV[$n] eq "-z") { sq_tst($ARGV[++$n]); exit; }
printf "\nUnknown option '%s', try '-h' for valid options\n\n", $ARGV[$n];
die("Bad command-line options");
}
sub rpe() {
my $n = ""; my $c=0; local $_;
foreach(@l) {
if(/^\s*[\d.]\s*[\d.]\s*[\d.]\s*\|\s*[\d.]\s*[\d.]\s*[\d.]\s*\|\s*[\d.]\s*[\d.]\s*[\d.]\s*$/) {
s/[^.\d]//g;s/0/./g; $n = $n . $_;
}
};
return $n;
}
sub read_proc($$) {
my $s; my $pid; my $ret; my $file=""; my $wfile=""; my $e = "";
$stkc = -1; $stkw = -1;
if($_[0] eq 'G') {
print "--------- Generating (#" . $_[1] . ") ---------\n";
$pid = open2($file, $wfile, $gcmd,$_[1]);
} elsif($_[0] eq 'S') {
print "--------------- Solving... ---------------\n";
$pid = open2($file, $wfile, $scmd);
print $wfile $_[1];
} elsif($_[0] eq 'U') {
print "--------------- Solving... ---------------\n";
$pid = open2($file, $wfile, $scmd,'U');
print $wfile $_[1];
} else {
die("Internal error: bad input to read_proc()");
}
local @l = ( ); my $n = 0;
while($_=<$file>) {
push(@l, $_); print "> " . $_ if($vflg);
$e = $1 if(/^(!!!.*)$/);
($stkc = $1+0, $stkw = $2+0) if(/\(stk (\d+) (\d+)\)$/);
}
# local @l = <$file>;
close $file; close $wfile;
waitpid $pid, 0;
if($?) {
return $e if($e); return "ret=$?";
}; $s = rpe(); return $s;
}
sub read_file($) {
my $s;
open FILE,"<",$_[0]; local @l = <FILE>; $s = rpe();
close FILE; return $s;
}
sub squish($) {
my $n = 0; my $c; my $bc = 0; my $dc = 0; my $s = $_[0];
my $os = "#";
while($s ne "") {
$c = substr $s, 0, 1; $s = substr $s, 1;
if($c eq "." || $c eq "0") {
$dc++; if($dc==7||$s eq "") {
$n |= (($dc==1?0:$dc+8)<<$bc); $bc += 4; $dc = 0;
}
} else {
if($dc) {
$n |= (($dc==1?0:$dc+8)<<$bc); $bc += 4; $dc = 0;
}
$n |= (($c)<<$bc); $bc += 4;
}
while($bc >= 6) {
$os .= substr $squstr, $n & 63, 1;
$n = $n >> 6; $bc -= 6;
}
}
$os .= substr $squstr, $n, 1 if($bc);
return $os;
}
sub unsq($) {
my $n = 0; my $bc = 0; my $os=""; my $i; my $s = $_[0]; my $j;
if('#' ne substr($s,0,1)) {
return $s if(81==length($s)); die("Bad compressed sudoku");
}; $s = substr $s,1;
while((length $os)<81) {
if($bc < 4) {
die("Compressed sudoku ends prrematurely") if($s eq "");
$i = index $squstr, substr($s, 0, 1); $s = substr($s,1);
die("Bad compressed sudoku") if($i == -1);
$n = ($i<<$bc) | $n; $bc +=6;
}
$bc -= 4; $i = $n & 15; $n = $n >> 4;
if($i < 10) {
$os .= ($i == 0?".":$i);
} else {
for($j=8;$j<$i;$j++) {$os .= '.';}
}
} return $os;
}
sub chksq($$) {
my $i = squish($_[0]); my $j = unsq($_[1]);
die("Squash check failed") if($i ne $_[1]);
die("Unsquash check failed") if($j ne $_[0]);
}
sub chk_fi($$) {
my $i; my $j; my $k = $_[1]; my $n= $_[0];
if($k) {
print "================== Inbuilt $n ==================\n";
$k = unsq($k);
} else {
print "================== File $n ==================\n";
$k = read_file("$n.sudoku");
}
die("*** Problem isn't even valid!") if(chk($k)==1);
print $k, "\n" if($vflg);
$i = read_proc('S', $k);
(length $i) == (81*$soff) or die("*** Failed!!!");
$i = substr $i,81*($soff-1),81;
die("*** Solution isn't even valid!") if(chk($i));
die("*** Solution doesn't fit the problem!") if(scmp($i,$k));
if(-f "$n.sol") {
$j = read_file("$n.sol");
die("*** 'Correct' solution isn't valid!") if(chk($j));
die("*** Mix-up - solution is for another problem!") if(scmp($j,$k));
($i eq $j) or die("*** Wrong answer!!!");
}
print "*** Correct answer\n";
}
sub chk_fail($$$$) {
my $i = $_[2]; my $e; my $n = $_[0]; my $c=$_[1]; my $o = $_[3];
print "================ Bad problem '$n' ================\n";
$i = unsq($i) if($i =~ /^#/);
$i = read_file("$n") unless(81 == length $i);
print $i . "\n" if($vflg);
die("*** Invalid file!") if(81 != length $i);
if($o eq 'I') {
die("*** Internal error - chk() passed invalid sudoku!")
if(chk($i)!=1);
}
$o = 'S' if($o ne 'U');
$e = read_proc($o, $i);
if($c) {
print "Expected '" . $c . "' got '" . $e . "'\n";
} else { return 2 unless((length $c) == 81);
return 0;
print "Got '" . $e . "'\n";
}
die("*** Didn't spot a bad problem!") if($e !~ /^!!! /);
die("*** Took too long to spot bad problem!") if($_[3] eq 'I' && $stkw);
die("*** Failed test!") if($c ne "" && $c ne $e);
print "*** Detected bad sudoku successfully\n";
}
sub genrand($$) {
my $i; my $j; my $k; my $s = $_[0]; my $c = $_[1];
if($s) {
print "================== #$s ==================\n";
} else {
print "================== Random ==================\n";
$s = int(rand(999999999)) unless($s);
}
$i = read_proc('G', $s);
(length $i) == (81*3) or die("*** Failed!!!");
$j = substr $i,81,81;
$k = substr $i,81*2,81;
print $k . "\n" . $j . "\n" if($vflg);
die("*** Problem isn't even valid!") if(chk($k)!=2);
die("*** 'Correct' solution isn't!") if(chk($j));
die("*** Solution doesn't fit the problem!") if(scmp($j,$k));
print "*** Generated problem OK\n";
$c = unsq($c) if($c);
if($c && ($c ne $k)) {
if($rflg) {
print "\n Sudoku generated was valid, but not the expected one.\n",
" This probably isn't serious, and may not even be an error.\n",
" To ignore this, add the -R option to the command line.\n\n";
die("*** Not expected sudoku!")
} else {
print "*** Not expected sudoku, but -R specified; ignoring\n";
}
}
$i = read_proc('S', $k);
(length $i) == (81*2) or die("*** Failed!!!");
$i = substr $i,81,81;
print $i . "\n" . $j . "\n" if($vflg);
($i eq $j) or die("*** Wrong answer!!!");
print "*** Correct answer\n";
}
sub scmp($$) {
my ($i,$a,$b);
for($i=0;$i<81;$i++) {
$a = substr $_[0], $i, 1;
$b = substr $_[1], $i, 1;
return 1 unless($a eq $b || $a eq "." || $b eq ".");
}; return 0;
}
sub chk($) {
my @a; my $n; my $i; my @v; my $c = 0;
for($n=0;$n<81;$n++) { $v[$n] = gi($_[0], $n); $c++ if($v[$n]); }
if($zoom) {
return 2 unless($c == 81);
return 0;
}
for($n=0;$n<81;$n++) { $a[$n] = 0; }
for($n=0;$n<81;$n++) {
next unless $v[$n];
$i = int($n/9)*9 + $v[$n]-1;
if($a[$i]) {
print "row ". int($n/9) . " many " . ${$v[$i]} . " \n";
return 1;
}; $a[$i] = 1;
}
for($n=0;$n<81;$n++) { $a[$n] = 0; }
for($n=0;$n<81;$n++) {
next unless $v[$n];
$i = ($n % 9)*9 + $v[$n]-1;
if($a[$i]) {
print "col ". (($n % 9)+1) . " many " . ${$v[$i]} . " \n";
return 1;
}; $a[$i] = 1;
}
for($n=0;$n<81;$n++) { $a[$n] = 0; }
for($n=0;$n<81;$n++) {
next unless $v[$n];
$i = ( int(($n % 9)/3)+int($n/27)*3 )*9 + $v[$n]-1;
if($a[$i]) {
print "box ". (int(($n % 9)/3)+int($n/27)*3+1) . " many " . ${$v[$i]} . " \n";
return 1;
}; $a[$i] = 1;
}
return 2 unless($c == 81);
return 0;
}
sub gi($$) {
my $n = substr $_[0], $_[1], 1;
$n = 0 if($n eq "."); $n = $n + 0;
return $n;
}
srand;
if(!$zoom) {
print "================ Unsquash Test ==============\n";
chksq(".............9.........1.............4..1..1....................2.."
. "...1..........", "#vnvGvTaox.u0xv");
chksq("........2.....5.3..58..7...326....158...........362..8..7...4.....5"
. "1....6...841..", "#PIdBjWoe7IGHF,8Yii6tUXBbLShC");
print "*** Passed\n"
}
if($fint) {
chk_fi("blank","#.......z");
chk_fi("tough1","#PIdBjWoe7IGHF,8Yii6tUXBbLShC");
chk_fi("insane1","#KxlV7Jds4.WOa53QQBCEEgz.gF");
chk_fi("insane2","#yTuoJQgMACknQkyi6AGEQJasobJMfpJ");
chk_fi("insane3","#LxVHGkHPvBCEEU7N697cyvBMLBpC");
chk_fi("insane4","#rAZf9MeZQ9QyjVAt2hst0SgUIc5iM");
chk_fi("insane5","#t0BU2SlN9oHkAVu9QqFjHIw4ECSRM");
chk_fi("wikipedia","#boHplm6Iqdaqkiu0hnapkejejKqpWp0C");
}
if($ffile) { foreach(glob("*.sudoku")) {
chk_fi($1,"") if(/^(.+)\.sudoku$/);
} }
if($fbad) {
chk_fail("row","!!! row 5","#vnvGvTaox.u0xv",'I');
chk_fail("col","!!! col 5","#vnvGvTa8.Gt0xv",'I');
chk_fail("box","!!! box 5","#vnvGe4kG..q0xv",'I');
chk_fail("tele13-mang.bad","","",'S') if(-f "tele13-mang.bad");
chk_fail("unique",'',"#.XwoFq3OixRhPPmooeL1Vw2iUo",'U')
}
if($fgen) {
genrand(951464,"#axiBBIPgN1RPQCEc4rDECkbYqome7A");
genrand(975900,"#GCnOKdlh.7BkvWCQwh.WcqBEoakC");
genrand(168996,"#tdjO0ahA3LbsmOg55K3G1wIY3Ses");
genrand(250762,"#s8GCxADk.WnpFq2KawIk6cVTu4HA");
genrand(909990524,"#t0BU2SlN9oHkAVu9QqFjHIw4ECSRM");
genrand(105761662,"#LxVHGkHPvBCEEU7N697cyvBMLBpC");
genrand(100440625,"#yTuoJQgMACknQkyi6AGEQJasobJMfpJ");
genrand(957749705,"#Q0GnEIAu1OEyHLaU6kXQeCy8e9G");
genrand(914809978,"#NCDJw9bt5RjGijAt2WhbN,EkQcAC");
genrand(774849286,"#soDgbcqF.D3a1mTiCHlBBkIQa,7Z0C");
genrand(862977530,"#xvTUcBJBnwWtHc0i6oyGM5jeYnrQK");
genrand(103980293,"#oKadABTt4vpO0.nGixnGQpEcashWmo");
genrand(122255857,"#34lWbkaAkBzr2rhelmblAyCEnS68G");
genrand(596684993,"#cB2DhAJcMSxiANgo1sBYJfKCpV.vko");
}
for($n = 0; $n<$gcnt; $n++) {
genrand(0,"");
}
print "\n######### All tests passed! #########\n\n";
+11
View File
@@ -0,0 +1,11 @@
. . . | . . . | . . 2
. . . | . . 5 | . 3 .
. 5 8 | . . 7 | . . .
------+-------+------
3 2 6 | . . . | . 1 5
8 . . | . . . | . . .
. . . | 3 6 2 | . . 8
------+-------+------
. . 7 | . . . | 4 . .
. . . | 5 1 . | . . .
6 . . | . 8 4 | 1 . .
+15
View File
@@ -0,0 +1,15 @@
From Wikipedia article "Sudoku":
. . . | 1 . . | 7 4 .
. 5 . | . 9 . | . 3 2
. . 6 | 7 . . | 9 . .
------+-------+------
4 . . | 8 . . | . . .
. 2 . | . . . | . 1 .
. . . | . . 9 | . . 5
------+-------+------
. . 4 | . . 7 | 3 . .
7 3 . | . 2 . | . 6 .
. 6 5 | . . 4 | . . .
http://en.wikipedia.org/wiki/Sudoku
+15
View File
@@ -0,0 +1,15 @@
build: anon
clean:
clobber:
-rm anon
anon: anon.c
${CC} ${CFLAGS} ${LDFLAGS} $< -o $@
alt:
data:
+178
View File
@@ -0,0 +1,178 @@
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
/* Defines */
#ifndef NO_STTY
#define S1 system("stty cbreak -echo")||
#define S2 system("stty sane")||
#else
#define S1
#define S2
#endif
#define A(i) (((q*)R(8))[i])
#define B p(b)
#define C p(&a)
#define H(i) sscanf(A(i),"%ld",&R(i+11))&0 ||
#define P q*
#define M(a,b) main((i)(a),(P)(b))
#define p(x) ((i*)(x))
#define D T(B-C,C-B)
#define T(x,y) ((a&1)*((i)(x))+(~a&1)*((i)(y)))
#define R(x) (*(B+x))
#define q char*
#define Q(x) ((q)(x))
#define W(x,y) ((B[x]=(i)(y))&0)||
#define BS (w*l*h)
#define do(x,y) (a-x||y)&&
#define f(x) M(x,b)
#define if(p,q,r,s) ((p)&&!(q)||(s))&&(r)||
#define i long
#define I (int)
#define while(x,y,z) do(x, y && !(z) && f(a))
#define for(s,i,x,y,z,Z) W(i,x)f(s)||Z) && while(s,R(i)-y,z||W(i,R(i)+1)0)(s
#define return return do
#define w R(12)
#define l R(13)
#define h R(14)
#define X(i) (R(i)%w)
#define Y(i) ((R(i)%(w*l))/w)
#define Z(i) (R(i)/(w*l))
#define pr !printf
#define switch(x) (W(32+R(15),R(32+x+R(15))) W(32+x+R(15),0) (B[15]+=x)|1)
#define case(k,x,y) R(a)==k && x && switch(y) && f(13)||
#define TL(i) R(32+R(i))
/* Main program */
int main(int a, P b) {
return(1>>1^1, M(6+!!M(5,C),C))
do(
13,
pr("\x1b[;H")||
for(14,4,0,BS,!X(4)&&pr(
"%*s",
I(l-Y(4)),
""
)
||
if(TL(4),pr(
"%*ld",I
R(31),
TL(4)),0,
pr("%*.*s",I
R(31),
I R(31),"#####")
)
if(X(4)==w-1 , pr("\n"),0 , pr("%*s", I(l+1), "")) (
(R(4)+1)%(w*l)==0 && l>1)&&
pr("\n"),0))
do(
1&~1,
pr("Syntax: %s <x> <y> [<z>]\n", b[0])||f(15)
)((a&~1)
-6||D>>12
&&(*(p(T(C,b))+8)=*p(Q(b)+(Q(&b)-Q(C)))
)
&&(*(p(T(C,b))+9) = *p(b))&&M(
8,T(C,b))
||
f( a) )&&do(
8,
if(R(9)&1,H(1)H(
2 ) 0,W(14,
l)W(13,1)0,
H(1
)
H(2)
H(3)
0)(srand(time(0)),0
) ||for(9,4, 0,BS, f(16)
|| W(R(4)+32,R(0))!R(0) && W(15,R(4) )0,
W(
31,
snprintf(A(0),1,"%ld",BS))
S1 pr("\x1b[2J") ||
f(13)
||
f(18) ||
f(15)
))
do(
16,W(0,rand()%BS
) W(1,0)
for(17, 5, 0,R(4),! (
TL(
5)-R(0))&&! (
W(1,1)
W(5,R(4)-1)
0),R(1)&&f(16))
)
do(
18,W(0,0
) for(19,4,0,BS, TL(4)-(R(4)+1)
%BS&& (
W(0,1)
W(4,BS-1
) 0)||0,!R(0) &&
pr(
"You win!\n"
)
||
R(0)&& (
W(a,getchar())
case('i',
0<Z(15),
-w*l)
case('j',
0<X(15),
-1)
case('k',
Z(15)<h-1,
w*l)
case('l',
X(15)<w-1,
1)
case('n',
Y(15)<l-1,
w)
case('o',
0<Y(15),-w
)
R(a)=='q'&&!
pr(
"You lose :-)\n"
)
&&f(15)||f(a))
)
)
do(
15,S2
(exit(0),a)
) (a-5||C<p(b));
}
+444
View File
@@ -0,0 +1,444 @@
# Best 3D puzzle
Anonymous
## Judges' comments
Taking the 4x4 board with 15 tiles to a whole new level, this entry
takes this puzzle to a whole new dimension! While you puzzle out
this puzzle, we invite you to take a good LONG look how and WHY
main is recursively called and how the run-time stack is used.
## To build
cc -o anon anon.c
Or, if the above does not work
cc -DNO_STTY -o anon anon.c
## To run
anon 4 4
anon 3 3 3
## Author's comments
### ABOUT THE GAME ITSELF
Remember Sam Loyd's Fifteen Puzzle? It consists of a 4x4 board with 15 tiles
numbered 1 to 15, and an empty spot. The goal of the game is to slide the
tiles around without lifting them off the board, so that they become sorted.
Well, that was then. This program is the 21st century version of the Fifteen
Puzzle: not only does it allow arbitrary board sizes, it also supports _3D_
boards! The tiles are numbered from 1 to N, where N is one less the number of
spaces on the board, and the goal is to rearrange them so that they appear
sorted in the order they appear on the screen.
The program takes 2 or 3 arguments, specifying the dimensions of the board.
For example, to play the original version of the Fifteen Puzzle:
anon 4 4
To play in a 3D board, do something like this:
anon 3 3 3
**[WARNING: do NOT run the program with more than 3 command-line arguments.
This will trigger a bug that will cause it to crash or do something strange.
:-)]**
Also, resist the temptation to create very large puzzles. The program does not
attempt to resize your terminal for you, and will produce confusing output. It
may also crash on you if you insist on running it with excessively large board
dimensions. :-) (10x10x10 is considered a safe upper limit.)
The empty space on the board is represented by a space filled with '#'
characters instead of digits. To slide the tiles around, use the following
keys:
i | Slide the tile above the current empty space downwards.
j | Slide the tile to the left of the current empty space to the right.
k | Slide the tile below the current empty space upwards.
l | Slide the tile to the right of the current empty space to the left.
o | Slide the tile behind the current empty space forwards.
n | Slide the tile in front of the current empty space backwards.
To quit the game:
q | Quit the game.
Note that, for example, sliding the tile above the current empty spot
downwards will fill up the empty spot, and create a new empty spot above where
the current empty spot was. Hence, you could think of the movement keys in
terms of how they effectively "move" the empty spot:
i | Move empty spot up
j | Move empty spot left
k | Move empty spot down
l | Move empty spot right
n | Move empty spot forwards
o | Move empty spot backwards
**NOTE:** as a measure of alleviating counter-productivity due to addiction to
this game, particularly for those hardcore gamers who insist on solving a
10x10x10 puzzle during work hours, and also to give an upper bound to user
frustration when the program generates an impossible puzzle (which it does
roughly half the time, just to hook you), the program will, after a very large
number of moves (which is system-specific) terminate itself by forcefully
destroying its own runtime stack. This will result in a core dump and/or an
abnormal termination message; but this is a feature, not a bug! :-)
### COMPILE NOTES
This program complies with ANSI/C99. It uses ANSI terminal control sequences,
and so requires a terminal that understands ANSI sequences, such as vt100 or
xterm.
Some compilers may emit lots of warnings about how things ought to be
parenthesized (e.g. `gcc -Wall`). This is deliberate, since if everything were
parenthesized "properly" the program would fail to work. It (ab)uses C
operator precedence to accomplish some cool hacks. :-) However, there are no
compiler errors. I have tested this with `gcc -pedantic -std=c99`.
The program also uses `stty cbreak`. If this breaks on your system, compile it
with -DNO_STTY. The game interface will be a bit annoying (you will need to
hit enter after every key), but it works.
The game requires lots of space on the runtime stack space due to deep
recursion, among other things. :-)
See spoilers below for more notes about portability.
### ABOUT THE CODE
Clearly, the author is very, very confused. Although he has broken up the file
into sections labelled with helpful headings, and although he has left ample
whitespace between all those #define's to make them easier to read, :-) and
although he has helpfully formatted the code with beautiful indentation,
something is clearly very, very wrong.
In fact, the closer you look at this code, the more you realize something is
horribly wrong with it. For example, why is it that the first statement in
main() is a return? What do all those nested do-loops do? (pun intended) Why
is the first statement inside the first do-loop a mere integer literal? Why
are there such strange statements, like that empty string on line 64, or that
isolated || on line 67?
But wait... why aren't any statements terminated by semicolons? Why is there
only ONE semicolon in the entire program?! Why is the author opening nested
blocks by such strange things as || and (, and closing them by || and ))? The
for-loop isn't a for-loop! The do-loop isn't a do-loop! Or... are they? Well,
the for-loop is defined in terms of a while-loop. But wait, the while loop is
defined in terms of the do-loop. And the do-loop is defined in terms of ...
Huh???
And that switch statement toward the end of the program... wait a minute, that's
not a switch statement! Why is a case defined in terms of a switch statement?!
And that initial return isn't a return! Well, it is... but not what you might
think!
Let's see if it all makes sense after we run it through CPP...
Uh oh. The result looks like the diseased imagination of a mind more confused
than the one who wrote the original code. Unfortunately, unless you're a Lisp
expert, it is probably easier to understand the program in its original form.
(And even then.) But that's just so, so wrong...
The entire program consists of a single expression, returned from main().
There are no if-statements, no for-loops or any looping or control constructs
besides the 'return', in spite of the misleading appearance of the original
source. :) Yes I know, this has been attempted before, using ?: and the bad
old comma operator. BUT this program does NOT use the ?: operator, and there
are only TWO comma operators in the entire program--and they are only there
because srand() and exit() return void.
The entire program consists of a single boolean expression returned from
main(). Looping is achieved by recursion, of course, and branching is achieved
by exploiting short-circuit evaluation of boolean expressions. `:-)`
But this is not all.
It is comprehensible that the program can achieve branching and looping using
only boolean expressions and recursion. But HOW does the program STORE DATA???
There are no variables of any kind in the program except for the two arguments
to `main()`. There are certainly no arrays declared anywhere. The program does
not call any memory allocation routines, nor any function that indirectly
returns allocated memory. Yet it happily looks up array references without
crashing. How??
One might be tempted to think that this program would be highly non-portable
because of such insane hacks. However, it has been tested and proven to work
on the following architectures:
* i386/linux
* sparc/solaris
* parisc64/linux
* arm/linux
* s390/linux
* mips/linux
* m68k/linux
* ia64/linux
* sparc64/linux
It probably will also compile and work on many (all?) other *nix platforms as
well. How does it achieve this incredible feat?
### SPOILER
.
.
.
.
.
.
.
.
.
.
.
(Read the following only if you give up figuring it out `:-)`)
.
.
.
.
.
.
.
.
.
#### The Evil Hack
The program (ab)uses an implicit assumption underlying practically all
architectures, and that is that parameters to C functions are implicit local
variables allocated on the runtime stack. This runtime stack is a contiguous
section of memory, and therefore, after N recursive calls of main() to itself,
there is enough room on the stack to store whatever the program desires, so
long as it does not exceed the maximum stack size.
(Theoretically, the runtime stack doesn't **have** to be contiguous… but all
current architectures that are worth consideration make this assumption. I
submit that this implies this program is 100% portable, even though
theoretically it shouldn't even work in the first place.) `:-)`
There are two types of architectures the program must handle: those that
allocate the stack top-down, and those that allocate the stack bottom-up. The
program correctly detects this at run-time, and adjusts itself accordingly.
:-) (It is a simple matter of testing if the address of argc in a recursive
call is greater or less than in the parent call.)
To avoid having to handle issues of int sizes, memory alignment, what exactly
is on the stack between successive locations of argc, etc., the program
(ab)uses the fact that argc must necessarily be allocated on an aligned
address, and therefore, the range of memory between two argc's is aligned, and
therefore safe to use as an array of longs.[*] The program also compares the
pointers as (long*) pointers, so that it will not have to deal with mapping
bytes to larger types. The initial memory allocation is done by recursively
calling main() until there is enough space on the stack (the exact number of
recursive calls is, of course, architecture-dependent).
[*] long was chosen instead of int, in order to skirt around pointer-size
issues on architectures like ia64. It really can be made anything large enough
to hold both ints and pointers. `:-)`
After the stack is deemed to have grown deep enough to be a sufficiently long
array (pun intended), the program begins its real code. It uses argc to keep
track of what it's supposed to be doing (since main() is the only function),
and argv to point to the base of this array (which is computed differently
based on how the architecture allocates the stack). Since this fills up the
only two variables in the program, everything else is stored in the MASS [**]
array.
[**] for "Memory Allocated by Stack Smashing" `:-)`
Note that from this point on, all bets are off as to what the contents of the
runtime stack are below the current recursive call to main(). We are
overwriting frame pointers, return addresses, etc., with data. Hence, the
program must never return from this call, otherwise it will crash horribly.
That's why I had to call exit() even though it meant I can no longer claim the
program doesn't need the comma operator. :-) (I was going to skirt around the
issue by indirectly calling exit(), such as via bsearch() or raise(), but I
was getting too close to the size limit.)
#### Some notes about the macros
In spite of the frightening appearance, it is probably easiest to understand
the code in its original form. (Don't even try running 'indent' on it: on my
system it chokes and complains about nesting errors.)
Most of the #define's are just to keep the code size down, due to the abusive
amounts of type casting employed. The others define a bizarre "programming
language" (in the crudest, most twisted sense of the word) that the author
used to write this mess.
R(i) and W(i,j) are macros to read/write the i'th position of the MASS.
A(i) retrieves the i'th command-line argument. This is slightly tricky,
because by the time the MASS is setup, we no longer have access to the
original values of argc and argv. So what is done is that the initial memory
allocation code will save argc and argv into positions 8 and 9 in the MASS
after the allocation. It does this by using argv, which at that time contains
a pointer to the top-level argc, to compute the location of the top-level
argv. This is done before the rest of the MASS is used, since otherwise they
may be overwritten.
do(x,y) has nothing to do with do-loops. `:-)` It defines a "state" in main(),
essentially, what to do when main() is called with argc containing a
particular value. (This is why the user must never run the program with more
than 3 arguments. :-) The state number is x, and y is the code. The program's
boolean expression consists of a number of states &&'d together. Within each
state, it is assumed that statements are separated by ||. All statements are
assumed to evaluate to false. This makes it easy to write conditional
statements: "if (a) { b } ..." can simply be written "a && b || ...". All
states created by do(x,y) are assumed to evaluate to false. There is only 1
state which can return true or false: state 5, a "manually-implemented" state
which determines whether the system uses top-down or bottom-up stack
allocation. It's the only state that needs to return a value from the boolean
expression, since once the MASS is initialized any return value can simply be
stored in a well-known location in the MASS.
if(p,q,r,s) is, in fact, an if-statement. `:-)` It is equivalent to:
if (p) { q; r } else {s}
Why are q and r split up? Because it's cleaner (in whatever twisted sense of
the word that can be applied to an IOCCC entry) to implement using boolean
expressions. Keep in mind that all statements are assumed to evaluate to
false. The proof that this macro in fact implements an if-then-else construct
is left as an exercise for the reader.
while(x,y,z) is actually a while-loop after all. `:-)` It implements the loop
using, of course, recursive calls to main(). However, this macro doesn't
actually run a while loop; it implements the loop in the state numbered x. It
is used for defining a while loop, which can then be called from another state
using f(x). (The reason we can't directly implement a while-loop inside
another state ought to be clear: we can't recursively call main() to enter
into the middle of a state.)
However, it _is_ possible to implement a for-loop directly inside a state! The
for(s,i,x,y,z,Z) macro does exactly this. Well, actually, technically speaking
this macro can only be used as the last thing in a state, because it secretly
closes the current state and opens a new one behind the programmer's back.
:-) Its intended usage is this: s is the state number for the loop body, and i
is the index variable (well, the index into the MASS of the index variable); x
and y-1 define the starting and ending values of i, and z is the loop body. Z
is the post-loop code in the current state. For example:
for(s,i, 0, 10,
some_code ,
other_code)
is equivalent to:
for (i=0; i&lt;10; i++) {
some_code;
}
other_code;
Note the "wrong" indentation in the former: the author prefers to write it
that way, since the analogy to the usual for-loop is clearer. This is why it's
easier to understand the pre-CPP code, since after CPP, the macro reshuffles
some_code after other_code so that it can close the current state and define
the one containing the loop body. (Have I told you that the author of this
program is horribly, horribly, confused? :-) This confusion also shows up in
the superficial appearance of the program, which heavily suffers from wrong
indentation.)
In spite of all appearances, switch() really is just a shorthand macro for
reducing code size. The evil choice of macro name is just to instill more
confusion into the would-be decipherer of this entry. :-) After all, case()
really _is_ the equivalent of a case statement, implemented using &&, and
conveniently encapsulating code common to the cases in the only switch-
statement in the program, which is the code that decides what to do with a
keypress. What could be more fun than to define such a case in terms of a
switch? :-)
Finally, for those who give up deciphering this horribly confused code, here
are the mappings of various locations of the MASS to their usage in the
program, and what the various state numbers are meant to do:
#### MASS usage map
0 | Function return value
1 | Function argument 1
2 | Function argument 2
3 | Function argument 3
4 | Scratch register 1
5 | Scratch register 2
6 | Scratch register 3
7 | Scratch register 4
8 | Value of original argv :-)
9 | Value of original argc :-)
11 | Zero register (always set to 0)
12 | Width of board
13 | Length of board
14 | Height of board
15 | Current position of hole
16 | Random seed for rand_r()
18 | Scratch register used by state 18 :-)
31 | field width for printing tiles
32 | Start of board data
(**CAVEAT:** not all of these mappings ended up in the final version of the
program, mainly due to size limitations which entailed the trimming off of a
lot of neat features in the game. It is left as an exercise for the reader to
figure out which of these are actually used.)
Note that argv and argc necessarily needs to stay away from lower indices of
the MASS, because otherwise they may overwrite their original values when the
memory allocation code saves them. Index 8 is deemed "safe enough". (It seems
to be on all tested architectures.)
#### State number assignments
1 | showhelp
2 | showhelp
3 | is 2D: start init
4 | is 3D: start init
5 | find allocation type
6 | MASS init, bottom-up
7 | MASS init, top-down
8 | main program
9 | generate() outer loop
13 | render()
14 | render() loop
15 | exit(0)
16 | pick a tile that hasn't occurred yet
17 | inner loop of 16.
18 | main loop
19 | checkwin() loop
Note that some of the manually-implemented states (those not implemented by
do()) respond to multiple state numbers. Also note that states 1-4
conveniently correspond to what the program should do when 1-4 arguments are
given at the command-line. :-)
The original intention was to include a parity-checking routine in the game so
that it will always generate a solvable game. However, size limits
necessitated the removal of this code. And besides, the game is more addictive
when it's sometimes unsolvable. Especially when it taunts the user with a
smiley. :-)
+18
View File
@@ -0,0 +1,18 @@
build: boutines
clean:
clobber:
-rm boutines
boutines: boutines.c
${CC} ${CFLAGS} ${LDFLAGS} $< -o $@
alt: boutines.orig
boutines.orig: boutines.orig.c
${CC} ${CFLAGS} ${LDFLAGS} $< -o $@
data:
Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

+73
View File
@@ -0,0 +1,73 @@
#define F 0xF
#define U 512
#define std(x,y) (*x)(const char *,...)=y##f
#define str(l,e,x) l e,l x
#define mx(p,v1,v2) p[3]=v2,p[1]=v1,p[2]=v2,*p=v1
#define vi(n) q+2,n,q+3,n
#define rt return
#include <stdlib.h>
#include <stdio.h>
typedef double n; n *d,*b,*f; typedef unsigned char c;
char _[ ]=" <?%s version=\"1.0\"?>\n<%s %s=\"%d\" %s=\"%d\">\n", q [7][7] = {
"ivory","black","width","height","text"};int v,std(i,scan),std(o,print);
int cc(str(const void*,x,y))
{
rt(*(n*)x>*(n*)y)-(*(n*)x<*(n*)y);
}
n t(n f,n g,str(n*,x,y))
{
f=*x++-f,g=g-*x,*y=f*f;rt *y+g*g;
}
c*ln(n*p)
{
c*f=((c*)(d+2*(2+v))+2*(p-d)); while(!*f) mx(f,rand(),rand());rt f;
}
n*put(str(n*,f,l),n z)
{
int r=(l-f)/4,p=*(f+(r*=2))<z;rt r>0?put(f+p*r,p?l:f+r,z):f;
}
n*g(n u,n w)
{
n y=u/(U-1),*s=put(d,d+v+2,y),z=w/(U-1),k,l=t(y,z,s,&k),
m=l,*r[4],g[4],*f; c p; for(mx(r,s,0),mx(g,k,l);
p=*(1+g)<*g,(m>*(g+1))+(*g<m);s=*f<m?m=*f,*(r+p):s)*(f=g+p+2)=t
(y,z,*(r+p)+=p?-2:2,p+g);rt s;
}
c*a(str(n*,x,r))
{
n*y; int i=0,j=0,k=0,u;for(u=0;y=g(*x+u/4/4.,*r+u%4/4.),16>u;++u)
i+=*ln(y),j+=*(1+ln(y)),k+=*(ln(y)+2);
*_=i/u,*(1+_)=j/u,*(_+2)=k/u;rt(c*)_;
}
void tr(n x,n y,n i)
{
c*h,w;n*m=g(y,i); for(w=4*(x<2);++w<4&&m==g(w/2*x+y,i+w%2*x););
for(w=4*(w>3&&(h=x>1?ln(m):a(&y,&i))&&o("<rect style=\"fill:rgb(%d,%d,%d\
);\" x=\"%f\" y=\"%f\" %s=\"%f\" %s=\"%f\"/>\n",*h,*(1+h),*(2+h),str(F+,
y,i),vi(x))),x/=2;x>0&&w<4;++w)tr(x,y+w/2*x,w%2*x+i);
}
int main()
{
long k,r=1e6,h;d=calloc(r,k=sizeof(n)),f=d+r,b=d;
while(0<(h=i("%lf",b)))*--f=*b++;v=b-d;if
(!h+v%2+!v&&(r=0x630C65u)){o("\n0x7");while(r-->0)o("F");rt -1;}
mx((d+v),-r,r);qsort(d,2+(v/=2),2*k,cc);
tr(U,0&o(4+_,"xml","svg",vi(2*F+U)),0);
for(b=d-1+r,k=0;r=1,v>k++;b-=2)
str(o("<%s x=\"%f\" y=\"%f\" fill=\"%s\" %s-anchor=\"end\">%d</%s>\n",
4+q,str(F+r/2.-5+U**,b,(b-1)),q+r,q+4,k+!o
("<circle style=\"fill:%s;\" cx=\"%f\" cy=\"%f\" r=\"3\"/>\n",
r+q,str(F+r/4.+U**,b,(b-1))),4+q),&&r--,);
free(d);rt o("</svg>\n")-7;
}
+75
View File
@@ -0,0 +1,75 @@
#define F 0xF
#define U 512
#define std(x,y) (*x)(const char *,...)=y##f
#define str(l,e,x) l##e,l##x
#define mx(p,v1,v2) p[3]=v2,p[1]=v1,p[2]=v2,*p=v1
#define mov(x,y) y=*f<m?x:y
#define vi(n) q+2,n,q+3,n
#define rt return
#include <stdlib.h>
#include <stdio.h>
typedef float n; n *d,*b,*f; typedef unsigned char c;
char _[ ]=" <?%s version=\"1.0\"?>\n<%s %s=\"%d\" %s=\"%d\">\n", q [7][7] = {
"ivory\0","black\0","width\0","height\0","text"};int v,std(i,scan),std(o,print);
int cc(str(const void*,x,y))
{
rt(*(n*)x>*(n*)y)-(*(n*)x<*(n*)y);
}
n t(n f,n g,str(n*,x,y))
{
f=*x++-f,g=g-*x,*y=f*f;rt *y+g*g;
}
c*ln(n*p)
{
c*f=((c*)(d+2*(2+v))+2*(p-d)); while(!*f) mx(f,rand(),rand());rt f;
}
n*put(str(n*,f,l),n z)
{
int r=(l-f)/4,p=*(f+(r*=2))<z;rt r>0?put(f+p*r,p?l:f+r,z):f;
}
n*g(n u,n w)
{
n y=(.5+u)/U, *s=put(d,d+v+2,y),z=(w+.5)/U,k,l=t(y,z,s,&k),
m=l,*r[4],g[4],*f; c p; for(mx(r,s,0),mx(g,k,l);
p=*(1+g)<*g,(m>*(g+1))+(*g<m);mov(*(r+p),s),mov(*f,m))*(f=g+p+2)=t
(y,z,*(r+p)+=p?-2:2,p+g);rt s;
}
c*a(str(n*,x,r))
{
n*y; int i=0,j=0,k=0,u;for(u=0;y=g(*x+u/4/4.,*r+u%4/4.),16>u;++u)
i+=*ln(y),j+=*(1+ln(y)),k+=*(ln(y)+2);
*_=i/u,*(1+_)=j/u,*(_+2)=k/u;rt(c*)_;
}
void tr(n x,n y,n i)
{
c*h,w;n*m=g(y,i); for(w=4*(x<=1);++w<4&&m==g(w/2*x+y,i+w%2*x););
w=4*(w>=4&&(h=x>1?ln(m):a(&y,&i))&&o
("<rect style=\"fill:rgb(%d,%d,%d);\" x=\"%f\" y=\"%f\" %s=\
\"%f\" %s=\"%f\"/>\n",*h,*(1+h),*(2+h),str(F+,y,i),vi(x)));
for(x/=2;x>0&&w<4;++w)tr(x,y+w/2*x,w%2*x+i);
}
int main()
{
long k,r=1e6,h;d=calloc(r,k=sizeof(n)),f=d+r,b=d;
while(0<(h=i("%f",b)))*--f=*b++;v=b-d;if
(!h+v%2+!v&&(r=0x630C65u)){o("\n0x7");while(r-->0)o("F");rt -1;}
mx((d+v),-r,r);qsort(d,2+(v/=2),2*k,cc);
tr(U,str(0,*o(4+_,"xml","svg",vi(2*F+U)),0));
for(b=d-1+r,k=0;v>k++;b-=2)for(r=1;0<=r;--r)
o("<%s x=\"%f\" y=\"%f\" fill=\"%s\" %s-anchor=\"end\">%d</%s>\n",
4+q,str(F+r/2.-5+U**,b,(b-1)),q+r,q+4,k+!o
("<circle style=\"fill:%s;\" cx=\"%f\" cy=\"%f\" r=\"3\"/>\n",
r+q,str(F+r/4.+U**,b,(b-1))),4+q);
free(d);rt o("</svg>\n")-7;
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

+130
View File
@@ -0,0 +1,130 @@
# Most superfluous output
Francois Boutines
Toulouse, France
francois.boutines@gmail.com
## Judges' Comments
### To build
cc -o boutines boutines.c
### To run
You will need an [SVG] viewer. Look here to find some [SVG Viewer Implementations].
[SVG]: http://www.w3.org/Graphics/SVG/
[SVG Viewer Implementations]: http://wiki.svg.org/Viewer_Implementations
The following will create an SVG file,
perl -e 'map{print rand," ",rand,"n";}(1..20);' | ./boutines > test.svg
Can you explain the author's remark "[generated files] are not as scalable as their name suggests"?
## Author's Comments
_In memory of my father Pierre Boutines-Vignard._
### Walkthrough
My program works as follows:
**Input**
> a list of 2D points in the unit square
**Output**
> a Voronoi diagram of the set as an [SVG] stream
This will possibly save a compressed SVG file and may be useful:
./boutines | gzip > result.svgz
Input consists of a list of floating points values separated by whitespaces
(ranging preferably in [0,1]). Alternating an horizontal coordinate, a
whitespace then the other coordinate (pointing downwards in the resulting
graph) and a newline will just go fine :
0 0
0 1
1 0
1 1
.5 .5
Strictly speaking, you have to provide a **set** of points. If there are
duplicates in the list, there is no guarantee on the one to be shown (in
addition their labels will overlap) in the resulting colored Voronoi diagram.
### Caution
This program might have been a lot shorter, but nearly impractical even for
medium sized datasets. On the other hand it could have been a lot faster, but
hard to qualify under the IOCCC size limit. So guess what I did a compromise
favoring innermost obfuscation, sacrificing sometimes speed and other tedious
factors.
Therefore this entry is limited to
> ![floor\bigg(\frac{10^6}{4\times(sizeof(double)+1)}-1\bigg)](eqn.png)
points and won't even be suitable for more than a few thousand : although
generated files do pass [W3C SVG Validator], and are highly compressible,
they are not as scalable as their name suggests… For serious applications
about Voronoi diagrams, see [Qhull], [CGAL] and the like : but you may
still encounter large output volumes (and have to handle some sort of clipping
in order to represent properly infinite regions of the diagram in SVG).
[W3C SVG Validator]: http://jiggles.w3.org/svgvalidator/
[Qhull]: http://www.qhull.org/
[CGAL]: http://www.cgal.org/
Beware, compilation may report warnings about precision loss, linting may be a
disaster, but the code should remain portable, and the output accurate enough
for most devices (including many inkjet printers). If you ever miss precision
on a particular dataset or peripheral, you may want to dive in and let U be
the next power of `__LINE__`.
Note : bad inputs will be sanctioned by the production of the 42nd Mersenne
prime (ie. 2^25964951 -1), memory will be kept.
### Why I think this code is Obfuscated ?
I'm quite divided on the subject because I wrote :
* clear SVG key words but complicated output statements
* no nested loops but loads of function calls
* easy recursion but no clear data struture
* easy maths but no use of math.h
* a single if
Be sure to check the antepenultimate line of code.
### Missing Features
**Color control**
> Cell colors are chosen randomly (with a questionable rejection scheme). It
might have been useful to input them along with sites coordinates, turning the
application into a puzzling graphics engine.
**Site labelling**
> The points are implicitly numbered in the order they were entered
(starting at one). This can be overridden however, via a simple XSL
transformation.
**Site radius**
> The site radius is hardwired in the code, I still wonder why I did not
design it as a function of the underlying cell's area (which can be averaged
for free) or at least a command line parameter. Same with the char set, the
viewport and potentially every SVG property.
## See Also
[Voronoi at Wikipedia](http://en.wikipedia.org/wiki/Voronoi_diagram),
[An Excerpt from The Algorithm Design Manual](http://www2.toki.or.id/book/AlgDesignManual/BOOK/BOOK4/NODE187.HTM),
[Voronoi and Art](http://www.snibbe.com/scott/bf)
## Example Output
> ![Voronoi diagram of two regular pentagon vertices](Voronoi.png)
+15
View File
@@ -0,0 +1,15 @@
build: chia
clean:
clobber:
-rm chia
chia: chia.c
${CC} ${CFLAGS} ${LDFLAGS} $< -o $@
alt:
data:
+82
View File
@@ -0,0 +1,82 @@
/*
* Sun's Java is often touted as being "portable", even though my code won't
* suddenly become uber-portable if it's in Java. Truth is, Java's one of
* the most ugly, slow, and straitjacketed languages ever. It's popular
* mainly because people hear the word "portable" and go "ewww".
*
* This program, then, is dedicated to bringing about the death of Java. We
* good coders have been oppressed for too long by the lame language
* decisions of pointy-haired bosses and academics who should know better.
* It's time we stand up against this junk, and bring back the fun in
* programming! Viva La Revolution!
*/
#define aSet c
#define BufferedReader(x)1
#define byte Y[I][_^1]?do(:):_&1?do(.):do(`):8;++y;}
#define class int N=0,_,O=328,l=192,y=4,Y[80][64]={0},I;struct
#define do(c)a(#c "\b")
#define err c,c
#define getAllStrings(x));q()
#define if(x)b(#x)
#define IOException
#define line c
#define main(a)b(char*x){write(1,"\033[",2),null}main()
#define new
#define null a(x);}a(char*x){write(1,x,strlen(x));try;try;try;try;
#define out c,c
#define println(x)c
#define private int d(int
#define public short c;}c;typedef int BufferedReader;char*F="JF>:>FB;;BII";
#define return {return
#define static f(x){N=(N+x)%6,y--?f(0),f(1),f(4),f(1):++Y[(I=O+N[F]-66)
#define String
#define System c
#define this if(D):1,O=I,I/=16,l<_/32?if(B):l>_/32?if(A):2,l=_,_/=16,byte
#define throws
#define toArray(x)c
#define try for(;--c.c;)
#define void /16][(_=l+N[6+F]-66)/16]?O/=16,l/=32,O<I/16?if(C):O>I/16?this
#define while(k)if(2J),if(7;21H),f(0),f(4),f(4),if(H),/*
import java.io.*;
import java.util.*;
/**
* A lame Java program.
* @author J. Random Worker
*/
class LameJavaApp
{
/** The infamous Long-Winded Signature From Hell. */
public static void main(String[] args)
throws IOException
{
/* Don't get me started on this. */
BufferedReader reader =
new BufferedReader(new FileReader(args[0]));
/* What, this long incantation just to print a string? */
System.err.println("Hello world!");
/* At least this is sane. */
String line;
while ((line = reader.readLine()) != null)
System.out.println(line.length());
}
/**
* Method with a needlessly long name.
* @param aSet a set (!)
*/
private String[] getAllStrings(Set<String> aSet)
{
/*
* This dance is needed even in J2SE 5, which has type
* templates. It was worse before that.
*/
return aSet.toArray(new String[0]);
}
}
+46
View File
@@ -0,0 +1,46 @@
# Most ambiguous language
V. Chia
Singapore
bi@mncw.tk
## Judges' comments
Have you had your morning cup of Java? You might want a
second cup before parsing this entry. And give your C
pre-processor a triple shot as it tries to handle parameters
for "stringification".
### To build
cc chia.c -o chia
### To run
chia
## Author's comments
Two things inspired this entry. First, there were the C programs which were
`#define`'d to look like Pascal or Visual Basic: the /bin/sh code from V7 Unix
(which reportedly was the motivation behind this contest!), the VAL Linker by
David Troendle, the 2000/primenum entry, ... Looking at these programs, I
thought, "hmm... if it's possible to make C code look like some weird cross
between Pascal, VB, and COBOL, then how about making C code look like some
other language?"
As chance would have it, I was writing some Java code at that time, and one of
my net.friends was also working on someone else's Java code. We both hated
Java; indeed, I hated Java so much that I was tired of hating it. Then I
remembered my earlier idea: "Of course! Why not write C code that looks like
Java? And poke fun at Java while I'm at it? All ye behold, as I turn anger
into action! PH34R MII!!!!!!!" And so, this entry was born. :-)
Besides carrying a revolutionary message in the comments, this entry also
draws a spiffy little Koch snowflake fractal on the screen, with the help of
ANSI escape sequences.
The code requires a preprocessor that can stomach all kinds of nonsense that
are passed as parameters to macros for stringification. GNU cpp handles such
things just fine, but certain broken preprocessors may decide to freak out
when they see macro parameters that don't look like C tokens.
+15
View File
@@ -0,0 +1,15 @@
build: giljade
clean:
clobber:
-rm giljade
giljade: giljade.c
${CC} ${CFLAGS} ${LDFLAGS} $< -o $@
alt:
data:
+49
View File
@@ -0,0 +1,49 @@
#define/**/F/***/for/*A*/
#define/***/H()f=*E<<4|*\
E,f=~(f|f<<1|E[3]|E[1]|E\
[1]<<4|E[2]|E[(2)]<<(1));
#define/***/I(x,d)F(;s;C\
()){s=s^(b=s&s-1^s);F(N[\
4]=q=0;q<4;q++)N[q]=E[q]\
;N[5]=E-B;N[d]^=+b^(b)x;}
#define/**/o(p,t,i,m,a,l\
\
)u=(f&p)i(m) ;s=u&E[3];I(t(m),3)s=(u)a &E[l];I(t(m\
),l)u=u>>5-m &u;s=u&E[3-l];I(t(m),3-l) s=(u)a&*E;I\
(t(m),(0));; /*echo/Line/%d;sed/-n/-e/ %d,%dp/%s>*/
/*c.c;cc/c.c /-c*/;;char*A=0,*_,*R,*Q, D[9999],*r,l
[9999],T=42, M,V=32;long*E,k[9999],B[1 <<+21],*N=B+
1234567,q=0, h=3,j=2,O,b,f,u,s,c,a,t,e ,d;C(){F(h=N
[3];(B[h]&&+ memcmp(N,B+B[h],16));h=B[ h]+4);B[h]||
(B[h]=N-B,N= N+6);}main(char*U,int*w[] ){;;F(_=A=D+
6666,A[fread (A,1,3333,fopen(__FILE__, "r"))]=0;*++
_;h||(*_=V))
*_-59|_[1]-* _||(h&&(*_=+ 35),h---2||(_[9]=V));;F(_
=A;*_;_++)10 -*_&&*_-V&&( *_-92)&&(k[q]=isalnum(l[q
]=*_),q++);M =47;*(E=N-6) =64;E[1]=289;E[2]=270336;
F(E[3]=32782 ;E<N;E=E+6){ H()o(1048560,<<,>>,4,>>4,
1)o(+489335, >>,<<,1,,2)o (978670,<<,>>,1,>>1,2)o(+
65535,>>,<<, 4,,1)if(8192 &*E){F(N=B;E>B;E=B+E[5])*
N++=E-B;F(;N >B;){h=*(E=B +*--N);H()s=~(E[1]|h|h<<1
);u=~(E[2]|h |h<<4);r=l;_ =D;d=1;a=2;O=8;F(q=74;q;q
--){F(b=0;b< 72;b++){h=+1 <<(q-1)/14*4+(b-1)/18;j=b
?(!(b%18)&&u &h)|h&f|(!(q%14)&&s&h)?1:
0:2;if(O<3)O ?j?j-1&&(O-2 &&d--,*R=34,O=2):(*_++=O-
2?l[d]?l[d++ ]:(d=t,O=e=3 ,34):(O=1,34)):j||(*_++=d
<t?l[d++]:(O =1,d=0,34)); else{if(O<6)if(j){j-2|e||
(_=R,O-4?d-- :M-_[-1]||(_ [-1]=l[d++],O=3));c=0;if(
k[d]&k[d-1]) F(;k[d-1];++ c)d--;!d||((h=l[d])^l[d-1
])+k[d]||!(+ 40-(h&62)&&h -125)||(c=1,d--);c-1||(c=
2,d--);c&&(_ [-c]=M,_[1-c ]=T,O=4);j-2|e||(*_++=+92
);}else{h=*_ ++=O-4?O-5?l [d++]:(O=3,M):(O=5,T),(_[
-1]&&(35-h|| !(a=+1)))||( O=7,*(R=Q=_-(1))=M);}else
{j?O-7||(O=6
,_[-1]=59):( *_++=a-2?O-6 ?O-7?126&*++ r:(O=8,T):(O
=7,M):(a=0,l [d]-100?(e=1 ,O=0):(e=0,O =3,35)));if(
e==1){F(r=A= l+d;35-*A;++ A)*A-M&&*A-T ||U-1&&(*A=V
);d=d+A-r;if (U-1){*A=0;F (j=2;13499>j &&(sprintf(l
,r+1,j,j,O=j +75,w[1]),j= O,!system(l) ););exit(j<+
13499);}t=d+ 9;_[-1]=l[++ d];}a-1|+j-2 ||(R-Q<3?(*(
Q<R?R-1:R)=* Q=*R=59):(*R =M,R[-1]=T), a=2);}}j?(*_
++=j-2?V:10, R):(R=_-1);} }R[-1]=T;*R= M;*_++=10;F(
R=D;putchar( *R)&&_>++R;) ;}}};O-b-f-u -s-c-a-t-e;}
+158
View File
@@ -0,0 +1,158 @@
# Best 2D puzzle
Gil Dogon
1 HaBeer Alley
Jerusalem
Israel
gil_jade@netvision.net.il
## Judges' comments
This entry takes editorial in how it deals with its output. After using
vi to look at the source, use vi to look at its output. We especially
recommend it on a 78 column xterm while leaning on Control-F.
Do you really understand expressions, then understand this:
s=s^(b=s&s-1^s)
... and understand why it is found in the source code.
### To build
cc giljade.c -o giljade
### To run
giljade > out
Open an xterm with 78 lines
vi out
Press ^F repeatedly
## Author's comments
### So what do we have here ?
Just run the executable with no command line args and look at the output. In
order to properly enjoy it you will need two good old programs: xterm and vi.
Do the following: open an xterm with precisely 78 lines, and use the tiny font
size for best results. Then vi (vim will also do) the output. Type ^F's and
enjoy the show ...
The program solves (very very fast) a sliding block puzzle. There are many
variants of such puzzles which are usually made from wood or plastic pieces.
The start position can be recognized by looking at the program itself. The
goal is to move the big piece (2 by 2) to the center top, which takes 179
steps in the shortest move sequence.
Notice: the step count used by the program is longer than the traditional step
count for such puzzles, as normally if the same piece is moved twice in a row
it is counted as only one step, but here it is counted as two.
The printout of the solution however is in a rather unorthodox form, as can be
easily discerned. As you have probably suspected each of the steps in the
solution printout is a C program which compiles to result in - surprise
surprise! - the original (well almost).
Actually, This program is smarter than merely printing ITSELF in 180 different
layouts. It is self-improving, in that the programs it prints have three
advantages over the original:
1. Their layout is more precise (Notice the annoying \ at the 10'th line of
the original program which is actually a 'layout bug'
2. Their binary output does not rely on the source file being in the same
directory, and will not dump core like the original if it doesn't. :)
3. They have much more comments (Not very helpful ones though).
In addition as we all know bugs can creep on us in the most unexpected of
places, and checking that indeed the output is composed of 180 legal C
programs by hand can be quite tedious, hence the program also include a self-
test mode. Just run it with the output file as command line argument. It will
then try to compile each of the programs (printing the line number where the
program starts) It will stop where any compilation fails and the culprit
program would be in the file 'c.c'. The exit code of the self-test will be
non-zero in that case. In case this entry wins, I do hope nobody by the name
of 'c' also wins this year otherwise that part of the program would have to be
changed!
Notice that the self-test does not try to run the result of the compilations
but this can easily be done. try it and diff the output of any of the 180
results with the original output. Of course all 180 programs also include the
self-test mode.
### Why I think this program is obfuscated.
* Because its says so, and twice is better than once!
* All the usual suspects i.e. ?: && || , used to compress code length in the
noble tradition of this contest, meaningless one character variable names,
etc...
* The board representation is efficiently compressed hence obfuscated, and
the algorithm that is used to generate possible moves is extremely efficient.
In fact it can compute several moves in parallel on one processor! Moreover
Only the most efficient bitwise logical operations, shift,and subtraction by
one is used. No inefficient conditional tests and jumps are needed in that
part of the program.
* The single expression I'm most proud of, and would have submitted to the
category of 'best obfuscated short expression' if there was one is:
s=s^(b=s&s-1^s)
Can you figure out what it does (very efficiently) and how it fits in the
scheme of things?
* IMHO the program is easier to understand before running cpp on it. It is
also shorter that way to be sure.
* It even takes care to obfuscate the comments in the output programs.
* Having the output programs a bit different than the original is more
interesting.
* I have written an earlier version of the program about half a year ago and
when returning to it now I had to sweat quite a lot to understand the f***ing
mess I've made.
### Known Bugs/problems/warnings/portability issues
Some CPPs issue a warning about empty macro parameters.
-pedantic informs me that 'ISO C' does not allow extra ; outside of a
function, and I to this I say ISO what ???
-Wall of course will suggest adding a lot of parenthesis, function prototypes,
and remove some unnecessary expressions, and to this I say: if I listen to you
where is my freedom to obfuscate in style?
As mentioned earlier if you try to run the original program without its source
nearby it will dump core.
The program relies heavily on the ASCII coding system (have I seen this
comment before ?). It also implicitly assumes that sizeof(int) = sizeof(FILE
*). On systems when that is not the case expect a core dump...
### Challenges
What use are the ;; for ?
Why do I use 126& in the program? (except for the rather obvious fact that it
serves as comment obfuscater).
Why not write s^= instead of s=s^ In the expression I'm most proud of ?
What is 40-(h&62) doing ?
Use the program to solve for a different starting position. It is not that
difficult. Notice however that if there are more than two empty spaces the
outputs would not compile as the layout would not be sufficient to contain the
program.
Use the program to solve for board size different than 4*5. Thats a bit more
tricky.
### Hint for the challenges
Just try to change the program, and use the self test to see what happens ...
+555
View File
@@ -0,0 +1,555 @@
18th International Obfuscated C Code Contest Guidelines, Hints and Comments
Copyright (C) 2005 Leonid A. Broukhis, Simon Cooper, Landon Curt Noll and
Peter Seebach.
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 contains guidelines 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.
| WHAT'S NEW IN 2005:
| The contest runs from 21-Mar-2005 00:00 UTC to 22-May-2005 23:59:59 UTC.
| We will only accept online submissions this year.
See the following for details,
| http://www.ioccc.org/2005/submit
| Most of the changes in the rules and guidelines for this year have been
| marked with a "|" character on the left hand side.
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
* compile it (with flags to enable all warnings)
* 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 declarations
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 :-)
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.
You should try to restrict commands used on the build file to
POSIX-like or common Un*x-like commands. You can also compile
and use your own programs. If you do, try to build and execute
from the current directory. This restriction is not a hard and
absolute one. The intent is to ensure that the building if your
program is reasonably portable.
Don't forget that the building of your program should be done
***without human intervention***. So don't do:
cat > prog.c
cc prog.c -o prog
However, you can do something cute such as making your program
do something dumb (or cute) when build 'automatically'. However
when it is run with a human involved, do something more clever.
For example, one could use the build instructions:
cc prog.c -DNONHUMAN -o prog
echo "See remarks section about alternate ways to compile"
and then include special notes in the program "remarks" for
alternate / human intervention based building.
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 <= 2048, the total size may be less than 4096
bytes. This means that one may use "free of charge" up to 2048
bytes of whitespace, or ; { or } followed by either whitespace
or end of file.
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.
However, initialized char arrays are OK to write over. This is OK:
char b[] = "Is this Ok";
b[9] = 'K';
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 don't like entries that use proprietary M*tif, Xv*ew, or OpenL*ok
toolkits, since not everyone has them. Use of OpenMotif is permitted
because it is more widely and freely available.
You should avoid depending on a particular window manager.
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 program "remarks".
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
* 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 program
"remarks" 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 program "remarks" 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 program "remarks" during the judging process, so it is worth your
while to write remarkable program "remarks".
We dislike C code with trailing control-M's (\r or \015) that results
in compilation failures. Some non-Un*x/non-Linux tools such as
MS Visual C and MS Visual C++ leave trailing control-M's on lines.
Users of such tools should strip off such control-M's before submitting
their entries. In some cases tools have a "Save As" option that will
prevent such trailing control-M's being added.
We dislike entries that depend on non-portable libcurses features such
as halfdelay(). One should restrict libcurses to portable features
found on BSD and SVR4/System V curses.
The rules disallow source that contains unescaped octets with values
between 128 and 255. You must use \octal or \hex escapes instead:
/* 123456789 123456789 123456789 123456 */
char *foo = "This string is 36 octets in length \263";
/* This octet requires 4 octets of source ^^^^ */
if (strlen(foo) == 36) printf("foo is 36 octets a final NUL\n");
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 program
"remarks". 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 web submission procedure tends to annoy us more
| than amuse us. Spend your creative energy on content of your
| entry rather than on the submission process itself.
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 parody 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
rules and guideline process as a parody of the sometimes tragic
mismatch between what a customer (or marketing) wants and what
engineering delivers.
JUDGING PROCESS:
Entries are judged by Leonid A. Broukhis, Simon Cooper, Landon Curt Noll
and Peter Seebach.
Each entry submitted is given an id number and subdirectory. The
"program", "info", "build" and "remarks" portions of a submission are
stored and judged from this directory.
Any "author" and identifiable "entry" information is 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. Therefore you MUST refrain from putting any information
| that reveals your identity in the "program", "info", "build", or "remarks"
| portions of your entry. 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 initial 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 "build" information
* reading the "program"
* reading the program "info", 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:
* 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 will often 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 is 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 judges will post an initial announcement of who won, the name
of their award, and a very brief description of the winning entry
on the IOCCC web site:
http://www.ioccc.org/whowon.html
We will also submit a brief announcement story to /.:
http://slashdot.org
that, depending on the willingness of the /. editors, may be posted
to their site at the same time.
Note that initial announcement will NOT contain source. This is because
the winning authors are given a chance to review the judges comments,
and test our Makefile. This review process typically takes a few weeks.
Sometime after the initial announcement, and once the the review
by the winners has been completed, the winning source will be
posted to the IOCCC web site:
http://www.ioccc.org/years.html
NOTE: previous winners are available at that URL
We will submit a story announcing the availability of the winners
to /. at the same time.
Finally the winning entries will be posted 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
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:
| q.2005@ioccc.org (do not submit entries to this address)
| You must include the words 'ioccc 2005 question' in the subject of your
EMail message when sending EMail to the judges.
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.
Check out the IOCCC Web page:
http://www.ioccc.org
It has rules, guidelines and winners of previous contests (1984 to date).
Leonid A. Broukhis
Simon Cooper
chongo (Landon Curt Noll) /\cc/\
Peter Seebach
+18
View File
@@ -0,0 +1,18 @@
INCDIR=`sdl-config --cflags`
LDFLAGS+=`sdl-config --libs`
build: jetro
clean:
clobber:
-rm jetro
jetro: jetro.c
sdl-config --version && ${CC} ${CFLAGS} ${INCDIR} ${LDFLAGS} $< -o $@
alt:
data:
+33
View File
@@ -0,0 +1,33 @@
# Most sonorous output
Jetro Lauha
Talonpojantie 5A9,
00790 Helsinki
<http://jet.ro>
## Judges' Comments
We have seen entries with SDL graphics in the past, now it's time for SDL
sound. This entry can even be run on a computer without a sound card with an
appropriate setting of an environment variable - for that you'll have to dig
into the SDL documentation.
Can you figure out how the notes are encoded and program a different melody?
### To build
Download and install the portable [Simple DirectMedia Layer library](http://www.libsdl.org/)
cc -o jetro `sdl-config --cflags --libs` jetro.c
### To run
./jetro
## Selected Author's Comments
To compile the entry you need SDL library, which is used only for audio
output. To run the entry make sure you have audio output available. The entry
plays 22KHz 16 bit mono music with a small softsynth. When the music plays,
you can stop the application by pressing enter, as the code will just wait
with one call to getchar() before it quits.
+47
View File
@@ -0,0 +1,47 @@
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include "SDL.h"
#define X2(a) a a
#define X4(a) a a a a
#define S1(a,b,c) #a".."#b".."#c"."
#define S14(a,b,c) X4(S1(a,b,c))
#define S2(a) #a"."#a"....."
#define S24(a) X4(S2(a))
#define S4(a) #a#a#a#a
#define S3(a,b,c) S1(a,b,c)S4(..)
#define SE X4(X4(S4(..)))
char l[]=SE SE X2(S3(J,H,M)S3(J,H,E)S3(F,E,A)S3(F,E,J)S3(H,E,O)S3(H,E,C)S3(H,F,
x)S3(H,F,L)),b[]=SE X2(S4(j.jv.j.v)S4(f.fr.f.r)S4(e.eq.e.q)S4(h.ht.h.t))SE,*r[3
]={S14(v,v,q)S14(r,r,m)S14(q,q,l)S14(t,t,o),S24(J)S24(F)S24(E)S24(H),S24(M)S24(
J)S24(H)S24(L)};
#define B int
#define C double
#define S static
#define I(a,b,c,d,f,g) a=(f-d)/10.,b=1e-2*(d*(28-g)-f),c=1e-2*(d*f-8*g/3);\
d+=a,f+=b,g+=c;
S C T;typedef float A;S B D,R,U,p=0;S A F[5][0100000]={{0},{0}};
void AA(void*u,Uint8*_,B L){u=u;while(L>0){B M=p&037777,s=p>>12,u=(s%R)[
l],J=(s%U)[b],w=0,a=0,n;A v,q,m,E=(0x2000-(p&017777))/8192e0f;v=q=0;
#define EF_(x) F[w][1638##x+M
#define EF(l,s,ms) ((s*ms+EF_(4)-l]*(1-ms))/2.f+EF_(3)]/2.f)
#define FQ(s) (A)sin((0.12*pow(2,n/12.))*p*s)
#define IZ(v,c) v*=v c?v:0;
#define BF F[w][M]=F[w][M+16384]=q;v+=q;++w
#define IP(n,x,y,z,c) if(n!=46){x}q=EF(y,q,z);c;BF;
#define IS(s,c) if(q c s 0.75f)q=s 0.75f;
#define NQ(x,a,m) n=x-(x>=97?121:65)+a;q=FQ(m);
IP(u,NQ(u,12,1)m=FQ(1.01f);IZ(q,>6e-1)IZ(m,>6e-1)q+=m;q*=5e-1f*(E+1);,12288,
0.2f,;)for(;a<3;++a){char sn=(s%D)[a[r]];q=0;IP(sn,NQ(sn,12,0.25f)IZ(q,<0.3),
12288,0.2f,;)}q=0;IP(J,NQ(J,0,1/8.f)X4(q*=q;)q=(A)fmod(q*20,4)*4;,6144,0.25f,IS
(-,<)IS(+,>)q*=E)v*=0.6f;*(Sint16*)_=(Sint16)(v*32767);_++,++_,++p,--L,L--;}}
B main(B c,char**a){SDL_AudioSpec f,d;c=c,a=a;D=strlen((!!c&24)[r]),R=strlen(l)
,U=strlen(b);if(SDL_Init(16)<0)exit(1);atexit(SDL_Quit);f.freq=22050,f.format=\
AUDIO_S16,f.channels=1,f.samples=4096,f.callback=AA,f.userdata=0;if(SDL_OpenAu\
dio(&f,&d)<0)exit(2);T=0;SDL_PauseAudio(0);getchar();SDL_CloseAu\
dio();return 0;}
+29
View File
@@ -0,0 +1,29 @@
build: klausler
clean:
-rm dict.h
clobber: clean
-rm klausler
klausler: klausler.c dict.h
${CC} ${CFLAGS} ${LDFLAGS} $< -o $@
alt:
data: dict.h
dict.h:
dict="";\
for f in mydict /usr/share/dict/words /usr/dict/words /usr/lib/dict/words ;\
do if [ -r $$f ]; then dict="$$dict $$f"; fi; done; \
if [ ".$$dict" = . ]; then echo no dictionary found; exit 1; fi; \
cat $$dict | \
tr -cd 'A-Za-z\n' |\
tr A-Z a-z |\
egrep -v '^[^ais]$$' |\
sort |\
uniq |\
sed 's/^/"/;s/$$/",/' >dict.h
+71
View File
@@ -0,0 +1,71 @@
# Abuse of the rules
Peter Klausler
Cray Inc.
2802 W 40th St
Minneapolis MN 55410
USA
pmk@cray.com
## Judges' comments
To reduce the size of the source, include other people's data.
That is what Peter suggests when he describes how to generate
a critical header file.
In other words: make use of other words! :-)
Rules might have to be changed!
### To build
#!/bin/sh
dict=""
for f in mydict /usr/share/dict/words /usr/dict/words /usr/lib/dict/words
do if [ -r $f ]; then dict="$dict $f"; fi; done
if [ ".$dict" = . ]; then echo no dictionary found; exit 1; fi
cat $dict | \
tr -cd 'A-Za-z\n' | \
tr A-Z a-z | \
egrep -v '^[^ais]$' | \
sort | \
uniq | \
sed 's/^/"/;s/$/",/' >dict.h
cc -o klausler klausler.c
### To run
klausler peter klausler | head
## Author's comments
A useful tool to help one appear extra smart and witty when IRCing, or even
just highly annoying.
Finds best anagrams for word or phrase given as program arguments. Use only
lower-case letters in these arguments. Output is sorted firstly in ascending
order of word count (fewer words are better) and secondly in descending order
of word length. Pipe the output into more(1)/less(1)/head(1) and you're likely
to find the most amusing possibilities in the first few screenfuls of output.
For example, "ana fawlty towers | more" quickly prints "waterfowl sty". The
fewer obscure short words in your system's dictionary, the better the quality
of the output; indeed, all one-letter words apart from "a", "i", and "s" (for
plurals) are ignored when the dictionary is constructed by build.sh.
Some history and explanation: When I noticed the call for entries in this
year's IOCCC, I submitted two of them. I worked on the first one very hard to
obfuscate it beautifully, using a goofy algorithm, wonderful two's-complement
arithmetic tricks, and cute formatting. It was a glorious work so lovely as to
make even strong men weep in admiration... but it didn't win anything. On the
other hand, this crappy little other program, which was only mildly obfuscated
from its original hacked form, took home an award!
I'm embarrassed to admit that I don't even know which specific rule this entry
has abused. It's just yet another anagram generator and it was written very
late one night. And now I honestly do not know how it works, so please don't
ask. Upon reviewing the program after its unexpected honor, I guess that it's
remarkable only for its complete lack of macros, sneaky naming, main()
recursion, or other tricks. Enjoy!
+14
View File
@@ -0,0 +1,14 @@
typedef unsigned char B;char*x[]={
#include "dict.h"
0};typedef struct L{B*s;struct L*n;}L;
L*h[128],*l[128],*s[128],Z[sizeof x/sizeof*x],*F=Z;int c[256],m,a=1;
int k(B*q){int g=0;B*p=q;while(*p)g|=!c[*p++]--;return g-1&p-q;}
void u(B*p){while(*p)c[*p++]++;}
void S(int N,int r,int t,L*W){L*w;int i,n;
for(n=r<N?r:N;n>0;n--)for(w=n==N?W:h[n];s[t]=w;u(w->s),w=w->n)if(k(w->s))
if(n==r){if(t==m-1)for(i=a=0;i<=t;i++)printf("%s%c",s[i]->s,i<t?' ':'\n');}
else if(t<m-1)S(n,r-n,t+1,s[t]=w);}
int main(int C,B**A){int i=0,g,n=0;B*p;while(--C)for(p=*++A;n<127&&*p;)c[*p++]++,n++;
for(;p=x[i++];u(p))if(g=k(p))(l[g]=*(l[g]?&l[g]->n:&h[g])=F++)->s=p;
while(++m<128)S(127,n,0,h[127]);
return a;}
+14
View File
@@ -0,0 +1,14 @@
typedef unsigned char B;B*x[]={
#include "dict.h"
0};typedef struct L{B*s;struct L*n;}L;
L*h[128],*l[128],*s[128],Z[sizeof x/sizeof*x],*F=Z;int c[256],m,a=1;
int k(B*q){int g=0;B*p=q;while(*p)g|=!c[*p++]--;return g-1&p-q;}
void u(B*p){while(*p)c[*p++]++;}
void S(int N,int r,int t,L*W){L*w;int i,n;
for(n=r<N?r:N;n>0;n--)for(w=n==N?W:h[n];s[t]=w;u(w->s),w=w->n)if(k(w->s))
if(n==r){if(t==m-1)for(i=a=0;i<=t;i++)printf("%s%c",s[i]->s,i<t?' ':'\n');}
else if(t<m-1)S(n,r-n,t+1,s[t]=w);}
int main(int C,B**A){int i=0,g,n=0;B*p;while(--C)for(p=*++A;n<127&&*p;)c[*p++]++,n++;
for(;p=x[i++];u(p))if(g=k(p))(l[g]=*(l[g]?&l[g]->n:&h[g])=F++)->s=p;
while(++m<128)S(127,n,0,h[127]);
return a;}
+16
View File
@@ -0,0 +1,16 @@
C99=--std=c99
build: mikeash
clean:
clobber:
-rm mikeash
mikeash: mikeash.c
${CC} ${CFLAGS} ${C99} ${LDFLAGS} $< -o $@
alt:
data:
+128
View File
@@ -0,0 +1,128 @@
# Best use of parenthesis
Michael Ash
USA
mike@mikeash.com
## Judges' comments
Having problems speaking code? Do you LISP? Parenthetically
speaking, this entry takes advantage of C99 features, while
speaking parenthetically. Best of all, it self-reproduces!
John McCarthy might not of imagined it quite like this! :-)
### To build
gcc --std=c99 -o mikeash mikeash.c
### To run
mikeash < mikeash.c
mikeash < mikeash.c | diff - mikeash.c
## Author's comments
This program is a self-reproducing program, which is on the IOCCC's list
of discouraged program types. Worse, it's a self-reproducing program
written in Common Lisp. What's this doing as an entry to the IOCCC?
Start over; this program, when compiled with a C99 compiler, is an
interpreter for an extremely limited and highly broken subset of Common
Lisp.
It requires C99 because of C99's ability to declare variables in the
initializer of a for loop. Unfortunately, C99 mode typically warns about
implicitly declared functions, and preprocessor directives prevent the
program from being valid Common Lisp. As a result, several warnings will
be printed about implicit declarations of functions. There are also
warnings about unknown escape sequences in the constant string, due to
different string escape semantics in C and Lisp, and some implicit
integer-to-pointer conversions due to the implicitly-declared functions.
Try:
echo '(format t "~s" (+ 2 2 ))' | ./lispob
You should see '4"' echoed on your command prompt. The " after the 4 and
the lack of a newline are due to the somewhat broken implementation of
the format function. More sophisticated arithmetic expressions may be
used:
echo '(format t "~s" (* (+ 2 2 ) (- 5 (/ 9 3 ))))' | ./lispob
This evaluates the expression (2+2) * (5 - 9/3) giving the correct
result, 8. Note that due to the highly ad-hoc nature of the tokenizer,
the spaces before the closing paretheses are mandatory.
The program can also be run in an interactive mode, by simply executing
./lispob and then typing lisp expressions, but this is difficult due to the
lack of proper editing facilities and the total lack of error recovery in the
interpreter. Typos will most likely crash the program.
Aside from being required to put spaces between tokens and closing
parentheses, there are other limitations on the dialect of Common Lisp
that this program understands:
* The only built-in functions are defvar, format, substitute, char-upcase,
+, -, *, and /.
* Only one variable is available. This variable is called 'q', although any
symbol name starting with the letter 'q' will be mapped to this variable.
* Only the first letter of a function name is significant. For example,
format, f, farm, and various other words starting with 'f' will all map to the
format function.
* The defvar function completely ignores its first parameter. It will always
store the result of evaluating its second parameter in 'q'. Unlike in Common
Lisp, multiple invocations of defvar on the same variable will overwrite old
values.
* Character constants are limited to #\Newline and single-character
constants such as #\x.
* The char-upcase function will give strange results if passed something
other than a lowercase character.
* The format function takes exactly three parameters. The first parameter is
ignored; output always goes to stdout. The second parameter must have exactly
one ~s format specifier in it, and no other format specifiers are permitted.
* The arithmetic functions take exactly two parameters.
* All tokens must be separated from a following ) by whitespace.
* A lot of other things. Notably, the language which this program interprets
is nowhere near Turing-complete.
Basically, the lisp interpreter is good for some basic math operations, and
for running itself. To do the latter, try this:
./lispob < lispob.c > lispob2.c
diff lispob.c lispob2.c
The program can also be run from an implementation of common lisp. To do
this, run the common lisp compiler and then type the following command:
(load "lispob.c")
The source code of lispob.c will be printed.
Lispob is obfuscated in several ways. First, it's actually two programs
in one, which actually share a small amount of code. Running a C code
beautifier will destroy the lisp program contained within. Second and
more importantly, it is very badly written, which will presumably
confuse people who are used to looking at well-implemented interpreters.
The program comes in at just under 2k of significant characters.
However, this size is exaggerated, because it contains a complete copy
of itself for the self-reproducing lisp program, making it twice the
size. This doubling effect made it something of a challenge to fit
inside the IOCCC's size limit.
This code should be highly portable. It was tested under Mac OS X and
Linux on i386, but it should run elsewhere. It requires ASCII due to
hardcoding various character constants. Other than this requirement, it
should run anywhere there's a conforming C99 compiler and a standard
C library.
+22
View File
@@ -0,0 +1,22 @@
;typedef char n;typedef n*m;int C;n c[11];n y[]={37,100,0};n b[2048];int i
;int A(void){return C=getchar();}int B(m s){return strlen(s)
;}n w[2048];typedef m defvar;m R(void){do A();while(isblank(C) || C == '\n')
;if(C<0) return 0;i=0;if(C==';'){for
(defvar q=
";typedef char n;typedef n*m;int C;n c[11];n y[]={37,100,0};n b[2048];int iY;int A(void){return C=getchar();}int B(m s){return strlen(s)Y;}n w[2048];typedef m defvar;m R(void){do A();while(isblank(C) || C == '\n')Y;if(C<0) return 0;i=0;if(C==';'){forY(defvar q=Y~sY;C!='\n';A()Y);R();}else if(C=='('||C==')')b[i++]=C;else if(C==34)do b[i++]=CY;while(A()!=34);else do b[i++]=C;while(!isblank(A())&&C!='\n')Y;b[i] = 0;return b;}typedef defvar*format;m E(void){Y;m a=R();if(!a) return 0;if(*a==34)return aY;if(*a=='#'){c[0]=a[2]=='N'?'\n':a[2];return c;}if(*a=='q')return wY;if(*a=='('){a=R();if(*a=='d'){R();strcpy(w,E());R();return wY;}else if(*a=='f'){R();m f = strdup(E());*strchr(f,126)=37Y;m s=E();s[B(s)+1]=0;s[B(s)]=34;printf(f+1,s);R()Y;}else if(*a=='s'){n p=*E();n o=*E();m r=strdup(E());a=r;forY(format t ;*a;a++)*a=*a==o?p:*aY;R();return r;}else if(*a=='c'){c[0]=*E()-32/*Y(substitute #\Newline (char-upcase #\y ) q= )q= );*/Y;R();return c;}else{n z=*a;int d=atoi(E()),e=atoi(E())Y;sprintf(c,y,z-'+'?z-'-'?z-'*'?d/e:d*e:d-e:d+e);R();return cY;}}return a;}int main(void){while(C+1)E();return 0;}Y"
;C!='\n';A()
);R();}else if(C=='('||C==')')b[i++]=C;else if(C==34)do b[i++]=C
;while(A()!=34);else do b[i++]=C;while(!isblank(A())&&C!='\n')
;b[i] = 0;return b;}typedef defvar*format;m E(void){
;m a=R();if(!a) return 0;if(*a==34)return a
;if(*a=='#'){c[0]=a[2]=='N'?'\n':a[2];return c;}if(*a=='q')return w
;if(*a=='('){a=R();if(*a=='d'){R();strcpy(w,E());R();return w
;}else if(*a=='f'){R();m f = strdup(E());*strchr(f,126)=37
;m s=E();s[B(s)+1]=0;s[B(s)]=34;printf(f+1,s);R()
;}else if(*a=='s'){n p=*E();n o=*E();m r=strdup(E());a=r;for
(format t ;*a;a++)*a=*a==o?p:*a
;R();return r;}else if(*a=='c'){c[0]=*E()-32/*
(substitute #\Newline (char-upcase #\y ) q= )q= );*/
;R();return c;}else{n z=*a;int d=atoi(E()),e=atoi(E())
;sprintf(c,y,z-'+'?z-'-'?z-'*'?d/e:d*e:d-e:d+e);R();return c
;}}return a;}int main(void){while(C+1)E();return 0;}
+15
View File
@@ -0,0 +1,15 @@
build: mynx
clean:
clobber:
-rm mynx
mynx: mynx.c
${CC} ${CFLAGS} ${LDFLAGS} $< -o $@
alt:
data:
+4192
View File
File diff suppressed because it is too large. Load diff
+41
View File
@@ -0,0 +1,41 @@
AC_PREREQ(2.59)
AC_INIT(mynx, 1.0, [])
platform=`uname -s|sed -e 's/^\([[a-zA-Z0-9]]*\)[[^a-zA-Z0-9]].*/\1/'`
echo "platform is... $platform"
my_configure_command="$[]0 $[]@"
AC_CHECK_TOOL(autoconf_tool, autoconf)
if test ${autoconf_tool:-no} != 'no' -a \( aclocal.m4 -nt configure -o configure.in -nt configure \); then
echo 'Rebuilding the configure script first...'
autoconf -f
echo 'Restarting configure script...'
echo $my_configure_command
exec $my_configure_command
fi
AC_SUBST(platform, $platform)
AC_CONFIG_SRCDIR($PACKAGE_NAME.c)
AC_CONFIG_FILES(makefile)
AC_ARG_ENABLE(w32,
[AC_HELP_STRING([--disable-w32],[generate Cygwin binary in Cygwin environment])]
)
if test $platform = 'CYGWIN' -a ${enable_w32:-yes} != 'no' ; then
CFLAGS="-mno-cygwin ${CFLAGS}"
LIBS="-lws2_32 ${LIBS}"
fi
AC_PROG_CC
AC_HEADER_STDC
AC_SEARCH_LIBS(socket, [socket nsl],[AC_DEFINE_UNQUOTED([AS_TR_CPP([HAVE_SOCKET])])])
AC_CHECK_HEADERS(
[arpa/inet.h netdb.h netinet/in.h sys/socket.h sys/ioctl.h],
[], [AC_MSG_FAILURE([Missing required I/O header.], 1)]
)
AC_CHECK_HEADERS([windows.h winsock2.h])
AC_OUTPUT()
echo
echo $PACKAGE_STRING
echo
AC_MSG_RESULT([ platform...: $platform])
AC_MSG_RESULT([ prefix.....: $prefix])
AC_MSG_RESULT([ CFLAGS.....: $CFLAGS])
AC_MSG_RESULT([ LDFLAGS....: $LDFLAGS])
AC_MSG_RESULT([ LIBS.......: $LIBS])
echo
+103
View File
@@ -0,0 +1,103 @@
quot 34
amp 38
lt 60
gt 62
euro 128
nbsp 160
iexcl 161
cent 162
pound 163
curren 164
yen 165
brvbar 166
sect 167
uml 168
copy 169
ordf 170
laquo 171
not 172
shy 173
reg 174
macr 175
deg 176
plusmn 177
sup2 178
sup3 179
acute 180
micro 181
para 182
middot 183
cedil 184
sup1 185
ordm 186
raquo 187
frac14 188
frac12 189
frac34 190
iquest 191
Agrave 192
Aacute 193
Acirc 194
Atilde 195
Auml 196
Aring 197
AElig 198
Ccedil 199
Egrave 200
Eacute 201
Ecirc 202
Euml 203
Igrave 204
Iacute 205
Icirc 206
Iuml 207
ETH 208
Ntilde 209
Ograve 210
Oacute 211
Ocirc 212
Otilde 213
Ouml 214
times 215
Oslash 216
Ugrave 217
Uacute 218
Ucirc 219
Uuml 220
Yacute 221
THORN 222
szlig 223
agrave 224
aacute 225
acirc 226
atilde 227
auml 228
aring 229
aelig 230
ccedil 231
egrave 232
eacute 233
ecirc 234
euml 235
igrave 236
iacute 237
icirc 238
iuml 239
eth 240
ntilde 241
ograve 242
oacute 243
ocirc 244
otilde 245
ouml 246
divide 247
oslash 248
ugrave 249
uacute 250
ucirc 251
uuml 252
yacute 253
thorn 254
yuml 255
+60
View File
@@ -0,0 +1,60 @@
# Best use of the www
Anthony Howe
Snert
42 av. Isola Bella
06400 Cannes,
France
achowe@snert.com
## Judges' comments
This little mynx will give any Fiery Fox a run for its money. A nice complement
to last years winning hibachi. The judges double dare any eager
Obfuscationalists to submit the missing pieces to get a functioning LAMP stack.
### To build
cc -O2 -o mynx mynx.c
If this does not work for you, use the enclosed configure script.
### Try
mynx http://www.ioccc.org/
## Author's comments
I was rather impressed by last year's mini web server. So much so that
it inspired me to try my hand at writing the client side complement.
A typical build would be command would be:
$ gcc -omynx mynx.c
While some others like to be a little different:
$ gcc -omynx mynx.c -lnsl -lsocket
I even managed to figure out a basic configure script, given last year's
example, which is kinda of useful when you consider how many OSes put
all the network functions in a variety of places. So a simpler build
command sequence would be:
$ ./configure
$ make
After which, the rest of the documentation can be read by saying:
$ mynx manual.html
Manifest:
mynx.c
makefile pre-built generic Un*x
README.TXT
manual.html
makefile.in makefile template
entities.txt ISO 8859-1 entites
configure.in configure script description
configure pre-built configure script
+21
View File
@@ -0,0 +1,21 @@
PACKAGE = @PACKAGE_NAME@
CC = @CC@
CFLAGS = @CFLAGS@
LDFLAGS = @LDFLAGS@
LIBS = @LIBS@
E = @EXEEXT@
build: ${PACKAGE}$E
clean:
-rm ${PACKAGE}$E ${PACKAGE}-alt$E
distclean: clean
-rm config.status configure.lineno config.log makefile
-rm -rf autom4te.cache
${PACKAGE}$E: ${PACKAGE}.c
${CC} ${CFLAGS} ${LDFLAGS} -o${PACKAGE} ${PACKAGE}.c ${LIBS}
${PACKAGE}-alt$E: ${PACKAGE}-alt.c
${CC} ${CFLAGS} ${LDFLAGS} -o${PACKAGE}-alt ${PACKAGE}-alt.c ${LIBS}
+87
View File
@@ -0,0 +1,87 @@
<html>
<head>
<title>Mynx</title>
</head>
<body>
<div align="center">
<table cellpadding="0" cellspacing="0" border="0" width="600">
<tr><td>
<h1>The Mynx Web Browser</h1>
<h2>Usage</h2>
<blockquote>
<code><b>mynx</b> <i>filepath</i>|<i>url</i></code>
</blockquote>
<h2>Description</h2>
<p>
View the web as it once was with the Mynx web browser. A fusion of something between more(1) and lynx(1).
It allows you to surf the web in complete safety and tranquility. The ideal web browser
for small children and their sensitive minds. It contains
a window popup blocker, it filters banner ads, and is easy to configure!
</p>
<p>
You can view local HTML files or give an <code>http://</code> URL. Simply press
the ENTER key to page down through long documents. To navigate, just type the number
found in square brackets to the left of any link, followed by the ENTER key. To
quit, simply visit link zero (0), or type CTRL+C.
</p>
<h2>Features</h2>
<ul>
<li>A lean simple interface verses
<a href="http://www.mozilla.org/">Mozilla Firefox</a>,
<a href="http://www.opera.com/">Opera</a>, or Internet Explorer.
</li>
<li>Can navigate frames and image links.</li>
<li>Integrated popup window blocker.</li>
<li>No forms to fill out.</li>
<li>No banner ads.</li>
<li>No cookie crumbs.</li>
<li>No past to worry about.</li>
</ul>
<h2>Technical Overview</h2>
<ul>
<li>Parses well formed XHTML documents as given by the
<a href="http://www.w3.org/TR/xhtml1/">W3C XHTML 1.0 Specification</a>.
</li>
<li>Recognises the terminal window dimensions and performs line wrapping.</li>
<li>Supports the ISO 8859-1 character entities, which can be easily redefined.</li>
<li>The compact HTML scanner supports trivial wildcard matching.</li>
<li>With minor changes, can be built as a Windows native console application.</li>
</ul>
<h2>Known Issues</h2>
<p>The following issues are related to space constraints:</p>
<ul>
<li>HTTP redirection responses (301, 302, 303, and 307) are not handled, assuming
that a short HTML message with a clickable link will be provided as recommended by
RFC 2616. However, not all sites properly adhere to this useful recommendation.
Symptoms of this are a couple of blank lines and a return to the prompt after
selecting a link.
</li>
<li><a href="http://www.w3.org/TR/html4/">HTML 4.01</a> or older documents should
still display, though the formatting may be a little different as these documents
often omit closing tags for many elements such as: &lt;/p&gt;, &lt;/li&gt;
</li>
<li>MIME types other than text/html are not handled.</li>
</ul>
<hr/>
<a href="manual.html">Top</a>
- <a href="http://www.ioccc.org/">IOCCC</a>
- <a href="http://www.usenix.org/">USENIX</a>
- <a href="http://www.sage.org/">SAGE</a>
- <a href="http://www.news.com/">CNet News</a>
- <a href="http://slashdot.org/">Slashdot</a>
</td></tr>
</table>
</div>
</body>
</html>
+221
View File
@@ -0,0 +1,221 @@
#define I int
#define c char *
#define G fscanf(f,
#define W while(
#define k return
#define Q if(
#define Z 512
#include <errno.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/ioctl.h>
FILE *f;
short w[4] = { 24, 80 };
I L, B, r, H;
c l[Z], b[Z], s[Z], S[Z][10], T[Z], h[Z];
I
e(c s)
{
I n = 0;
Q *s == '#')
k (I) strtol(s+1, 0, 0);
W n < Z) {
Q *S[n] && !strcmp(s, S[n]+1))
k *S[n];
n++;
}
k '?';
}
void
P(I x)
{
Q x == '\n' || w[1] - 3 < B) {
b[B] = 0;
b[B+1] = 0;
B = printf("%s", b);
B = snprintf(
b, Z,
"\n %s",
b + B + 1
);
r++;
}
Q b[B-1] != ' ' || !isspace(x)) {
b[B++] = isspace(x) ? ' ' : x;
Q w[1] - 3 < B)
*strrchr(b, ' ') = 0;
}
}
void
p(c t, ...)
{
va_list x;
va_start(x, t);
vsnprintf(s, Z, t, x);
t = s;
W *t)
P(*t++);
va_end(x);
}
I
X(c s)
{
I x;
c t = s;
long m = ftell(f);
W *t && (x = fgetc(f)) != EOF) {
Q *t == '*')
s = t++;
Q tolower(x) != *t) {
Q *s != '*')
break;
t = s;
}
t++;
}
Q *t)
fseek(f, m, SEEK_SET);
k !*t;
}
void
d(c s)
{
Q 4 < B)
P('\n');
P('\n');
Q *s == 'h')
B = 1;
}
void
a(c s)
{
*T = 0;
G
ungetc(fgetc(f), f) == '"'
? "\"%511[^\"]"
: "'%511[^']",
T
);
Q *s == 'a' || *s == 'f' || s[1] == 'f') {
free(l[++L]);
l[L] = strdup(T);
p(" [%d] ", L);
}
Q *s != 'a')
p("%s%s\n", T, *s == 'b' || s[1] == 'h' ? "" : "\n");
X("*>");
}
void *Y[] = {
"!--*-->" , 0 ,
"a *href=" , a ,
"ifr*src=" , a ,
"fra*src=" , a ,
"img*src=" , a ,
"p*>" , d ,
"bl*>" , d ,
"br" , a ,
"hr" , a ,
"h*>" , d ,
"/h" , a ,
"/tr" , a ,
"/dt" , a ,
"/dd" , a ,
"li*>" , d ,
"*>" , 0 ,
0 , 0
};
I
main(I V, c *v)
{
I x, n = 0;
c t = v[1];
ioctl(0, TIOCGWINSZ, w);
f = fopen("entities.txt", "r");
Q f) {
W G "%s %d", S[n]+1, &x) == 2)
*S[n++] = x;
fclose(f);
n = 0;
}
W t) {
I m = 0;
struct hostent *y;
struct sockaddr_in A;
L = 0;
B = 1;
Q !sscanf(t, "http://%255[^/]%n", h, &n) && !*h) {
Q !(f = fopen(t, "rb")))
k 1;
goto e;
}
Q 0 < sscanf(h, "%*[^:]%n:%d", &x, &H))
h[x] = 0;
else
H = 80;
y = gethostbyname(h);
Q !y)
k 1;
memcpy(&A.sin_addr.s_addr, y->h_addr, y->h_length);
A.sin_port = htons( (short) H);
A.sin_family = y->h_addrtype;
f = tmpfile();
Q !f)
k 1;
W
connect(
m = socket(
A.sin_family, SOCK_STREAM, 0
), (void *) &A, sizeof A
)
|| errno == EINTR
)
;
n = snprintf(
b, Z,
"GET %s%s HTTP/1.0\r\nHost: %s:%d\r\n\r\n",
t[n] == '/' ? "" : "/", t+n, h, H
);
Q send(m, b, n, 0) == n) {
W 0 < (n = recv(m, b, Z, 0)))
fwrite(b, 1, n, f);
}
close(m);
rewind(f);
X("*\r\n\r\n");
e:
r = 3;
*b = ' ';
W r < *w && (x = fgetc(f)) != EOF) {
Q x == '<') {
void **p = Y;
W *p) {
Q X(*p)) {
Q p[1])
(* (void (*)(c ))
p[1])(*p);
break;
}
p += 2;
}
} else {
Q x == '&') {
G "%9[^;];", T);
x = e(T);
}
P(isspace(x) ? ' ' : x);
}
}
printf("\n? ");
fflush(stdout);
fgets(T, Z, stdin);
Q *T == '\n')
goto e;
t = l[strtol(T, 0, 0)];
fclose(f);
}
k 0;
}
+15
View File
@@ -0,0 +1,15 @@
LDFLAGS+=-lm
build: persano
clean:
clobber:
-rm persano
persano: persano.c
${CC} ${CFLAGS} ${LDFLAGS} $< -o $@
alt:
data:
+116
View File
@@ -0,0 +1,116 @@
# Best of show
Mauro Persano
São Paulo
Brazil
mauro_persano@yahoo.com
## Judges' Comments
### To build
cc -lm persano.c -o persano
If your system is one of those that distinguish between text and binary
streams, you must know what to do to switch the standard output into
binary mode (e.g. adding a line to the source code or specifying a
linker option).
### Try
persano 3 16 > knot3-16.gif
Open the GIF file with a viewer capable of displaying animated GIFs and
watch closely at the bottom of the picture (you may need to use
"gifsicle" - a great tool to manipulate animated GIFs - to slow down the
animation and to compress the GIFs generated by the entry).
What needs to be done to fix the problem?
Solving the author's exercises below may or may not help.
At the time of judging, the approximation of π used in the program could
not be found on mathworld.com.
## Selected Author's Comments
### NAME
**knot**
> writes animated GIF images of rendered torus knots to standard output.
### SYNOPSIS
knot p q [num frames]
### DESCRIPTION
A (p,q)-torus knot is a closed, non-intersecting curve on the surface of
a torus in R3 that winds p times around one cycle of the torus and q
times around the other. p and q should be coprime; otherwise, the
resulting curve will _not_ be a knot (that is, imagining the resulting
curve as a loop of rubber, there will be a way to bend, twist and
stretch it, without cutting it [1], until it ends up looking just like a
circle embedded in R3 [2]).
Sample usage:
knot 3 2 1 > foo.gif
writes a non-animated GIF (a single frame) stream of a rendered trefoil
knot to the file foo.gif.
knot 5 2
writes a GIF stream with a rendering of Solomon's Seal knot to standard
output; since the number of frames is not specified, an animation with
40 frames will be written.
Please view the code with 8-character tabs!
### OUTPUT FORMAT
The program writes fully valid GIF 89 streams.
It is suggested that the output be viewed with a program capable of
displaying animated GIFs, such as almost any graphical HTTP browser.
Due to code size constraints, full LZW compression was not implemented
[3]. In fact, the output images are even somewhat expanded, thanks to
GIF overhead.
The GIF format supports only a limited number of bits per pixel, so the
program uses ordered dithering to emulate full RGB output.
### PORTABILITY
The program was tested on Linux, with gcc 3.1; Cygwin, with gcc 3.3; and
Solaris/Sparc, with Sun's C compiler.
The only major portability issue should be reliance on ASCII.
It should also be mentioned that the program won't work on systems that
distinguish between text and binary streams; however, since hardly
anyone uses such systems in this day and age, this is a minor issue. [4]
### EXERCISES FOR THE READER
1. (1 point) The surface is composed of many small polygons. Try to make it
smoother by increasing the number of polygons.
2. (2 points) Figure out how to change the radius of the tube cross section.
3. (5 points) Locate the famous transcendental constant π in the code.
### FOOTNOTES
[1] You can call such a transformation an "ambient isotopy" if you want to
impress people at parties.
[2] Also known as the "unknot", which sounds slightly less impressive than
"ambient isotopy".
[3] Unfortunately (for the author), the convenient excuse that LZW compression
was not implemented in order to avoid the Unisys patent can no longer be used.
[4] ;)
+138
View File
@@ -0,0 +1,138 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#define H 20
#define X for
#define F(v,b) X(k = 0; k < 3; k++) v[k] = b;
typedef double R, V[3], U[4], (*J)(R);
typedef void Z;
typedef int _;
V o, d, v;
R (*q)[H][6], C[4*H][H][6], sr = 15, br = 25, A, s, t;
_ P, Q, g, S, k, e = 256, (*u)(_) = putchar, D[64];
J f = cos, Y = sin;
char B[256];
Z
T(_ *p, _ k, _ n)
{
_ g;
*p = n;
X(g = 0; k && g < 4; g++)
T(p + (9 & (g * 4|g))*(1<<k - 1), k - 1,
n + (1<<6-2 * k)*(4 - g&3));
}
Z
O(_ c)
{
B[++S] = c,
(S > e-2 || c==129) && (*B = S, S = fwrite(B, S+1, 1, stdout) - 1);
}
Z N
(R*v){R w=sqrt
(*v**v +1[v]*v[1]
+v[2]*2[v]);F(v,v[k]
/w)}Z K(_ j){V
n,p ;R*b=(*
q) [j],w=f
(A),x=
Y(A);
F(p,
br*o[
k]+sr
* (n[ k] =f(t)*k[v]+
Y(t)*(v[(k+1)%3]* d[( k+2)%3]-v[(k+2)%
3]*d[(k+1)%3])))*b++=p[1 ]+e/ 2,*b++=-*p*x+
p[2]*w-e*e,*b++=(*p*w+p[2]*x)+e/2;F( b,fabs(*n
*!!k+n[1]*( k<2)+n[2])/sqrt(2+ !(k-1)))
}Z M(R*a,_ s,Z(*m)(_)){_ i;R d=
pow(25/log (36),4)/s/ 377;X(
*a=i=0;i<s ;i++,*a+=d )m(i);
}Z G(_ i ){R w=-Y (P*s),
x=f(P*s), y=Y(Q*s ),z=f
(Q*s);F( v,k[o] =(k<2
)*(x+3)*( k?y:z) -!(k-2 )*w)N(
v);F(d,P* (k?k- 1?x:w*y:w*z )+Q*(k?
k-1?0:*o:- o[1]) )N(d),w=*d**v+d[1]
*v[1]+d[2] *v[2 ];F(v,k[v]-w
*d[k])N(v),q =&C[
i],M(&t,H,K); }Z W
(char*s){*s&&( W(s
+1),u(*s-98*(*s>
97)));}Z E(_ z){R
*r,*a,*b;U*q,l,x,d
,I[256];_ i,j,m,c,y,
w,h,Y=sizeof l;fputc(
46,stderr),M(&s,4*H,G),
W("ibcbcbbbbb,"),g=130,
O(e/2);X(y=0;y<e;y++){X(i
=e;i;)*(I[--i])=0;X(;i<4
*H*H;i++)X(*l=k=0;k-5;k++
,a=b)if(b=C[(i/H+((k^k/
2)&1))%(4*H)][(i+(k/2&1
))%H],k&&y<*a^y<*b){X(
h=0;h<4;h++)h[x]=a[h
+2]+(b[h+2]-a[h+2])
*(y-*a)/(*b-*a),h?
*l&&(d[h]=(l[h]
-h [x])/w):(w=1+
fabs (*l-(*x=(_)*x)
) ); X(q=I+(_)*x;
*l&& w--;q+=2*(
*x<* l)-1)X(**q
>C[i /H][i%H][1
]&&( memcpy(*q,
x,Y),* *q=C[i/H][
i%H][1 ]),h=1;h<
4;h++)x [h]+=h[d];
memcpy(l ,x,Y);}X(
i=0;i<e;i++ ,O(*r?c:
127),g=g<e-1 ?g+1:(O(e/
2),130))X(r=&I[ i][3],c=0,j
=2;j+1;j--,r--)k=3|!( j-1)*4,m=*r*k+
(63*( *r*k-(_)(*r*k))>D[(y*8&56)+(i&7)
]), c<<=k/4+2,c|=(m|-(m>k))&
k;} O(129);u(0);}_
main(_ c, char **v)
{
if (c < 3)
return fprintf(stderr, "Usage: %s P Q [F]\n", *v), 1;
P = atoi(v[1]),
Q = atoi(v[2]),
T(D, 3, 0);
W("bb\346cbcba98FIG");
X(; k < 384; k++)
u(k / 3<<("gdb"[k%3] - 97) | 31 | (k % 3!=1)<<5);
W("bbbce0.2EPACSTEN\x0b\xff!"),
M(&A, c > 3 ? atoi(v[3]) : 40, E),
u(59);
return 0;
}
/* vi:set ts=8: */
+152
View File
@@ -0,0 +1,152 @@
18th International Obfuscated C Code Contest Rules
Copyright (C) 2005 Leonid A. Broukhis, Simon Cooper, Landon Curt Noll and
Peter Seebach.
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 18th IOCCC contest window is:
| 21-Mar-2005 00:00 UTC to 22-May-2005 23:59:59 UTC
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) The size of your program source must be <= 4096 bytes in length.
The number of characters excluding whitespace (tab, space,
newline, formfeed, return), and excluding any ; { or } immediately
followed by whitespace or end of file, must be <= 2048.
3) Submissions should be performed using the instructions outlined at,
| http://www.ioccc.org/2005/submit
4) If your entry is selected as a winner, it will be modified as follows:
Your 'build' instructions will be incorporated into a
makefile. If your build instructions *is* a makefile then
it should be portable and usable from within a master
makefile.
Your program source will be renamed using an identifier of
our choice (usually your family name or anonymous) followed
by an optional digit, followed by '.c'
Your entry will be compiled into a file with the above name
minus the '.c'.
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) Your program source 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 "remarks" section of your submission.
7) The program must be of original work. All submitted programs are
are thereby put in the public domain. All explicitly copyrighted
programs will be rejected.
| 8) Entries must be received prior to 22-May-2005 23:59:59 UTC.
An EMail a confirmation of submission will be sent to the sender
before the close of the contest.
9) Each person may submit up to 8 entries per contest year. Each entry
must be submitted separately.
10) Entries requiring human interaction to be built are not permitted.
11) Programs that require special privileges (setuid, setgid, super-user,
| special owner or group) are highly discouraged.
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 submitted "remarks".
13) Your source may not contain unescaped octets with the high bit set.
I.e., your source may not contain octet values between 128 and 255.
14) Any program that fails to compile because of lines with trailing
control-M's (\r or \015) will be rejected.
15) When you submit your entry you must have a valid email address
that can both send and receive email. The online submission
method is a two phase process that requires the use of an
approval code. This code will be emailed to you as part of
phase 1.
Entries submitted without a working or valid email address will
be disqualified.
The judges are not responsible for delays in email, please plan
enough time for one automated exchange of email as part of your
submission.
16) You are STRONGLY encouraged to submit an original entry.
Submissions that are similar to previous entries are discouraged.
| 17) The total size of your submission: the sum of the size of the program,
| hints, comments, build and info files MUST be less than one megabyte
| in size.
FOR MORE INFORMATION:
The judging will be done by Leonid A. Broukhis, Simon Cooper, Landon
Curt Noll and Peter Seebach. Please send questions or comments
about the contest, to:
| q.2005@ioccc.org (for questions only!)
| You must include the words ``ioccc 2005 question'' in the subject of
your EMail message when sending EMail to the judges.
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).
Details of how to submit your entry are located at,
| http://www.ioccc.org/2005/submit
Leonid A. Broukhis
Simon Cooper
chongo (Landon Curt Noll) /\cc/\
Peter Seebach
Binary file not shown.
BIN
View File
Binary file not shown.
+38
View File
@@ -0,0 +1,38 @@
LDFLAGS+=-lcurses
build: sykes
clean:
-rm *.bin
clobber: clean
-rm sykes pet.rom
sykes: sykes.c
${CC} ${CFLAGS} ${LDFLAGS} $< -o $@
alt: sykes.orig
sykes.orig: sykes.orig.c
${CC} ${CFLAGS} ${LDFLAGS} $< -o $@
data: pet.rom
pet.rom: basic-2-c000.901465-01.bin basic-2-d000.901465-02.bin edit-2-n.901447-24.bin nullfill.bin kernal-2.901465-03.bin
cat basic-2-c000.901465-01.bin basic-2-d000.901465-02.bin edit-2-n.901447-24.bin nullfill.bin kernal-2.901465-03.bin >pet.rom
basic-2-c000.901465-01.bin:
wget http://www.zimmers.net/anonftp/pub/cbm/firmware/computers/pet/basic-2-c000.901465-01.bin
basic-2-d000.901465-02.bin:
wget http://www.zimmers.net/anonftp/pub/cbm/firmware/computers/pet/basic-2-d000.901465-02.bin
edit-2-n.901447-24.bin:
wget http://www.zimmers.net/anonftp/pub/cbm/firmware/computers/pet/edit-2-n.901447-24.bin
kernal-2.901465-03.bin:
wget http://www.zimmers.net/anonftp/pub/cbm/firmware/computers/pet/kernal-2.901465-03.bin
nullfill.bin:
dd bs=2k count=1 if=/dev/zero of=nullfill.bin
BIN
View File
Binary file not shown.
+224
View File
@@ -0,0 +1,224 @@
# Best emulator
Stephen Sykes
Maxisat
Laivalahdenportti 2
00810, Helsinki
Finland
sds@maxisat.fi
## Judges' comments
For those who fondly remember their first PET, this entry will start you
down memory lane ... starting with $C000 of course!
We encourage you to try and grok the obfuscated expression on line 56,
after C pre-processor gets finished with it!
You will need to download the ROM contents to use the emulator in PET
mode.
wget http://www.zimmers.net/anonftp/pub/cbm/firmware/computers/pet/basic-2-c000.901465-01.bin
wget http://www.zimmers.net/anonftp/pub/cbm/firmware/computers/pet/basic-2-d000.901465-02.bin
wget http://www.zimmers.net/anonftp/pub/cbm/firmware/computers/pet/edit-2-n.901447-24.bin
wget http://www.zimmers.net/anonftp/pub/cbm/firmware/computers/pet/kernal-2.901465-03.bin
dd bs=2k count=1 if=/dev/zero of=nullfill.bin
cat basic-2-c000.901465-01.bin basic-2-d000.901465-02.bin edit-2-n.901447-24.bin nullfill.bin kernal-2.901465-03.bin >pet.rom
### To build
cc -o sykes sykes.c -lcurses
### To run
sykes binary_file
### Author's comments
This program is not only a complete 6502 processor emulator, but also an
emulation of the Commodore PET 2001.
This is the second version of the same entry, but this one takes care to
not include any possibly copyrighted items in the info files, to be sure
to not infringe the rules.
### Test
Compile the program, then test the 6502 emulation like this:
./prog 6502test
A basic test is done for each instruction and addressing mode, all tests
should pass. At the end of the tests, it loops forever - break out with
control-C.
### PET EMULATION
Cast your mind back to 1977... a little company called Commodore
introduced the "PET", the Personal Electronic Transactor.
The machine was a hit, and history was made.
Now you can re-live those wonderful times with this PET emulator!
To emulate the PET, you must download the pet rom. Use the script
provided (fetchrom), it will fetch the parts from right place, and will
compile it into the file pet.rom.
Or if you don't have wget, navigate to here:
<http://www.zimmers.net/anonftp/pub/cbm/firmware/computers/pet/>
and fetch the files basic-2-c000.901465-01.bin,
basic-2-d000.901465-02.bin, edit-2-n.901447-24.bin,
kernal-2.901465-03.bin. Concatenate them in that order into one pet.rom
file, adding a 2048 byte filler in between the edit-2 and kernal-2
files. The resulting file should be 16384 bytes.
Make sure you have a terminal window of 40x25 chars or bigger, and then
run the emulator like this:
./prog pet.rom
You should see the startup message. Try typing in some BASIC - for
instance:
PRINT "HELLO, WORLD"
There is an optional numeric parameter, which controls the speed. For a
slower cursor blink, try
./prog pet.rom 6
and for faster
./prog pet.rom 2
the default is 4.
The control keys are as follows:
^A HOME
^L CLR
^R RVS
^E OFF
^Y INST
^X STOP (break)
^F cursor forward
^B cursor back
^N cursor down
Supplied also is a short demo program written in BASIC. Try typing
LOAD "DEMO"
RUN
Many other old programs will run in this emulator too. Files with a .PRG
extension should work. (Look, for instance, here:
<http://www.zimmers.net/anonftp/pub/cbm/pet/ALLFILES.html>,
or try this one: <http://www.zimmers.net/anonftp/pub/cbm/pet/games/english/dungeon.prg>)
The filenames must be upper case in order to be loaded by the emulator.
You can save programs too - try
10 PRINT "HELLO!"
SAVE "HELLO"
NEW
LOAD "HELLO"
RUN
You also might try typing this to see an ancient easter egg:
WAIT 6502,12
### 6502 EMULATION
The program is basically a 6502 emulator, and it does NOT need the
commodore rom to work.
Supplied as a demonstration is a compiled-for-6502 version a chess
program (heh, I found a use for a previous losing entry :). Try:
./prog chess
It works as you would expect (it plays very badly). There's no castling
or en-passant, and to win you must actually take the opponent's king.
You can write your own programs too, any 6502 assembler should work.
The emulator loads the supplied file at $C000, and starts execution from
that address also (the reset vector is ignored).
The screen memory begins at $8000, and is 40 columns * 25 rows.
Keypresses appear when they occur in memory location $A2, and are OR'd
with $80 - this is a way of indicating a fresh character. The program
can frequently check this byte, and when it sees a new character, it can
AND it with $7F to indicate that it has been read.
The 6502 emulator receives an interrupt 60 times a second or so, you may
want to disable interrupts (with SEI) if you do not need this.
In 6502 emulation mode the special PET character codes are not used and
the screen understands normal ASCII.
Lastly, the before emulation starts, the low byte from a time() call is
placed at address 0 - this can be used as a random seed.
### Technical description
Most of the program comprises the 6502 emulator. Curses is used for the
screen and keyboard handling.
Much of the obfuscation comes from the need to squeeze in the 6502
emulation as well as faking enough of the PET hardware for it to work.
If the supplied file is exactly 16384 bytes, the emulator assumes it is
a PET rom, and goes into PET emulation mode. Otherwise some PET specific
features are skipped during normal 6502 emulation.
The main processing all happens in a heroic expression containing no
less than 64 ternery operators (after cpp) starting on line 56. This
decodes the 6502 instructions according to a table and executes them.
The addressing mode is decoded in a similar expression starting on line
53.
### Bugs
The machine emulated is an older 40 column PET, so 80 column programs
will not show correctly.
There is no emulation of PET graphics characters.
The parameter controls the speed of the 60Hz "jiffy clock", and not the
processor speed. This means many games may run too fast to be usable -
it really depends on the speed of your machine.
Although the PET emulator can do LOAD and SAVE, it cannot VERIFY or OPEN
and CLOSE files.
The PET hardware emulation is not at all complete - features such as the
hardware timers are completely missing. Some programs will not run
correctly.
The 6502 emulation does not include the seldom used decimal mode, or any
of the "undocumented" instructions.
### IMPORTANT NOTE
I think it is great fun to run the PET emulation and mess around with
Microsoft BASIC. However, this obviously needs the rom file to work. My
program is original and completely free of any copyright, but, of
course, the pet rom is not my work. So I ask the user to download it
from the internet. This is to avoid directly infringing any copyright.
### Finally
What does this do?
./prog pet.rom -1
Have fun!
+66
View File
@@ -0,0 +1,66 @@
#include <stdio.h>
#include <string.h>
#include <curses.h>
#define P *p
#define E (s?s-1?s-2?
#define T (s=fgetc(g))
#define _ m[n&
#define L R(
#define b ):L
#define G ):(
#define r =t&
#define F _++k+O]
#define W t--?t--?
#define Y _ k--+O]=
#define M W W W W W W W
#define J *E&D:&V:&I:&C)
#define q C|Z|I|D|B|V|S|32
#define H E Z:C:V:S)&&(d+=P&l?P-O:P)
#define U(z,w)(t=w,d+=z,_ t]+_ t+1]*O)
int d,C,Z,I,D,B,V,S,i=49152
,t,s,o,h,z,O=256,n=65535,l=128,f=255,e,w; unsigned char*p,m[65536],a,x,y,k,*u,
*j=" ./ p/ 7 ] . 6 6 p t7 r(0)1*+2,4WgcovGn^f_NVO>F?T\\swldiHZYI9QJ"
"RCKSL[b<D8AP:;a@`BXq3j=- HZYI9QJRCKSL[b<D8AP:;a@`BX 57 ; ; ; ; "
" ; "
" )< <% ><% <% '< <% +< <% 7$ ($A @$A "
"($A &$ $A *$ $A C2 2; =2; 62; '2 2; +2 2; D# #B ?#B 6#B &# #B "
"*# #B F HFG 1 L HFG 'F HFG NFM F :89 :89 J8I :89 &8 :89 +8K :89 ., "
".,/ 5,0 .,/ ', ,/ +, ,/ -E -E3 4E -E3 &E E3 *E E3 2133024425660788"
; R(x){ Z=x?0:2; S=x&l; } K(x){ R(x-P); C=x<P?0:1; } A(){ R(t=F); C r 1; Z r 2
; I r 4; D r 8; B r 16; V r 64; } X( ){ Y d/O; Y d; } N( ){ X( ); Y q; I=4; d=
U(0,n-1); } main(int c,char*v[])
{ FILE*g ; _ z]=time(0); g=fopen(
c>1?v[1]:"", j+32); t=i; if(g) { ;
for(; T+1;
_ t++ ]=s);
w r /* ### COMMODORE BASIC ### */n ;
d=w?i: U(C, n
-3); /* READY. */z=c>
2?atoi( v[2])+1
:4; c=z ? n * z
/ 4 : n; nodelay(
initscr( ), 1 ) ;
curs_set(I); cbreak(); noecho( ) ; for (; ;
) { o++ % ( c *4) ?h :( h= getch () ,h-ERR?(_
162]=h|l):0); if(!w){ s=(_ 59408]
|=z?l:0)&15; _ 59410]=~(h-ERR?(s^8?0:j[h|l]&1)|(j[h]/8
-5-s?0:1<<j[h]%8):0); } o%c|I||N(); p=m +O+O+ _ l-9]; t
=d%65493; i=_ d++]; if(w+t<4){ if(P&&(u=strchr(++p,34)))
{ *u=0; _ l-9]=u-m+1; if(g=fopen(p,t?j+61:j+32)){ i=1025
-t; if(!t){ T; for(T; T+1; _ i++]=s); for(p=m+42; p<m+47 ;
){ P++=i%O; P++=i/O; } } for(; t; fputc(_ i],g))t=_++i]?3:t
-1; fclose(g); } } i=96; } t=j[i/2&14|i&1|O+O]&15; e=W W W W
U(2,d)+(i-190?x:y):U(2,d)+y:f&_ d++]+(i-150&&i-182?x:y):U(1,_ d
])+y:U(2,d):_ d++]:d++:U(1, _ d ] + x & f ):&a - m; p=e
+m; s=i>>6; t=j[i+O]-35; M M M W 0 : L a = y G k = x G L
a=x)G L x = k ) G L y=a)G L x = a ) G P =y G P = x G P
=a G t=a-P-1+C,C r O?0:1,V=((a^ P ) & ( a ^ t )&l)/2 , L a r
f)G d=F,d+=F*O+1 G A(),d=F,d|=F*O G t=P,L P=P/2|C*l),C r 1 G t=P,L P=P*2|
C),C=t/l):A(b a=F G Y q G Y a G L a|=P)G C=P&1,L P/=2)G L y=P)b x=P b a=P G
s=U(1,--d),X(),d=s G d=i&32?U(0,e):e b++y b++x b++P b a^=P b--y b--x b--P):
K(y):K(x):K(a G J=0 G J=E 8:8:4:1)G d--,B=16,N() G L a&P),V=P&64
,S=P&l):!H:H:(C=P/l,L P*=2)b a&=P G t=a+P+C,C r O?1:0,V=(~(a^P)&
(a^t)&l)/2,L a r f)); t=e^O*O/2; if(t<1000){ s=P%l; i=A_REVERSE; P>s?attron(i)
:attroff(i); mvaddch(t/40,t%40,s+w<32?s+64:s>95+w?s-32:s); } } } perror(*v); }
Binary file not shown.
+66
View File
@@ -0,0 +1,66 @@
#include <stdio.h>
#include <string.h>
#include <curses.h>
#define P *p
#define E (s?s-1?s-2?
#define T (s=fgetc(g))
#define _ m[n&
#define L R(
#define b ):L
#define G ):(
#define r =t&
#define F _++k+O]
#define W t--?t--?
#define Y _ k--+O]=
#define M W W W W W W W
#define J *E &D:&V:&I:&C)
#define q C|Z|I|D|B|V|S|32
#define H E Z:C:V:S)&&(d+=P&l?P-O:P)
#define U(z,w)(t=w,d+=z,_ t]+_ t+1]*O)
int d,C,Z,I,D,B,V,S,i=49152
,t,s,o,h,z,O=256,n=65535,l=128,f=255,e,w; unsigned char*p,m[65536],a,x,y,k,*u,
*j=" ./ p/ 7 ] . 6 6 p t7 r(0)1*+2,4WgcovGn^f_NVO>F?T\\swldiHZYI9QJ"
"RCKSL[b<D8AP:;a@`BXq3j=- HZYI9QJRCKSL[b<D8AP:;a@`BX 57 ; ; ; ; "
" ; "
" )< <% ><% <% '< <% +< <% 7$ ($A @$A "
"($A &$ $A *$ $A C2 2; =2; 62; '2 2; +2 2; D# #B ?#B 6#B &# #B "
"*# #B F HFG 1 L HFG 'F HFG NFM F :89 :89 J8I :89 &8 :89 +8K :89 ., "
".,/ 5,0 .,/ ', ,/ +, ,/ -E -E3 4E -E3 &E E3 *E E3 2133024425660788"
; R(x){ Z=x?0:2; S=x&l; } K(x){ R(x-P); C=x<P?0:1; } A(){ R(t=F); C r 1; Z r 2
; I r 4; D r 8; B r 16; V r 64; } X( ){ Y d/O; Y d; } N( ){ X( ); Y q; I=4; d=
U(0,n-1); } main(int c,char*v[])
{ FILE*g ; _ z]=time(0); g=fopen(
c>1?v[1]:"", j+32); t=i; if(g) { ;
for(; T+1;
_ t++ ]=s);
w r /* ### COMMODORE BASIC ### */n ;
d=w?i: U(C, n
-3); /* READY. */z=c>
2?atoi( v[2])+1
:4; c=z ? n * z
/ 4 : n; nodelay(
initscr( ), 1 ) ;
curs_set(I); cbreak(); noecho( ) ; for (; ;
) { o++ % ( c *4) ?h :( h= getch () ,h-ERR?(_
162]=h|l):0); if(!w){ s=(_ 59408]
|=z?l:0)&15; _ 59410]=~(h-ERR?(s^8?0:j[h|l]&1)|(j[h]/8
-5-s?0:1<<j[h]%8):0); } o%c|I||N(); p=m +O+O+ _ l-9]; t
=d%65493; i=_ d++]; if(w+t<4){ if(P&&(u=strchr(++p,34)))
{ *u=0; _ l-9]=u-m+1; if(g=fopen(p,t?j+61:j+32)){ i=1025
-t; if(!t){ T; for(T; T+1; _ i++]=s); for(p=m+42; p<m+47 ;
){ P++=i%O; P++=i/O; } } for(; t; fputc(_ i],g))t=_++i]?3:t
-1; fclose(g); } } i=96; } t=j[i/2&14|i&1|O+O]&15; e=W W W W
U(2,d)+(i-190?x:y):U(2,d)+y:f&_ d++]+(i-150&&i-182?x:y):U(1,_ d
])+y:U(2,d):_ d++]:d++:U(1, _ d ] + x & f ):&a - m; p=e
+m; s=i>>6; t=j[i+O]-35; M M M W 0 : L a = y G k = x G L
a=x)G L x = k ) G L y=a)G L x = a ) G P =y G P = x G P
=a G t=a-P-1+C,C r O?0:1,V=((a^ P ) & ( a ^ t )&l)/2 , L a r
f)G d=F+F*O+1 G A(),d=F+F*O G t=P,L P=P/2|C*l),C r 1 G t=P,L P=P*2|C),C=t
/l):A(b a=F G Y q G Y a G L a|=P)G C=P&1,L P/=2)G L y=P)b x=P b a=P G s=U(1
,--d),X(),d=s G d=i&32?U(0,e):e b++y b++x b++P b a^=P b--y b--x b--P):K(y):
K(x):K(a G J=0 G J=E 8:8:4:1)G d--,B=16,N() G L a&P),V=P&64,S=P&
l):!H:H:(C=P/l,L P*=2)b a&=P G t=a+P+C,C r O?1:0,V=(~(a^P)&(a^t)
&l)/2, L a r f)); t=e^O*O/2; if (t<1000) { s=P%l; i=A_REVERSE; P>s ? attron(i)
:attroff(i); mvaddch(t/40,t%40,s+w<32?s+64:s>95+w?s-32:s); } } } perror(*v); }
+15
View File
@@ -0,0 +1,15 @@
build: timwi
clean:
clobber:
-rm timwi
timwi: timwi.c
${CC} ${CFLAGS} ${LDFLAGS} $< -o $@
alt:
data:
+84
View File
@@ -0,0 +1,84 @@
# Most discourteous interpreter
Arne "Timwi" Heizmann
Germany
timwi@gmx.net
## Judges' notes
### To build
cc timwi.c -o timwi
### To run
timwi < bf_program
Unlike most BF interpreters that we have been receiving for the last few
years, this one, in our opinion, is the most obfuscated albeit the most
discourteous to the language it interprets. A simple 3-character fix will make
it slightly less so.
Quite a few BF programs found on the Net expect byte-based memory, quite a few
exceed the capacity of this interpreter, but there are many that work. Some
small quines work, some don't.
Why?
## Selected notes from the author
This is an interpreter for the programming language BrainFuck (BF).
Input must be provided in the following format: First a sequence of integers
separated by whitespace (this will be the input to the BF program), then a
colon (:), then the BF program itself.
Example:
(echo "20 : ,-->+.>+.<<[>[>>+>+<<<-]>[>>+>+<<<-]>";
echo "[<+>-]>[<<<+>>>-]>[-]<<<<.<-]") | timwi
This will print the first 20 Fibonacci numbers.
You must not pass any command-line arguments.
### Features
* Supports the complete set of 8 BF instructions (+-<>[].,).
* Supports the use of alternative characters for some of those instructions.
Use this to obfuscate your BF programs!
For a challenge, figure out what this obfuscated BF program does:
J4mzt?Vazexx-20d~&&~AxdUV!x(~Jz&V)x*(P=J)JUN(dizz)xx_!xx'0&{Vz;}&Jj
It takes two integers as input and outputs one integer.
* Ignores all whitespace (newlines, spaces and tabs) in the input program.
### Limitations
Since the program, naturally, uses ints, the calculations must not exceed the
range of an int. (But then again, you can use the integer overflow to further
obfuscate your BF programs in creative ways!)
You are limited to 3125 input integers and 3125 instructions. If you exceed
one of these limits, the behaviour is undefined.
### Obfuscations
Some of the superficial obfuscations are pretty obvious: I'm using #defines to
make everything look nice and liney, and the program is merely a recursive
main function with only a single 'return' statement which uses nested ternary
operators to make even the pre-processed code unreadable.
However, the more subtle obfuscations relate to the way the program works.
After applying the pre-processing, you will see a lot of "1+1+1+...etc.", and
even if you replace these with their result, those numbers will still not
represent (or even relate to) the ASCII codes of the BF instructions.
The program will first read in all the input integers, but it will begin
execution immediately and only read program instructions as they are needed.
Yet there is no global variable storing how far it has read! Perhaps the
hardest thing to figure out is how it finds the matching square brackets.
+26
View File
@@ -0,0 +1,26 @@
#include <stdio.h>
#define _ main(
#define _l ___l ___l ___l ___l ___)
#define __l int
#define ___l ___)*(
#define ____l (_l],
#define ____ 1
#define ___ __+_____
#define __ ____+____
#define _____ __+____
#define ______1 *(l__
#define _____1 *__1%(__
#define ____1 )?(
#define ___1 _1&(__
__l __I[____l _I[____l*l__=_I,*l_=__I;__l _ __l _1,__l*__1){__l _l_;
return ___1+ __ ____1 ___1 ____1*__1 = getchar()):__ ____1*__1<____?
____:_____1+___ ____1 _____1+_____ ____1 _____1+____)____1 ___1+___+
____ ____1 _____1 +__)____1 _____1 )____1 *l__)++:_____1+____)-____?
______1 ++) :_____1+_____) -____?__:printf("%d\n",*l__):_____1+____+
___ ____1 *l__) =*(l_++ ):__:___l ____- ____):_____1 +_____)-3?__-2:
____:(___1+____+___ ____1 _____1)____1*l__)-- :_____1+__)?__:______1
--):___l 0))?__:_ _1,__1+____)+____:(___1+____+___ )) &&* l__?_ ___1
+___+___+__),__1+____)?_ ___1+11 )|(___1)?____:__- 2),__1):____-1 :(
_l_=_ ___1 -____+___l ____),__1+____ )) ?_l_+_ ___1 )?_1 :___1+10)|(
___1-____ ____1 __):0),__1+_l_):0):__:_1%(__ ____1 _1/(__)) ?_ scanf
("%i",__1 ____1 _____):(___l _____)-____,__1 +____):_ _____,l_):__;}
+18
View File
@@ -0,0 +1,18 @@
build: toledo
clean:
clobber:
-rm toledo toledo2
toledo: toledo.c
${CC} ${CFLAGS} ${LDFLAGS} $< -o $@
alt: toledo2
toledo2: toledo2.c
${CC} ${CFLAGS} ${LDFLAGS} $< -o $@
data:
+117
View File
@@ -0,0 +1,117 @@
# Best game
Oscar Toledo G.
Familia Toledo
Av. Santa Cruz del Monte 9-304
Ciudad Satelite Edo de Mexico
CP 53110
Mexico
uno@biyubi.com
## Judges' comments
Challenge yourself with your ability to look 5, 6 or more moves ahead.
Challenge your knowledge of C operator precedence. The following the
move analysis via recursion while it executes moves. All while playing
by the rules of C and Chess within a single function!
## Improved version
Better mate searching
### To build
cc toledo.c -o toledo
### To run
For two human players
toledo
To play against the program
toledo a
## Author's comments
### What does this program
This is a chess program, it can work in two modes: two-players, and one player
(always white) against the machine. To get the first mode, run the program
without arguments:
prog
The other mode is accesible running the program with one argument (5-ply
analysis):
prog a
Two arguments for 6-ply analysis:
prog a b
And each succesive argument will analyze one ply more. There is no ply limit,
but beyond 7 ply is very slow, try it at your own risk and computing time.
### Entering movements
When is your turn, you can enter your move, by example, as "d2d4" (without the
quotes) and press the Enter key, the computer will check move legality and
will warn you of illegal moves. All legal chess moves are permitted.
One special case is when you are doing promotion, you must enter the move with
an extra letter indicating the desired piece.
By example "f7f8n" (supossing you have a pawn on f7), will promote it to a
knight, substitute 'n' for the desired piece (N/Q/R/B).
Note that the program requires the piece letter, it will not select
automatically a queen, so don't be surprised if it doesn't accept your move.
### Game status
The computer will check for checkmate and stalemate, also after each machine
move, it will show the score of the position, an higher number is better for
the computer, i.e. worst for you.
### Quirks
None.
### Program operation
This is a good example of a chess program reduced to the essential. In order
to get it into the contest limits, I used short but slow and unintelligible
algorithms.
The interface accounts for only a fraction of the code, the core does
multiples functions, it is called recursively to analyze and evaluate each
ply, does alpha-beta cutting, move generation, machine playing, check
detection, illegal move verification and does moves after they are verified.
Also sets an standard on ultra-mini-chess programs, the player and the
computer can do all legal chess moves, other features are:
* Illegal move verification.
* Checkmate detection.
* Stalemate detection.
* Computer is tough (check 7-ply), even in 5 ply can give a surprise to
amateur players.
### Obsfucation tricks
* Only one C function, really modular.
* Extensive use of the trinary and comma operators, save a hard drive today.
* Extensive use of C operator precedence, all good C programmers remember
it... I cannot.
* Exchanged operands every place is possible, someday someone will
understand it,
* Mixed and multifunction expressions on statements, in good old-BASIC
style.
* Macros used to hide C syntax, check unballanced parenthesis and calls with
empty arguments!
* Only includes strictly necessary standard headers, the linker takes care,
and compiles faster... but I'm still not seeing the difference.
* Uses only one string, very easy to I18N ;)
+64
View File
@@ -0,0 +1,64 @@
#define F getchar())
#define H(z)*n++=z;
#include <setjmp.h>
#define v main(0,0,0
#define Z while(
#define _ if(
#define o(d) (u[l]=0,l[d]=6^e,q=1e4>v,0),l[d]=0,u[l]=e^6,q)
#define I(H,n) { _ r=l[x=H],!r|(r^e)<-1){ _ j=u[l],-7==r|6==r\
){ n; e=~e; return 1e5- f; } u[l]=0,t=j+1,i=j-1; _!i&89<x)i\
=j,t=6; _-1==t&30>x)t=j,i=-7; Z++i<t){ b=S; d=0; S&=63; \
a=((j^e)!=1?6!=(j^e)?O[32+x/10]-O[u/10+32]-q:(S|=6!=j?8\
:1,2==u-x)*9+9*(x-u==2):(d=1==j?x-u:u-x)/8+!(!((x-u)%\
10)|r)*99+(j==1?90<x:29>x)*(9*O[28+i]-288))+O[r+28\
]*9-288+O[x%10+33]-f-O[33+u%10]; x[l]=i; S|=(21=\
=u|21==x)*2+(u==28|28==x)*4+(91==u|x==91)*16+32\
*(u==98|x==98)+(20==d)*64*x; a-=k>f?main(a,f+1\
,M,k):0; _ i==c&u==h&!f&N&a>-1e4&x==y)longjm\
p(z,1); S=b; _!N|f&&(a>M||!f&a==M&&1&rand()\
)){ _!f){ _ k){ c=i; h=u; y=x; } } else _ \
L-a<N){ n; e=~e; u[l]=j; x[l]=r; return\
a; } M=a; } } x[l]=r; u[l]=j; n; } }
typedef int G; char J [ 78 ], O [ ]
= "HRQAMS#-smaqrh[UTZYTU[|TBA("
"$#(ABT|ba`gg`ab8>GK[_`fFDZXEYR" "L\t####"
"##B#A#@#G#F#E#D#K\t\3Zlv#tjm" "\3J#tjm\3Pwb"
"ofnbwf\3Joofdbo\3)&`&`.&`&`" "#+&g*\t"; G y,
c,h,e,S,*s,l[149]; jmp_buf z ; G main(G L,G f,
G N,G k){ G u=99,p,q,r,j,i,x ,t, a, b,d,M=-1e9
; char *n; if( *l){ e=~e; Z u >21){ q= l[--u]^e;
_!-- q){ _!l[p=e?u-10:u+10]){ I(p,)_ e?u>80 & !l[p
-=10]:u<39&!l[p+=10])I(p,)} _ l[p=e?u-11:9+u] )I(p,)
else _ u-1==S>>6){ l[u-1]=0; I(p,l[u-1]=-2^e); } _ l[
p=e?u-9:11+u])I(p,)else _ S>>6==1+u){ l[1+u]=0; I(p,l
[1+u]=e^-2); } } _!--q){ n=O+41; Z++n<50+O)I(u+80-*n,
)} _ 0<q&4>q){ n=q==2?53+O:O+49; Z++n<O+(q!=1)*4+54
){ p=u; do I(p-=*n-80,)Z!p[l]); } } _ 4==q){ n=49+O
; Z++n<O+58)I(u-*n+80,)_ e&!(S&24)|!e&!(S&3)&&k&&
!l[u-2]&!l[u-1]&!l[u-3]&&o(u)&o(u-1)){ l[u-1]= 4
^e; l[u-4]=0; I(u-2,l[u-1]=0; l[u-4]=e^4); } _
e&!(S&40)|!e&!(S&5)&&k&&!l[u+1]&!l[2+u]&&o(u)&
o(1+u)){ l[u+1]=e^4; l[3+u]=0; I(u+2,l[1+u
]=0; l[u+3]=4^e); } } } e=~e; return M; }
Z h<130){l[h]=-(21>h|98<h|2 >(h+1 )%
10); O[h++]^=3; } n=O +14; s=20+l; Z
++s<29+l){ 10[s]=1; 70[s]=~ ( * s = *
n++ -+84); 60 [ s] =-2; } Z n=J){ puts
(58+O); u=19; Z++u<100){ H(32)_!( u%10
))H(32)H(O[7+l[u]])_(9+u)%10>7){ H(58
-u/10)H(32)_ u&1)puts(n=J); } } puts
(O+58); _-1e4 >v , 1)){ e=~e; puts
(O+(v,0)> 1e4?e?90:82:96)); break
; } _ 1<L&e) { d=v,2+L); printf
(O+114,h%10+64,58-h/10,y%10+64
,58 -y/10,d); } else{ putchar
(62 ) ; h= (95 & F-44; c=l[h
+=(56-F *10]; y=(95&F-44; y
+=(56-F*10; Z 10!=(u=(95
&F)){ c=5; Z--c>1&&u!=c
[O]); c=e^c-7; } } _!
setjmp(z)){ v+1,1);
puts( 106+
O); } } Z
10!=
F; }
+64
View File
@@ -0,0 +1,64 @@
#define F getchar())
#define H(z)*n++=z;
#include <setjmp.h>
#define v main(0,0,0
#define Z while(
#define _ if(
#define o(d)(S=63,l[d]=6^e,q=1e4>v,u[l]=0),l[d]=0,u[l]=e^6,S=b,q)
#define I(H,n) { _ r=l[x=H],!r|(r^e)<-1){ _ j=u[l],-7==r|6==r\
){ n; e=~e; return 1e5-443*f; } u[l]=0,t=j+1,i=j-1; _!i&89<\
x)i=j,t=6; _-1==t&30>x)t=j,i=-7; Z++i<t){ d =0; S&= 63; \
a=((j^e)!=1?6!=(j^e)?O[32+x/10]-O[u/10+32]-q:(S|=6!=j?8\
:1,2==u-x)*9+9*(x-u==2):(d=1==j?x-u:u-x)/8+!(!((x-u)%\
10)|r)*99+(j==1?90<x:29>x)*(9*O[28+i]-288))+O[r+28\
]*9-288+O[x%10+33]-f-O[33+u%10]; x[l]=i; S|=(21=\
=u|21==x)*2+(u==28|28==x)*4+(91==u|x==91)*16+32\
*(u==98|x==98)+(20==d)*64*x; a-=k>f?main(a,f+1\
,M,k):0; _ i==c&u==h&!f&N&a>-1e4&x==y)longjm\
p(z,1); S=b; _!N|f&&(a>M||!f&a==M&&1&rand()\
)){ _!f){ _ k){ c=i; h=u; y=x; } } else _ \
L-a<N){ n; e=~e; u[l]=j; x[l]=r; return\
a; } M=a; } } x[l]=r; u[l]=j; n; } }
typedef int G; char J [ 78 ], O [ ]
= "HRQAMS#-smaqrh[UTZYTU[|TBA("
"$#(ABT|ba`gg`ab8>GK[_`fFDZXEYR" "L\t####"
"##B#A#@#G#F#E#D#K\t\3Zlv#tjm" "\3J#tjm\3Pwb"
"ofnbwf\3Joofdbo\3)&`&`.&`&`" "#+&g*\t"; G y,
c,h,e,S,*s,l[149]; jmp_buf z ; G main(G L,G f,
G N,G k){ G u=99,p,q,r,j,i,x ,t,a,b=S,d,M=-1e9
; char *n; if( *l){ e=~e; Z u >21){ q= l[--u]^e;
_!-- q){ _!l[p=e?u-10:u+10]){ I(p,)_ e?u>80 & !l[p
-=10]:u<39&!l[p+=10])I(p,)} _ l[p=e?u-11:9+u] )I(p,)
else _ u-1==S>>6){ l[u-1]=0; I(p,l[u-1]=-2^e); } _ l[
p=e?u-9:11+u])I(p,)else _ S>>6==1+u){ l[1+u]=0; I(p,l
[1+u]=e^-2); } } _!--q){ n=O+41; Z++n<50+O)I(u+80-*n,
)} _ 0<q&4>q){ n=q==2?53+O:O+49; Z++n<O+(q!=1)*4+54
){ p=u; do I(p-=*n-80,)Z!p[l]); } } _ 4==q){ n=49+O
; Z++n<O+58)I(u-*n+80,)_ e&!(S&24)|!e&!(S&3) &&
!l[u-2]&!l[u-1]&!l[u-3]&&o(u)&o(u-1)){ l[u-1]= 4
^e; l[u-4]=0; I(u-2,l[u-1]=0; l[u-4]=e^4); } _
e&!(S&40)|!e&!(S&5) &&!l[u+1]&!l[2+u]&&o(u)&
o(1+u)){ l[u+1]=e^4; l[3+u]=0; I(u+2,l[1+u
]=0; l[u+3]=4^e); } } } e=~e; return M; }
Z h<130){l[h]=-(21>h|98<h|2 >(h+1 )%
10); O[h++]^=3; } n=O +14; s=20+l; Z
++s<29+l){ 10[s]=1; 70[s]=~ ( * s = *
n++ -+84); 60 [ s] =-2; } Z n=J){ puts
(58+O); u=19; Z++u<100){ H(32)_!( u%10
))H(32)H(O[7+l[u]])_(9+u)%10>7){ H(58
-u/10)H(32)_ u&1)puts(n=J); } } puts
(O+58); _-1e4 >v , 1)){ e=~e; puts
(O+(v,0)> 1e4?e?90:82:96)); break
; } _ 1<L&e) { d=v,2+L); printf
(O+114,h%10+64,58-h/10,y%10+64
,58 -y/10,d); } else{ putchar
(62 ) ; h= (95 & F-44; c=l[h
+=(56-F *10]; y=(95&F-44; y
+=(56-F*10; Z 10!=(u=(95
&F)){ c=5; Z--c>1&&u!=c
[O]); c=e^c-7; } } _!
setjmp(z)){ v+1,1);
puts( 106+
O); } } Z
10!=
F; }
+64
View File
@@ -0,0 +1,64 @@
#define F getchar())
#define H(z)*n++=z;
#include <setjmp.h>
#define v main(0,0,0
#define Z while(
#define _ if(
#define o(d)(S=63,u[l]=0,l[d]=6^e,q=1e4>v,0),l[d]=0,u[l]=e^6,S=b,q)
#define I(H,n) { _ r=l[x=H],!r|(r^e)<-1){ _ j=u[l],-7==r|6==r\
){ n; e=~e; return 1e5-443*f; } u[l]=0,t=j+1,i=j-1; _!i&89<\
x)i=j,t=6; _-1==t&30>x)t=j,i=-7; Z++i<t){ d =0; S&= 63; \
a=((j^e)!=1?6!=(j^e)?O[32+x/10]-O[u/10+32]-q:(S|=6!=j?8\
:1,2==u-x)*9+9*(x-u==2):(d=1==j?x-u:u-x)/8+!(!((x-u)%\
10)|r)*99+(j==1?90<x:29>x)*(9*O[28+i]-288))+O[r+28\
]*9-288+O[x%10+33]-f-O[33+u%10]; x[l]=i; S|=(21=\
=u|21==x)*2+(u==28|28==x)*4+(91==u|x==91)*16+32\
*(u==98|x==98)+(20==d)*64*x; a-=k>f?main(a,f+1\
,M,k):0; _ i==c&u==h&!f&N&a>-1e4&x==y)longjm\
p(z,1); S=b; _!N|f&&(a>M||!f&a==M&&1&rand()\
)){ _!f){ _ k){ c=i; h=u; y=x; } } else _ \
L-a<N){ n; e=~e; u[l]=j; x[l]=r; return\
a; } M=a; } } x[l]=r; u[l]=j; n; } }
typedef int G; char J [ 78 ], O [ ]
= "HRQAMS#-smaqrh[UTZYTU[|TBA("
"$#(ABT|ba`gg`ab8>GK[_`fFDZXEYR" "L\t####"
"##B#A#@#G#F#E#D#K\t\3Zlv#tjm" "\3J#tjm\3Pwb"
"ofnbwf\3Joofdbo\3)&`&`.&`&`" "#+&g*\t"; G y,
c,h,e,S,*s,l[149]; jmp_buf z ; G main(G L,G f,
G N,G k){ G u=99,p,q,r,j,i,x ,t,a,b=S,d,M=-1e9
; char *n; if( *l){ e=~e; Z u >21){ q= l[--u]^e;
_!-- q){ _!l[p=e?u-10:u+10]){ I(p,)_ e?u>80 & !l[p
-=10]:u<39&!l[p+=10])I(p,)} _ l[p=e?u-11:9+u] )I(p,)
else _ u-1==S>>6){ l[u-1]=0; I(p,l[u-1]=-2^e); } _ l[
p=e?u-9:11+u])I(p,)else _ S>>6==1+u){ l[1+u]=0; I(p,l
[1+u]=e^-2); } } _!--q){ n=O+41; Z++n<50+O)I(u+80-*n,
)} _ 0<q&4>q){ n=q==2?53+O:O+49; Z++n<O+(q!=1)*4+54
){ p=u; do I(p-=*n-80,)Z!p[l]); } } _ 4==q){ n=49+O
; Z++n<O+58)I(u-*n+80,)_ e&!(S&24)|!e&!(S&3) &&
!l[u-2]&!l[u-1]&!l[u-3]&&o(u)&&o(u-1)){ l[u-1]=4
^e; l[u-4]=0; I(u-2,l[u-1]=0; l[u-4]=e^4); } _
e&!(S&40)|!e&!(S&5) &&!l[u+1]&!l[2+u]&&o(u)&&
o(1+u)){ l[u+1]=e^4; l[3+u]=0; I(u+2,l[1+u
]=0; l[u+3]=4^e); } } } e=~e; return M; }
Z h<130){l[h]=-(21>h|98<h|2 >(h+1 )%
10); O[h++]^=3; } n=O +14; s=20+l; Z
++s<29+l){ 10[s]=1; 70[s]=~ ( * s = *
n++ -+84); 60 [ s] =-2; } Z n=J){ puts
(58+O); u=19; Z++u<100){ H(32)_!( u%10
))H(32)H(O[7+l[u]])_(9+u)%10>7){ H(58
-u/10)H(32)_ u&1)puts(n=J); } } puts
(O+58); _-1e4 >v , 1)){ e=~e; puts
(O+(v,0)> 1e4?e?90:82:96)); break
; } _ 1<L&e) { d=v,2+L); printf
(O+114,h%10+64,58-h/10,y%10+64
,58 -y/10,d); } else{ putchar
(62+e); h= (95 & F-44; c=l[h
+=(56-F *10]; y=(95&F-44; y
+=(56-F*10; Z 10!=(u=(95
&F)){ c=5; Z--c>1&&u!=c
[O]); c=e^c-7; } } _!
setjmp(z)){ v+1,1);
puts( 106+
O); } } Z
10!=
F; }
+15
View File
@@ -0,0 +1,15 @@
LDFLAGS+=-L${X11_LIBDIR} -lX11 -lm
build: vik
clean:
clobber:
-rm vik
vik: vik.c
${CC} ${CFLAGS} ${LDFLAGS} $< -o $@
alt:
data:
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

+110
View File
@@ -0,0 +1,110 @@
# Most circuitous walk
Daniel Vik
926 Genter Street
La Jolla Ca 92037
USA
daniel@vik.cc
## Judges' comments
An amazing use of the X libraries with twisty code passages,
all different. One risks running in code path circles as main is
called again and again. be sure to pay attention to commas! :-)
### To build
cc -O3 -ansi vik.c -L/usr/X11R6/lib -lX11 -lm -o vik
### To run
vik
vik maze.map
## Author's comments
This entry is a Wolfenstein style graphics engine where a user can navigate in
a 3D world. The maze has walls with bitmap textures. The application contains
a default world with textures, but the power of the engine is exposed through
user configured maps. User defined worlds support up to 26 different wall
textures that can even be animated. One example of a user defined world is
submitted with the entry.
### Features
This program is a complete 3D engine with
* Easy configurable maze maps
* Up to 26 differnt bitmap textures in a maze
* Support for animated bitmap textures
* Uses default bitmaps in case the configured bitmaps can't be found
* A default map in case no one is specified
* Configurable window size
* Navigation using cursor keys (rotate left and right, move forward and
backward)
### Build and Run
Compile the source code and link x libraries if nessecary. The program takes
three options which have to be typed in a specific order as described below.
Usage: prog [-w <width>] [mapfile]
width - Specifies the width of the window
mapfile - Filename containing a map
Here are a few examples:
> | Command line: | Description: |
> | ------------------------ | ---------------------- |
> | $ ./prog | Starts the engine using a built in labyrinth and texture bitmaps |
> | $ ./prog maze.map | Starts the engine and loads the labyrinth defined in the file maze.map |
> | $ ./prog -w 400 maze.map | Starts the engine using maze.map in a window that is 400 pixels wide |
Note that the mapfile has to be the last argument and the -w option if present
has to be the first. The map definition files and the bitmap files should be
located in the current directory.
Use the cursor keys to navigate through the labyrinth.
### Creating mazes
A maze consist of a map file and texture bitmap files. The map file is an
ascii text file where lower case letters represent walls. The letter tells the
engine what bitmap texture file to use. The '*' character lets the engine know
where to position the user. The example below shows how a map file can look:
aaaaaaaaaaaaa
a a
a * a
a bbbb cccccccc
c c
cccccccccccccccccccc
The engine loads the map, and creates walls. When a character 'a'-'z' is found,
the engine will load the corresponding texture bitmap. The bitmap file must be
named `*.bmp` where `*` is substituted with the letter of the wall in the map.
So to load the map above, the files `a.bmp`, `b.bmp`, and `c.bmp` should be
located in the same directory as the engine executable (or rather in the
current directory).
### Obfuscation
The program is obfuscated in several ways, bad use of variables, use of the ?
operator, recursive calls to main, bad use of for variables and the comma
operator. To make the final obfuscated touch I ran indent which really made
the program unreadable (I guess that is not really the intent with indent ;)
### Compiler warnings
There are no compiler warnings when compiling with -ansi but there are quite
many warnings from lclint. Mainly because the program is very optimized for
code size.
### Limitations
The program only compiles and runs on X based systems.
The program does not run that smooth under cygwin. It seems to be a priority
issue with cygwin and it can easily be solved by increasing the priority of
the application a little bit.
+18
View File
@@ -0,0 +1,18 @@
aaaaaaaaaaaaaaaaaaaaaaaaa
a a
a b a
a * a
a a
aaaaa aaaaaaaa aaaaaaaaaaaa
ccccc c a a
c c a a
c c a a a
c ccccccca a a
c ca a a
c ca a a
c caaaaaa a a
c cccc ccccccaaaaaa a
c cccc ca a
c cb a
c ca a
ccccccccccccccccccccccaaaaaaaaaaaa
+109
View File
@@ -0,0 +1,109 @@
#include<math.h>
#include<stdio.h>
#include<stdlib.h>
#include<sys/time.h>
#include<X11/Xlib.h>
#include<X11/keysym.h>
Window L;
GC N;
Display *K;
XEvent O;
XImage *Q;
float w, x, y[7 << 16];
struct timeval S, U;
int a, b, c, d =
92, e, f, g, h, i, j, k, l, m, n, o, p, *q[96], r[7 << 16], s[96], *t,
*u = r, *v, P = 256, R[64], T, J = 12288;
struct
{
int a, b, c, d, e;
} A[9999], *B, *G, *H;
unsigned char C, D[9999], *E = D, F[] = " .bmp";
FILE *I;
#define Q(o,X,Y,C)B->b=b+32*o,B->c=c+32*X,B->d=Y,B->e=C,B++->a=l,
#define D(o,X)(int)((X*(B->b-e)-o*(B->c-f))/(x*B->e-w*B->d))
int
main (int X, char **Y)
{
for (j = J << 8, x = y[i], w = y[i + 32], B = A; k = D (x, w), B->b;
k >> 8 ? 0 : (l = D (B->d, B->e), l > 0
&& l < j) ? j = l, h = k, g = B->a : 0, B++);
for (;
X
&& (p =
1 | 3 * (o = (--X < 2 || 119 - 1[Y[1]] ? 320 : atoi (2[Y]))) / 4);)
{
for (e = f = J / 2, K = XOpenDisplay (0); m < o << 8;
y[m] =
sin ((m & 255) / 20.4 + asin ((m / P - o / 2) / 3.2 / o)),
D[m & 511] = 10 + d * !(1 & (m >> 3 & m)), r[m++] =
m / 18 << (16 & (m >> 6 ^ m)));
for (N =
XCreateGC (K, L =
XCreateSimpleWindow (K, RootWindow (K, 0), 0, 0, o, p,
0, 0, 0), 0, 0), ((I =
fopen (X ?
Y[X]
: "",
"r")) ?
fread (E + 1,
1,
1 << 15,
I),
fclose (I) :
0), B = G =
A + J / 3; *++E; f = l == 32 ? e = b + 99, c + 99 : f)
for (l = *E - 10, *F = *E, k = !l, b *= !k, c += P * k, b += P;
l > 54 && l < 96
&& (Q (0, 0, 1, 0) Q (8, 0, 0, 1) Q (8, 8, -1, 0)
Q (0, 8, 0, -1)
! q[l] && (s[l] = 1, q[l] = u, I = fopen (F, "r"))); l = J)
for (q[l] = ++u + 19, m = 2;
n = (m++ % 3 ? n : 0 ** ++u) >> 8 | C << 16, *u =
n, 0 < fread (&C, 1, 1, I)
|| (m /= J, s[l] = m ? m : 1) * fclose (I););
for (XMapWindow (K, L),
XSelectInput (K, L, KeyPressMask | KeyReleaseMask), H = A; G->b;
*H = *G++, H += !B->b)
for (B = A + J / 3;
B->b && !(B != G && B->b == G->b - 128 * (B->d - G->d)
&& B->c == G->c - 128 * (B->e - G->e)); B++);
for (Q =
XCreateImage (K, DefaultVisual (K, 0), DefaultDepth (K, 0),
ZPixmap, 0, (char *) (v =
malloc (4 * o * p)), o, p,
32, 0);
d = (d + R[19] - R[17]) & 127, n = R[18] - R[20], n ? (i =
o * 128 +
d + (n <
0) *
64, main (0,
Y)
>
200) ? e +=
(int) (y[i] * 64), f += (int) (y[i + 32] * 64) : 1 : 1;
XSync (K, 0), gettimeofday (&S, 0), m = T - S.tv_usec)
{
for (T -=
(m > 0
&& m < J * 4 ? U.tv_usec =
m, select (0, 0, 0, 0, &U) : m) - 4 * J, a =
a + 1 & -1 >> 1, m = 0;
k =
1 +
(int) (p * 512 /
((i = m * P + d, g = n =
0, main (0, Y)) * y[m * P + 32])), m < o; m++)
for (t = g ? c =
64 * s[g], q[g] + h / 4 + 64 * (a / 3 % s[g]) : t;
l = 32 - (17 << (k < 2)) * (2 * n - p) / k, n < p;
v[m + o * n++] = l >> 6 ? 4477904 << (l < 0) : t[c * l]);
for (XPutImage (K, L, N, Q, 0, 0, 0, 0, o, p); XPending (K);
R[63 & XLookupKeysym (&O.xkey, 0 & XNextEvent (K, &O))] ^=
O.type == KeyPress || O.type == KeyRelease);
}
}
return j;
}
+19
View File
@@ -0,0 +1,19 @@
LDFLAGS+=-lGL -lGLU -L${X11_LIBDIR} -lX11
build: vince
clean:
clobber:
-rm vince vince.improved
vince: vince.c
${CC} ${CFLAGS} -I${X11_INCLUDEDIR} ${LDFLAGS} $< -o $@
alt: vince.improved
vince.improved: vince.improved.c
${CC} ${CFLAGS} -I${X11_INCLUDEDIR} ${LDFLAGS} $< -o $@
data:
+98
View File
@@ -0,0 +1,98 @@
# Most beauteous visuals
Vincent Weaver
Ithaca, NY
USA
vince@deater.net
<http://www.deater.net/weave/>
## Judges' comments
This beauteous entry makes use of visual {}'s and whitespace to instruct
the OpenGL development libraries to create beauteous visuals. Even
hitting the space bar while the program runs produces a "spacey" effect! :-)
Challenge: Try modifying the texture to something of your own design.
## Improved Version
This following improved version of the submission will run on SGI Irix and
also has the recursive CPP macro (which snuck in accidentally) removed.
### To build
Before building, make sure that you have the OpenGL development libraries
installed.
cc -Wall -O2 -o vince vince.c -L/usr/X11R6/lib -lGL -lGLU -lX11
If you are on a 64 bit platform you might need to substitute `-L/usr/X11R6/lib64`.
### To run
vince
Under MacOSX run from within an xterm while the X11 server is running.
## Author's comments
### ABUSE OF RULES
* The executable needs to read in its own source code in order to run. As
long as the source is in the same directory as the executable it should be
able to find it...
* The program requires the OpenGL library.
* The program abuses severely the whitespace and { } ; exceptions in the
filesize limits.
### Requirements
* OpenGL. It works (slowly) with Mesa.
* 16bpp graphics capability (but might work at other depths)
* The original source needs to be in the same directory as the executable,
and the source's name should be the same as the executable but with .c on the
end.
### Background
I was annoyed after the last IOCCC because I slaved away on a clever text
based game only to find all of the game winners used X11. X11 isn't standard
C!
So to one up them, I decided to use OpenGL. It's standard, and most Unix-like
systems these days have either accelerated graphics or else software
rendering.
### Obfuscation
It was a challenge getting the source code below the 2k limit. OpenGL has way
too many GRATUITOUSLY_LONG_CONSTANTS and glLongStudlyFunctionNames();
Therefore, much of the obfuscation comes secondary to just reducing the code
size to fit under the limit while still having some semblance of a demo.
There are some interesting abuses scattered about.
### Usage
Try hitting the spacebar when the program is running.
### For Fun
Try modifying the texture to your own custom design...
### Thanks
Many thanks to John Clemens for testing this on various machines for me.
### Errors you can get
0 = no error
1 = X problem
2 = Can't open glx
3 = Can't open 16bpp visual
4 = can't open source file
+90
View File
@@ -0,0 +1,90 @@
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <GL/glx.h>
#include <GL/glu.h>
#define E(x) { printf("%i\n",x); goto l; }
#define G fgetc(F)
#define H glEnable(
#define I glMaterialfv(GL_FRONT,
#define J glMatrixMode(
#define L (y
#define M 640,480
#define N NULL
#define O GL_DIFFUSE , i
#define P glCallList(u);
#define T glTexCoord2i
#define U glLightfv(GL_LIGHT0,
#define V R(); glVertex3i(c,m,n);
#define X GL_TEXTURE_2D
#define Z(x) G; x=G; x=x<50-(x==59);
void Y()
{ { { { { { { { { { { { { { { {
{ { { { { { { { { { {
{ { { { { {
{ { { { { { { {
{ { { { { {
{ { { { { ; { } } } } }
} } } } } } }
} } } } } }
} } } } } }
} } } } } }
} } } } } } }
} } } } } } } } } } } } } } } }
void Q()
{ { ; { { { { { { { {
{ { { { { {
{ { { { { {
; { { } } } } } } } }
} ; } } } } } } } } }
} } } } } }
FILE *F; int u,t,l,m,n,x=0,a=0,b[]={ GLX_DOUBLEBUFFER,
GLX_RGBA , GLX_DEPTH_SIZE , 16, None},o,n,c ; void R() {
Z(c); Z(m); Z(n); } int main( int _, char **A) { char f[
BUFSIZ ] ; GLXContext r ; XVisualInfo * v ; Display *y;
XEvent e ; GLfloat g=0, h=10, i[ ]= { 1,1, 1, 1, 5,5, 100
,0, .6, .6, .6 ,1 } ; XSetWindowAttributes s; GLubyte j[1
<<10] ; Window w; if(! L= XOpenDisplay ( N ) ) ) E(1) ;if
( !
glXQueryExtension L , N , N ) ) E (2); v=glXChooseVisual L ,
DefaultScreen (y ) , b ) ; s.colormap = XCreateColormap L ,
RootWindow (y,v -> screen), v -> visual, AllocNone ); if (!(
r= glXCreateContext L, v, N, 1) ) ) E (3) ; strcpy(f, *A ) ;
s.event_mask=KeyPressMask; strcat(f,".c"); F=fopen(f,"r" ) ;
w= XCreateWindow L, RootWindow( y, v -> screen ), M , M, 0,v
->depth,InputOutput, v->visual , CWColormap|CWEventMask, &s)
;glXMakeCurrent L , w , r ); H GL_DEPTH_TEST ); if ( ! F )E(
4 ) ; glShadeModel ( GL_SMOOTH ) ; while ( a != 89 ) a = G ;
G; G ; glGenTextures( 1, & t ); while ( x< 1024 ) { G; a =G;
j[ x++ ] = 128; j[ x++ ] = 128 & - ( a<33 ); j [ x ]= j[ x-1
]; x++; j[x++] =-1;} glBindTexture(X,t); glTexParameteri (X,
GL_TEXTURE_MIN_FILTER , GL_NEAREST ) ; glTexImage2D( X ,0,
GL_RGBA, 16 , 16 , 0 , GL_RGBA, GL_UNSIGNED_BYTE , j ) ; J
GL_PROJECTION ) ; gluPerspective( 60 , 1.333 , 1 , 100) ; J
GL_MODELVIEW); u=glGenLists(1); glNewList(u,GL_COMPILE); H X
) ; while ( a != 81 ) a = G ; G ; G ; for (x=0; x<6; x++ ) {
glBegin(GL_QUADS); R(); glNormal3f( c, m,n); T(1,1); V T (1,
0 ) ; V T ( 0 , 0 ) ; V T( 0 , 1 ) ; V glEnd ( ) ; }
glEndList( ) ; XMapWindow L , w ) ; c = 0; for ( ; ; ) { if(
XPending L ) ) { XNextEvent L , &e ) ; if((XLookupKeysym ( (
XKeyEvent *)&e,0))&1<<5){ h=10; i[c]=!i[c]; c++; c&=3; } else
E(0)} glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) ;
glLoadIdentity(); gluLookAt ( -2 ,0 ,5 ,0,0 ,0,0 ,0 ,1 ) ; H
GL_LIGHTING); H GL_LIGHT0 ); U GL_POSITION, i + 4); U O) ; U
GL_SPECULAR,i); glLightModelfv( GL_LIGHT_MODEL_AMBIENT,i +8)
; I GL_AMBIENT, i+8); I O + 8 ) ; glRotatef( g, 1, 1, 1) ; P
glTranslatef(-h,0,0); P usleep (4000); g+=.07*x; if (g>360)
g-=360.0; h-=x /100.0; glFlush(); glXSwapBuffers L ,w);}
l:
return 0;
}
+88
View File
@@ -0,0 +1,88 @@
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <GL/glx.h>
#include <GL/glu.h>
#define E(x) { printf("%i\n",x); goto l; }
#define G fgetc(F)
#define H glEnable(
#define I glMaterialfv(GL_FRONT,
#define J glMatrixMode(
#define L (y
#define N NULL
#define O GL_DIFFUSE , i
#define P glCallList(u);
#define T glTexCoord2i
#define U glLightfv(GL_LIGHT0,
#define V R(); glVertex3i(c,m,n);
#define X GL_TEXTURE_2D
void Y()
{ { { { { { { { { { { { { { { {
{ { { { { { { { { { {
{ { { { { {
{ { { { { { { {
{ { { { { {
{ { { { { ; { } } } } }
} } } } } } }
} } } } } }
} } } } } }
} } } } } }
} } } } } } }
} } } } } } } } } } } } } } } }
void Q()
{ { ; { { { { { { { {
{ { { { { {
{ { { { { {
; { { } } } } } } } }
} ; } } } } } } } } }
} } } } } }
FILE* F; void Z (int* x) { G; *x=G; *x=*x<50- (*x==59); }
int u,t,l,m,n,x=0, a=0,b[]={ GLX_DOUBLEBUFFER, GLX_RGBA ,
GLX_DEPTH_SIZE,16, None},o,n,c; void R() { Z(&c); Z(&m );
Z(&n ) ; } int main( int _, char **A) { char f [BUFSIZ ] ;
GLXContext r; XVisualInfo* v ; Display *y; GLfloat g=0 ,h=
10, i[]= { 1,1, 1,1, 5,5, 100, 0, .6,.6,.6,1 } ; XEvent e ;
XSetWindowAttributes s; GLubyte j[ 1<<10] ; Window w,u; if(
! L
=XOpenDisplay ( N ) ) ) E( 1 ) ; if ( ! glXQueryExtension L,N
,N ) ) E( 2 ) ; v = glXChooseVisual L , DefaultScreen (y ),b
); s. colormap = XCreateColormap L , u = RootWindow ( y , v->
screen),v->visual, AllocNone ); if ( !(r=glXCreateContext L,v
,N , 1 ) ) ) E ( 3 ) ; strcpy (f , * A) ; strcat (f, ".c" ) ;
F = fopen ( f , "r" ) ; s . event_mask = KeyPressMask ; w =
XCreateWindow L,u, 0,0,640, 480,0,v -> depth, InputOutput , v
-> visual , CWBorderPixel | CWColormap | CWEventMask ,& s);
glXMakeCurrent L , w , r ) ; H GL_DEPTH_TEST ) ; if ( ! F )E(
4 ) ; glShadeModel ( GL_SMOOTH ) ; while ( a != 89 ) a = G ;
G; G ; glGenTextures( 1, & t ) ; while ( x< 1024 ) { G; a =G;
j[ x++ ] = 128; j[ x++ ] = 128 & - ( a<33 ); j [ x ]= j [ x-1
]; x++; j[x++] = -1;} glBindTexture(X,t); glTexParameteri (X,
GL_TEXTURE_MIN_FILTER , GL_NEAREST ) ; glTexImage2D ( X ,0,
GL_RGBA, 16 , 16 , 0 , GL_RGBA, GL_UNSIGNED_BYTE , j ) ; J
GL_PROJECTION ) ; gluPerspective ( 60 , 1.333 , 1 , 100) ; J
GL_MODELVIEW); u=glGenLists(1); glNewList (u,GL_COMPILE); H X
); while(a!=81)a=G; G;G;for(x=0;x<6;x++){glBegin(GL_QUADS ) ;
R(); glNormal3f(c,m,n); T(1,1); V T(1,0); V T(0,0); V T(0 ,1)
; V glEnd(); } glEndList(); XMapWindow L, w) ; c=0; for(; ; )
{ if (XPending L)){ XNextEvent L, &e); if ((XLookupKeysym ( (
XKeyEvent *)&e,0))&1<<5){ h=10; i[c] =!i[c]; c++; c&=3; } else
E(0) } glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) ;
glLoadIdentity (); gluLookAt ( -2 ,0 ,5 ,0,0 ,0,0 ,0 ,1 ) ; H
GL_LIGHTING); H GL_LIGHT0 ); U GL_POSITION, i + 4 ); U O) ; U
GL_SPECULAR, i); glLightModelfv( GL_LIGHT_MODEL_AMBIENT,i +8)
; I GL_AMBIENT, i+8 ); I O + 8 ) ; glRotatef( g, 1, 1, 1) ; P
glTranslatef (-h,0,0); P usleep (4000); g+=.07*x; if (g > 360)
g-=360.0; h-=x / 100.0; glFlush () ; glXSwapBuffers L, w); }
l:
return 0;
}