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:
1 parent
28efc67f5d
commit
c0663537cb
1683 files changed
+220064
No files matched your search
Binary file not shown.
+124
@@ -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}
|
||||
|
||||
@@ -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/>
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
|
||||
build: aidan
|
||||
|
||||
clean:
|
||||
|
||||
clobber:
|
||||
-rm aidan
|
||||
|
||||
aidan: aidan.c
|
||||
${CC} ${CFLAGS} ${LDFLAGS} $< -o $@
|
||||
|
||||
alt:
|
||||
|
||||
data:
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
. . . | . . . | . . .
|
||||
. . . | . . . | . . .
|
||||
. . . | . . . | . . .
|
||||
------+-------+------
|
||||
. . . | . . . | . . .
|
||||
. . . | . . . | . . .
|
||||
. . . | . . . | . . .
|
||||
------+-------+------
|
||||
. . . | . . . | . . .
|
||||
. . . | . . . | . . .
|
||||
. . . | . . . | . . .
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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";
|
||||
@@ -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 . .
|
||||
@@ -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
|
||||
@@ -0,0 +1,15 @@
|
||||
|
||||
build: anon
|
||||
|
||||
clean:
|
||||
|
||||
clobber:
|
||||
-rm anon
|
||||
|
||||
anon: anon.c
|
||||
${CC} ${CFLAGS} ${LDFLAGS} $< -o $@
|
||||
|
||||
alt:
|
||||
|
||||
data:
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
@@ -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<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. :-)
|
||||
|
||||
|
||||
@@ -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 |
@@ -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;
|
||||
}
|
||||
@@ -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 |
@@ -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
|
||||
|
||||
> 
|
||||
|
||||
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
|
||||
|
||||
> 
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
|
||||
build: chia
|
||||
|
||||
clean:
|
||||
|
||||
clobber:
|
||||
-rm chia
|
||||
|
||||
chia: chia.c
|
||||
${CC} ${CFLAGS} ${LDFLAGS} $< -o $@
|
||||
|
||||
alt:
|
||||
|
||||
data:
|
||||
|
||||
@@ -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]);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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.
|
||||
@@ -0,0 +1,15 @@
|
||||
|
||||
build: giljade
|
||||
|
||||
clean:
|
||||
|
||||
clobber:
|
||||
-rm giljade
|
||||
|
||||
giljade: giljade.c
|
||||
${CC} ${CFLAGS} ${LDFLAGS} $< -o $@
|
||||
|
||||
alt:
|
||||
|
||||
data:
|
||||
|
||||
@@ -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;}
|
||||
@@ -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 ...
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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.
|
||||
@@ -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;}
|
||||
@@ -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
|
||||
|
||||
@@ -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!
|
||||
@@ -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;}
|
||||
@@ -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;}
|
||||
@@ -0,0 +1,16 @@
|
||||
C99=--std=c99
|
||||
|
||||
build: mikeash
|
||||
|
||||
clean:
|
||||
|
||||
clobber:
|
||||
-rm mikeash
|
||||
|
||||
mikeash: mikeash.c
|
||||
${CC} ${CFLAGS} ${C99} ${LDFLAGS} $< -o $@
|
||||
|
||||
alt:
|
||||
|
||||
data:
|
||||
|
||||
@@ -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.
|
||||
@@ -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;}
|
||||
@@ -0,0 +1,15 @@
|
||||
|
||||
build: mynx
|
||||
|
||||
clean:
|
||||
|
||||
clobber:
|
||||
-rm mynx
|
||||
|
||||
mynx: mynx.c
|
||||
${CC} ${CFLAGS} ${LDFLAGS} $< -o $@
|
||||
|
||||
alt:
|
||||
|
||||
data:
|
||||
|
||||
Vendored
+4192
File diff suppressed because it is too large.
Load diff
@@ -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
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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}
|
||||
@@ -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: </p>, </li>
|
||||
</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>
|
||||
@@ -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;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
LDFLAGS+=-lm
|
||||
build: persano
|
||||
|
||||
clean:
|
||||
|
||||
clobber:
|
||||
-rm persano
|
||||
|
||||
persano: persano.c
|
||||
${CC} ${CFLAGS} ${LDFLAGS} $< -o $@
|
||||
|
||||
alt:
|
||||
|
||||
data:
|
||||
|
||||
@@ -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] ;)
|
||||
@@ -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
@@ -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.
Binary file not shown.
@@ -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
|
||||
|
||||
Binary file not shown.
@@ -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!
|
||||
@@ -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.
@@ -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); }
|
||||
@@ -0,0 +1,15 @@
|
||||
|
||||
build: timwi
|
||||
|
||||
clean:
|
||||
|
||||
clobber:
|
||||
-rm timwi
|
||||
|
||||
timwi: timwi.c
|
||||
${CC} ${CFLAGS} ${LDFLAGS} $< -o $@
|
||||
|
||||
alt:
|
||||
|
||||
data:
|
||||
|
||||
@@ -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.
|
||||
@@ -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_):__;}
|
||||
@@ -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:
|
||||
|
||||
@@ -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 ;)
|
||||
@@ -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; }
|
||||
@@ -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; }
|
||||
@@ -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; }
|
||||
@@ -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:
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 60 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
@@ -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.
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
Reference in new issue
Block a user