Add preview of 1984-2019

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

One will find HTML commented out with:

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

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

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

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

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

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

No files matched your search

BIN
View File
Binary file not shown.
+147
View File
@@ -0,0 +1,147 @@
# %W% %G% %U%
#
# 1993 makefile
#
# Copyright (c) 1993, Landon Curt Noll & Larry Bassel.
# All Rights Reserved. Permission for personal, educational or non-profit
# use is granted provided this this copyright and notice are included in its
# entirety and remains unaltered. All other uses must receive prior permission
# from Landon Curt Noll and Larry Bassel.
SHELL=/bin/sh
CHMOD=chmod
CP=cp
RM=rm
SED=sed
LN=ln
# 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 may want nothing
# at all. Adjust the CFLAGS line as needed.
#
# NOTE: Some compilers cannot optimize, or optimize some entries
# entries incorrectly. You might want need to turn on -O
# to see if your compiler can handle them.
#
#CFLAGS=-O -Xa
#CFLAGS=-Xa
CFLAGS= -ansi
#CFLAGS=
# ANSI compiler
#
# Set CC to the name of your ANSI compiler.
#CC=cc
CC=gcc
# misc shell babble
#
NOINCLUDE=$(SED) -e 's/^.\([ ]*\)include/%include/'
SPACECLEAN=$(SED) -e 's/\([^ ]\)\([ ]\)[ ][ ]*/\1\2/g'
CPPCLEAN=$(GREP) -v '^. [0-9][0-9]*'
# winners that compile under ANSI C
#
WINNERS= ant cmills dgibson ejb jonth leo lmfjyh plummer rince schnitzi vanb
ALT_NAMES= ag ag.txt chris mind jkb
all: $(WINNERS) $(ALT_NAMES)
ant: ant.c
${CC} ${CFLAGS} ant.c -o ant
cmills: cmills.c
${CC} ${CFLAGS} cmills.c -o cmills -lX11
dgibson: dgibson.c dgibson.sh dgibson.data1
-@if [ ! -f life.d ] ; then \
echo "cp dgibson.data1 life.d"; \
cp dgibson.data1 life.d; \
echo "rm -f data.name"; \
rm -f data.name; \
echo "echo dgibson.data1 > data.name"; \
echo dgibson.data1 > data.name; \
fi
${CC} ${CFLAGS} dgibson.c -o dgibson
-${CHMOD} +x dgibson.sh
ejb: ejb.c
${CC} ${CFLAGS} ejb.c -o ejb
jonth: jonth.c
${RM} -f jonth.tmp.c
${SED} -e s/\^\ /#define/ -e 's/@/Window(D,/g' jonth.c > jonth.tmp.c
${CC} ${CFLAGS} \
-DXX1='H 19;}M(J,4)}N H 20;}M(T,4)}q(m,w,' \
-DXX='XKeycodeToKeysym(D,o[13],0);K 12:Y();}R;}d XX1' \
jonth.tmp.c -o jonth -lX11
leo: leo.c
${CC} ${CFLAGS} leo.c -o leo
lmfjyh: lmfjyh.c
${RM} -f \"\;main\(\)\{puts\(\"Hello\ World!\"\)\;\}char\*C=\".c
${CP} lmfjyh.c \"\;main\(\)\{puts\(\"Hello\ World!\"\)\;\}char\*C=\".c
${CC} ${CFLAGS} \
\"\;main\(\)\{puts\(\"Hello\ World!\"\)\;\}char\*C=\".c \
-o lmfjyh
plummer: plummer.c
${CC} ${CFLAGS} plummer.c -o plummer
rince: rince.c
${CC} ${CFLAGS} rince.c -lcurses -ltermcap -o rince
# NOTE: this is the original source that won
#
rince.orig: rince.orig.c
$(CC) $(CFLAGS) rince.orig.c -lcurses -ltermcap -o rince.orig
schnitzi: schnitzi.c
${CC} ${CFLAGS} schnitzi.c -o schnitzi
vanb: vanb.c
${CC} ${CFLAGS} -DO5=main vanb.c -o vanb
# alternate names for selected entries
#
ag: ant
$(RM) -f ag
$(LN) ant ag
ag.txt: ant.txt
$(RM) -f ag.txt
$(LN) ant.txt ag.txt
chris: cmills
$(RM) -f chris
$(LN) cmills chris
mind: leo
$(RM) -f mind
$(LN) leo mind
jkb: rince
$(RM) -f jkb
$(LN) rince jkb
tidy:
${RM} -f \"\;main\(\)\{puts\(\"Hello\ World!\"\)\;\}char\*C=\".c
clean:
$(RM) -f *.o a.out core
clobber: clean tidy
$(RM) -f $(WINNERS)
$(RM) -f $(ALT_NAMES)
${RM} -f jonth.tmp.c life.d rince.orig data.name data.name2
nuke: clobber
@true
install: all
cat $(WINNERS) > /dev/null
+59
View File
@@ -0,0 +1,59 @@
1993 marked the "The Tenth International Obfuscated C Code Contest"
Copyright (c) 1993, Landon Curt Noll & Larry Bassel.
All Rights Reserved. Permission for personal, educational or non-profit use is
granted provided this this copyright and notice are included in its entirety
and remains unaltered. All other uses must receive prior permission in writing
from both Landon Curt Noll and Larry Bassel.
Use make to compile entries. It is possible that on BSD or non-unix
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).
Name and address information are separated from the actual program
prior to judging. This eliminates any chance that we would bias our
judging for/against any person or group.
This year was the first year that ANSI C was the default. Use of
classic K&R C was allowed so long as ANSI C compilers could still
compile the entry. If you do not have an ANSI C compiler, you may
not be able to compile the winners, sorry!
A few notes regarding future contests:
Be sure to wait until the 1994 rules are posted before submitting entries.
Rules differ from year to year, sometimes in significant ways.
In 1994, we will retract the guideline that discouraged the use of C
constructs such as 3["curds"]. At one time, certain ANSI compilers did
not consider such expressions to be valid ANSI C. Alert readers noted
that the current ANSI standard considered them to be valid. We were
unable to find an ANSI C compiler that flagged such expressions as
errors.
Please send us comments and suggestions what we have expressed above.
Also include anything else that you would like to see in future contests.
Send such email to:
...!{sun,pacbell,uunet,pyramid}!hoptoad!judges
judges@toad.com
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
Email the fix (patch file or the entire changed file) to the above address.
Credits:
We would like to thank Barbara Frezza for her role as official chef
of the contest. Landon Noll and Larry Bassel appreciated the opportunity
to serve as official taste testers. And as usual, the food was excellent.
+307
View File
@@ -0,0 +1,307 @@
#define D ++*p
#define B **p
#define W while
#define R return
#define E else
#define Q if
#define G fprintf(stderr,
#include <stdio.h>
#ifndef A
#define A 512
#endif
typedef int I;
typedef char C;
typedef void V;
I z;
I f;
I x;
I a[A], b;
I d[A][A];
I m[A], n, o;
I N();
I M();
I P();
I U();
V X();
V T();
V F();
V L();
V O();
I
main(c, p)
I c;
C B;
{
I i;
FILE *j;
C *k, l[BUFSIZ+1];
Q (--c < 1) {
G "usage: ag <pattern> [js...]\n");
R 2;
}
N(-3);
N(-6-b);
N(0);
N(-3-b);
X(&(*++p));
*l = '\n';
o = 1;
i = 1;
do {
k = "-";
j = stdin;
Q (1 < c && **++p != '-') {
Q (!(j = fopen(k = *p, "r"))) {
G
"ag: Failed to open '%s'.\n", k);
i = 3;
continue;
}
}
W (fgets(l+1, BUFSIZ, j)) {
Q (M(l)) {
printf("%s:%s", k, l+1);
i = 0;
}
}
fclose(j);
} W (1 < --c);
R i;
}
V
X(p)
C B;
{
I i, j;
i = N(-3);
T(p);
W (B == '|') {
D;
j = N(-3);
N('\n');
a[i] = -4-b;
i = N(-3);
T(p);
a[j] = -4-b;
}
}
V
T(p)
C B;
{
W (B != '|' && (!x || B != ')') && B)
F(p);
}
V
F(p)
C B;
{
I i = N(-3);
Q (B == '^') {
D;
N('\n');
} E Q (B == '$') {
D;
N('\n');
} E Q (B == '(') {
D;
++x;
X(p);
Q (B != ')') {
G "ag: Missing ')'.\n");
exit(3);
}
--x;
D;
} E {
L(p);
}
Q (B == '*') {
D;
a[i] = -4-b;
N(-5-i);
} E Q (B == '?') {
D;
a[i] = -4-b;
}
}
V
L(p)
C B;
{
I i, j;
Q (B == '.') {
N(0);
} E Q (B == '[') {
D;
i = N(-2);
Q (B == '^') {
D;
a[i] = -1;
}
Q (B == ']') {
D;
N(']');
}
W ((i = B) != ']') {
Q ((*p)[1] == '-' && i < (j = (*p)[2])) {
W (i <= j)
N(i++);
*p += 3;
} E {
N(i);
D;
}
}
N('\n');
} E {
Q (B == '\\')
D;
N(B);
}
D;
}
I
N(c)
I c;
{
Q (A <= b) {
G "ag: Pattern too long.\n");
exit(3);
}
a[b] = c;
R b++;
}
V
O(p)
I p;
{
I i = n;
Q (b <= p)
R;
Q (a[p] < -2) {
Q (a[p] != -3)
O(-4-a[p]);
O(p+1);
} E Q (!a[p] || a[p] == z || P(&p)) {
W (i < o)
Q (m[i++] == p)
R;
f = U(p+1);
Q (A <= o) {
G "ag: Out of space.\n");
exit(3);
}
m[o++] = p;
}
}
I
P(p)
I *p;
{
I i = 0, j = 0;
Q (a[*p] == -2 || (j = a[*p] == -1)) {
W (a[D] != '\n')
Q (a[*p] == z)
i = 1;
}
R i ^ j;
}
I
U(p)
I p;
{
R (
f || p == b || (
a[p] < -2 && (
(a[p] != -3 && U(-4-a[p]))
|| U(p+1)
)
)
);
}
I
M(p)
C *p;
{
I c, i, j, k;
f = c = 0;
W (*p && 0 <= c) {
Q (0 < (i = d[c][*p])) {
c = i;
} E {
z = *p;
i = d[c][0];
j = n = o;
do
O(m[i++]+1);
W (m[i] != 2);
i = k = 0;
W (i < n) {
Q (m[i] == 2) {
j = n;
++k;
}
Q (m[i++] == m[j]) {
Q (o <= ++j) {
j = n;
Q (m[i] == 2) {
o = n;
break;
}
}
} E {
j = n;
}
}
Q (n < o)
d[++k][0] = n;
c = d[c][*p] = f ? -1 : k;
}
++p;
}
R c < 0;
}
+46
View File
@@ -0,0 +1,46 @@
Best Utility:
Anthony Howe
Mortice Kern Systems, Inc.
Unit 1, 14 Weber Street North,
Waterloo, Ontario, N2J 3G4
Canada
Judges' comments:
To use:
make ant
./ant 'ERE' [file ...]
where:
ERE is an extended regular expression
file a file to process (default is stdin)
You may also want to try the author's test suite:
make -f ant.test.mk
See the author's Posix P1003.2-like documentation file ant.txt
for more information.
This program demonstrates that Posix doesn't guarantee readability. :-)
Selected notes from the author:
Some of the features of my entry are:
o "Lengthy" POSIX.2 style specification and manual :) :)
o Useful subset of POSIX.2 Extended Regular Expressions.
o Recursive ERE parser/compiler that generates an NFA railroad.
o Lazy NFA to DFA evaluation to improve performance speed.
o Code tested on a variety of platforms.
o Make driven test script.
o Can be compiled with ANSI or K&R C.
o Not a toy, but actually useful and usable on systems that use DOS.
Copyright (c) 1993, Landon Curt Noll & Larry Bassel.
All Rights Reserved. Permission for personal, educational or non-profit use is
granted provided this this copyright and notice are included in its entirety
and remains unaltered. All other uses must receive prior permission in writing
from both Landon Curt Noll and Larry Bassel.
+240
View File
@@ -0,0 +1,240 @@
#
# Test Driver for Anthony's Grep
#
# Public Domain 1992, 1993 by Anthony Howe. No warranty.
#
SHELL=/bin/sh
PRG=./ant
all: ant char word anchor literal wild closure option branch sub class
#
# Built the entry
#
ant: Makefile
make -f Makefile ant
#
# Test simple text patterns without the use of meta characters.
#
empty:
$(PRG) '' ant.test.mk
char:
$(PRG) 'q' ant.test.mk
word:
$(PRG) 'simple' ant.test.mk
#
# Test meta characters.
#
anchor: anchor1 anchor2 anchor3 anchor4 anchor5
anchor1:
$(PRG) '^anchor1' ant.test.mk
anchor2:
$(PRG) 'Grep$$' ant.test.mk
#
# Find all empty lines.
#
anchor3:
$(PRG) '^$$' ant.test.mk
#
# This is valid but will never match.
#
anchor4:
-$(PRG) 'x^a' ant.test.mk
#
# This is valid but will never match.
#
anchor5:
-$(PRG) 'mk$$x' ant.test.mk
literal: literal1 literal2
#
# Every line with a dollar-sign.
#
literal1:
$(PRG) '\$$' ant.test.mk
#
# Every line with a backslash.
#
literal2:
$(PRG) '\\' ant.test.mk
#
# wild #1#
# wild #a#
# wild #%#
#
wild:
$(PRG) '#.#' ant.test.mk
#
# closure !!
# closure !x!
# closure !xxxxxx!
#
closure:
$(PRG) 'closure !x*!' ant.test.mk
#
# option ++
# option +a+
# option +b+
# option +c+
# option +abc+
#
option: option1 option2
option1:
$(PRG) '+b?+' ant.test.mk
option2:
$(PRG) '+.?+' ant.test.mk
branch: branch1 branch2 branch3 branch4 branch5 branch6
branch1:
$(PRG) 'q|simple' ant.test.mk
#
# This pattern should be the same as '(^all)|(Public)|(Grep$)'.
#
branch2:
$(PRG) '^all|Public|Grep$$' ant.test.mk
#
# This pattern should generate the same results as branch2.
#
branch3:
$(PRG) 'Grep$$|^all|Public' ant.test.mk
#
# Null expression between start of pattern and vertical-line.
#
branch4:
$(PRG) '|Grep' ant.test.mk
#
# Null expression between vertical-line and end of pattern.
#
branch5:
$(PRG) 'Grep|' ant.test.mk
#
# Null expression between vertical-line and vertical-line.
#
branch6:
$(PRG) 'all||Grep' ant.test.mk
#
# sub aabcbcbcxx
# sub aagxx
# sub aaggxx
# sub aadddxx
# sub aaxx
#
sub: sub0 sub1 sub2 sub3 sub4 sub5 lparen1 lparen2 rparen1 rparen2
#
# Null sub-expressions.
#
sub0:
$(PRG) 's()u()b()' ant.test.mk
sub1:
$(PRG) '#(1|%)#' ant.test.mk
sub2:
$(PRG) 'aa((bc)*|g)xx' ant.test.mk
#
# Null expression between the left-parenthesis and the vertical-line.
#
sub3:
$(PRG) '#(|1)#' ant.test.mk
#
# Null expression between the vertical-line and the right-parenthesis.
#
sub4:
$(PRG) '#(1|)#' ant.test.mk
#
# Null expression between the vertical-line and the right-parenthesis.
#
sub5:
$(PRG) '#(%||1)#' ant.test.mk
#
# Missing left-parenthesis generates an error.
#
lparen1:
-$(PRG) 'left ( only' ant.test.mk
lparen2:
$(PRG) 'left \( only' ant.test.mk
#
# Right-parenthesis without preceding left parenthesis should be a literal.
#
rparen1:
-$(PRG) 'right ) only' ant.test.mk
rparen2:
$(PRG) 'right \) only' ant.test.mk
#
# 12345678
# -----------------
# =0= 1 45
# =1= 2 45 78
# =2= 2 45
# =3= 2 45 78
# =4= 2 45
# =5= 2 45
# =6= 2 45
# =7= 2 45
# =8= 2 45
# =9= 1 45
# =]= 23 6
# =-= 2 4 678
# = = 2 4 6
#
class: class1 class2 class3 class4 class5 class6 class7 class8
class1:
$(PRG) '=[09]=' ant.test.mk
class2:
$(PRG) '=[^09]=' ant.test.mk
class3:
$(PRG) '=[]]=' ant.test.mk
class4:
$(PRG) '=[^]]=' ant.test.mk
class5:
$(PRG) '=[0-9]=' ant.test.mk
class6:
$(PRG) '=[^0-9]=' ant.test.mk
class7:
-$(PRG) '=[3-1]=' ant.test.mk
class8:
$(PRG) '=[-13]=' ant.test.mk
+376
View File
@@ -0,0 +1,376 @@
0. NAME
ag Anthony's Grep
1. SYNOPSIS
ag <pattern> [file...]
2. DESCRIPTION
The AG utility shall search input files, selecting lines matching a
pattern. An input line shall be selected if the pattern, treated as a
subset of Extended Regular Expressions as described by POSIX.2
Standard section 2.8.4, matches any part of the line; a null pattern
shall match every line. Each selected input line shall be written to
the standard output.
Regular expression matching shall be based on text lines, which are
separated by a <newline> character. A regular expression cannot
contain a <newline> and there is no way for a pattern to match a
<newline> found in the input.
3. OPTIONS
None.
4. OPERANDS
pattern Specify one pattern to be used during the search for
input. See Extended Regular Exprssions below on what
constitutes a valid pattern.
file A pathname of a file to be searched for the pattern.
If no file operands are specified or the file operand
is dash (-), the standard input shall be used.
5. EXTERNINAL INFLUENCES
5.1. STANDARD INPUT
The standard input shall be used only if no file operands are
specifed. See Input Files.
5.2. INPUT FILES
The input files shall be text files.
5.3. ENVIRONMENT VARIABLES
No environment variables are used.
5.4. ASYNCHRONOUS EVENTS
Default.
6. EXTERNAL EFFECTS
6.1. STANDARD OUTPUT
For each selected input line from a file, a single output line shall
be written:
"%s:%s\n", file, line
Standard input will have the filename dash (-).
6.2. STANDARD ERROR
Standard error is used for diagnostic messages only.
6.3. OUTPUT FILES
None.
7. EXTENDED DESCRIPTION
7.1. EXTENDED REGULAR EXPRESSIONS
7.1.1. MATCHING A SINGLE CHARACTER
An ERE ordinary character, a special character preceded by a
backslash, or a period shall match a single character. A bracket
expression shall match a single character. An ERE matching a single
character enclosed in parentheses shall match the same as the ERE
without parentheses would have matched.
7.1.1.1. ERE ORDINARY CHARACTERS
An oridinary character is an ERE that matches itself. An ordinary
character is any character in the supported character set, except for
the ERE special characters listed in 7.1.1.2. The interpretation of
an ordinary character preceded by a backslash (\) is the ordinary
character.
7.1.1.2. ERE SPECIAL CHARACTERS
An ERE special character has special properties in certain contexts.
Outside of those contexts, or when preceded by a backslash, such a
character shall be an ERE that matches the special character itself.
The extended regular expression special characters and the contexts in
which they have their special meaning are:
. [ \ ( The period, left-bracket, backslash, and left-
parenthesis are special except when used in a
bracket expression. Outside a bracket
expression, a left-parenthesis immediately
followed by a right-parenthesis will be
treated as a null expression.
) The right-parenthesis is special when matched
with a preceding left-parenthesis, both
outside of a bracket expression.
* ? The asterisk and question-mark are special
except when used in a bracket expression.
Results are undefined if this character
appears first in an ERE, or immediately
following a vertial-line, circumflex, or
left-parenthesis.
| The vertical-line is special except when used
in a bracket expression. A vertical-line
appearing first or last in an ERE or
immediately following a vertical-line or
left-parenthesis, or preceding a
right-parenthesis, produces a null expression.
^ The circumflex shall be special when used as
an anchor or, as the first character of a
bracket expression.
$ The dollar-sign shall be special when used as
an anchor.
7.1.1.3 PERIODS IN ERE
A period (.), when used outside of a bracket expression, is an ERE
that shall match any character in the supported character set except
NUL.
7.1.2. ERE BRACKET EXPRESSION
A bracket expression (an expression enclosed in square brackets, []),
is an ERE that matches a single character contained in the nonempty
set of characters represented by the bracket expression.
The following rules and definitions apply to bracket expressions:
1) A bracket expression is either a matching list expression
or a nonmatching list expression. It consists of one or more
characters and/or range expressions. The right-bracket (])
shall lose its special meaning and represent itself in a
bracket expression if it occurs first in the list [after an
initial circumflex (^), if any]. Otherwise, it shall
terminate the bracket expression. The special characters
period (.), asterisk (*), left-bracket ([), and backslash (\)
shall lose their special meaning within a bracket expression.
2) A matching list expression specifies a list that shall match
any one of the expressions represented in the list. The first
character of the list shall not be the circumflex. For
example, [abc] is an ERE that matches any of a, b, or c.
3) A nonmatching list expression begins with a circumflex (^),
and specifies a list that shall match any character except for
the expressions represented in the list after the leading
circumflex. For example, [^abc] is an ERE that matches any
character except a, b, or c. The circumflex shall have this
special meaning only when it occurs first in the list,
immediately following the left-bracket.
4) A range expression represents the set of characters that
fall between two elements in the current collation sequence,
inclusive. It shall be expressed as the starting point and
the ending point separated by a hyphen (-).
In the following, all examples assume the collation sequence
specified for the POSIX Locale (a.k.a ASCII Character Set),
unless another collation sequence is sepecifically defined
by the hardware.
The starting range point and the ending range point shall be a
collating element (character). The ending range point shall
collate higher than the starting range point; otherwise the
expression shall be treated as invalid.
The interpretation of a range expression where the ending
range point is the starting range point of a subsequent range
expression is undefined.
The hyphen character shall be treated as itself if it occurs
first (after an initial ^, if any) or last in the list, or as
an ending range point in a range expression. As examples, the
expressions [-ac] and [ac-] are equivalent and match any of
the characters a, c, or -; the expressions [^-ac] and [^ac-]
are equivalent and match ant character except a, c, -; the
expression [%--] matches any of the characters between % and
- inclusive; the expression [--@] matches any of the
characters between - and @ inclusive; and the expression
[a--@] is invalid, because the letter a follows the symbol -
in the POSIX Locale.
7.1.3. ERE MATCHING MULTIPLE CHARACTERS
The following rules shall be used to construct EREs matching multiple
characters from EREs matching a single character:
1) A concatenation of EREs shall match the concatenation of the
character sequences matched by each component of the ERE. A
concatenation of EREs enclosed in parentheses shall match
whatever the concatenation without parentheses matches. For
example, both the ERE cd and the ERE (cd) are matched by the
third and forth character of the string abcdefabcdef.
2) When an ERE matching a single character, or a concatention of
EREs enclosed in parentheses is followed by the special
character asterisk (*), together with that asterisk it shall
match what zero or more consecutive occurences of the ERE
would match. For example, the ERE b*c matches the first
character in the string cabbbcde, and the ERE b*cd matches the
third through seventh characters in the string
cabbbcdebbbbbbcdbc. And, [ab]* and [ab][ab] are equivalent
when matching the string ab.
3) When an ERE matching a single character or an ERE enclosed in
parentheses is followed by the special character question-mark
(?), together with that question mark it shall match what zero
or one consecutive occurences of the ERE would match. For
example, the ERE b?c matches the second character in the
string acabbbcde.
The behaviour of multiple adjacent duplication symbols (*, ?) produces
undefined results.
7.1.4. ERE ALTERATION
Two EREs separated by the special character vertical-line (|) shall
match a string that is matched by either. For example, the ERE
a((bc)|d) matches the string abc and the string ad. Single
characters, or expressions matching single characters, separated by
the vertical-line and enclosed in parentheses, shall be treated as an
ERE matching a single character.
7.1.5. ERE PRECEDENCE
The order of precedence shall be as shown in the table below, from
high to low:
escaped characters \<special character>
bracket expression [ ]
grouping ( )
single-character-ERE duplication * ?
concatenation
anchoring ^ $
alteration |
For example, the ERE abba|cde matches either the string abba or the
string cde (because concatenation has a higher order of precedence
than alteration).
7.1.6. ERE EXPRESSION ANCHORING
An ERE can be limited to matching strings that begin or end a line;
this is called anchoring. The circumflex and dollar-sign special
characters shall be considered ERE anchors in the following contexts:
1) A circumflex (^) outside a bracket expression shall anchor
the (sub)expression it begins to the beginning of a string;
such a (sub)expression can match only a sequence starting at
the first character of a string. For example, the EREs ^ab
and (^ab) match ab in the string abcdef, but fail to match in
the string cdefab, and the ERE a^b is valid, but can never
match because the character a prevents the expression ^b from
matching the first character of a string.
2) A dollar-sign ($) outside a bracket expression shall anchor
the (sub)expression it ends to the end of a string; such a
(sub)expression can match only a sequence ending at the last
character of a string. For example, the EREs ef$ and (ef$)
match ef in the string abcdef, but fail to match in the string
cdefab, and the ERE e$f is valid, but can never match because
the character f prevents the expression e$ from matching the
last character of a string.
8. EXIT STATUS
The following exit codes will be returned:
0 Successful match.
1 No match.
2 Usage error.
3 General error.
9. INSTALLATION
AG can be built on any system providing at least K&R C. It has been
tested on
o SunOS with GCC
o ATARI Mega ST with Sozobon C
o PC clone with Turbo C and WatCom C
o Interactive UNIX System V/386 release 3.2
For most machines, the compile command line should be
cc -O -o ag ag.c
PC class machines may require that medium or large memory model be used
and that ARRAY be set to 256. For Watcom C the command line would be
wcl -ml -DARRAY=256 ag.c
The value ARRAY represents the size of the compiled pattern array and
the size of the array used to record matched states. The default
value choosen should handle most patterns. ARRAY can be overridden on
the command line with -DARRAY=nn, where 255 < nn < INT_MAX.
10. REFERENCES
[Aho86] Aho, Sethi, and Ullman, "Compilers - Principles, Techniques,
and Tools", Addison-Wesley, 86, ISBN 0-201-10088-6, chapter 3
[K&P81] Kernighan and Plauger, "Software Tools in Pascal".
Addison-Wesley, 81, ISBN 0-201-10342-7, chapter 5
[Mil87] Webb Miller, "A Software Tools Sampler",
Prentice Hall, 87, ISBN 0-13-822305-X, chaper 4
[POSIX] POSIX.2 Standard, 2.8.4 Extended Regular Expressions, 4.28 Grep
11. FILES
ag.c Obfuscated source
ag.txt Manual for AG
agag.c Unobfuscated source
test.mk Makefile test driver for AG.
12. BUGS
The expression (a*)* compiles but loops forever.
There is no check for trailing backslash (\) in the pattern.
There is no check for unbalanced brackets. Omitting a closing bracket
will generate a "Patern too long" error, which is not the real error.
13. NOTICES
Public Domain 1992, 1993 by Anthony Howe. No warranty.
+54
View File
@@ -0,0 +1,54 @@
long
z[7992],W,H,*t=z,j,k,*T=z,n,b;
#include<X11/Xlib.h>
Window*E,D,s,w[999],*e=w;
Display*d;
Pixmap
p;
m(w,h,x,y,u,v){
#define C XCreateSimpleWindow(d,
XSetWindowBackgroundPixmap(d,s=C*e=C
#define l(n)t[n]=T[n]+
D,l(0)x,l(1)y,t[2]=w,t[3]=h,1,b,0),l(6)-x,l(7)-y,W,H,0,0,0),p);
l(4)u;
l(5)v;
#define M XMapRaised(d,
M
s);
M*e++);
t+=8;
}
main(c,g)char**g;
{
XSetWindowAttributes
a;
XGCValues
v;
n=DefaultScreen(d=XOpenDisplay(0));
p=XCreatePixmap(d,D=RootWindow(d,n),W=DisplayWidth(d,n),H=DisplayHeight(d,n),DefaultDepth(d,n));
v.subwindow_mode=IncludeInferiors;
XCopyArea(d,D,p,XCreateGC(d,D,GCSubwindowMode,&v),0,0,W,H,0,0);
a.override_redirect=True;
XChangeWindowAttributes(d,D=C
D,0,0,W,H,0,0,b=BlackPixel(d,n)),CWOverrideRedirect,&a);
M
D);
m(W,H,0,0,3,3);
for(c=c^1?atoi(g[1]):9;
;
)for(T=z,n=e-(E=w);
n--;
T+=8,++E){
XMoveWindow(d,*E,*T+=T[4]*c,T[1]+=T[5]*c);
j=0;
#define F(n,o,s)o+T[n-4]s-0&&++j&&T[n]s!1&&(T[n]=0-T[n])||
if((F(4,0,<)F(4,T[2]-W,>)F(5,0,<)F(5,T[3]-H,>)1)&&j&&(j=T[2]/2)&&(k=T[3]/2)&&e-w<997&&rand()%32768<=T[2]*T[3]*(T[4]*T[4]+T[5]*T[5])/999){
m(T[2]-j,T[3]-k,j,k,2,2);
m(j,T[3]-k,0,k,-2,-2);
m(T[2]-j,k,j,0,2,-2);
T[7]-=2;
XResizeWindow(d,*E,T[2]=j,T[3]=k);
T[6]-=2;
}
}
}
+72
View File
@@ -0,0 +1,72 @@
"Bill Gates" Award:
Chris Mills
Pagine Corporation
1961-A Concourse Drive
San Jose, CA 95131
USA
Judges' comments:
From the San Jose Mercury News (May 15, 1993 page 20A "West Hackers
trounce East in computer quiz game"):
"Since 1984, a contest has been held on Usenet for the most
unreadable, creative, bizarre but working C program", Gates
said. "What is the name of this contest?"
"Windows," shot back Gassee, naming Microsoft's premier product
- a product over which Apple sued Microsoft five years ago. Not
the right answer - it's "The Obfuscated C Contest [sic]" - but
it brought down the house of Apple partisans...
[The expression on Bill Gates' face was a sight to behold, as reported
to us by several who were there].
To use:
make cmills # requires the X11 library
DISPLAY="your_X_server_display"
export DISPLAY
./cmills [speed] # must be run on an X11 server
where:
speed update speed from 1 to 9 (default is 9)
Csh users should use:
make cmills # requires the X11 library
setenv DISPLAY "your_X_server_display"
./cmills [speed] # must be run on an X11 server
You must set $DISPLAY in your environment or the program will
dump core. This is not a bug as the author documented it as
a feature. :-)
The optional argument is integer which controls the speed of the
program. By default the speed is 9. You may want to try 1.
You will have to kill the program (i.e., ^C) to stop it.
WARNING: Slow servers or servers with long request queues will
continue to 'run' for a while after you have killed
the program.
This program makes your windows about as useful as their windows. :-)
Selected notes from the author:
The program uses a single backing pixmap (which is the size of the
screen) for all of its subwindows (with a little bit of trickery to
move the offset around). This is much better (and faster) than the
obvious implementation which would require a full-screen pixmap and
a separate backing pixmap for each subwindow.
The chance that a window breaks is based on it's kinetic energy,
which in turn is based on it's area and speed. How silly!
Copyright (c) 1993, Landon Curt Noll & Larry Bassel.
All Rights Reserved. Permission for personal, educational or non-profit use is
granted provided this this copyright and notice are included in its entirety
and remains unaltered. All other uses must receive prior permission in writing
from both Landon Curt Noll and Larry Bassel.
+41
View File
@@ -0,0 +1,41 @@
#include <stdio.h>
#define maxc (prs >> 16)
#define maxr (prs & 0xff00) >> 8
#define find (col > 1)
#define endb || (prs & 16) && X(0) || chpa || (eols, 0)
#define lnst doln ? 0 : (init, 0) || (prs & 128) && X(0)
#define L endb) || 0 || (find ? 0 : (rrr++, rrc = 0)) || (lnst
#define X(p) (dfc++ && ((prs & 48) != 32 || rrc < maxc) && ++ccl && \
(find ? (bat = bit, bit = but, but = p, ccl == col && \
(ret = bat + bit + but) + 1) : (las = las * 2 + \
(((main(ccl + 1, cro - 1) + main(ccl + 1, cro) + \
main(ccl + 1, cro + 1) - p) | p) == 3), occ |= las & 1, \
printf(" %c", "_O"[las & 1]), ccl == 2 && (sta |= (las & 3) << 6),\
0)))
#define _ || (find || rrc++, 0) || X(0)
#define O || (find || rrc++, 0) || X(1)
#define chpa (find && col > ccl && ((ret = bit + but) + 1))
#define eols (!find && (cro == 1 ? (sta |= occ << 3) : cro == 2 && \
(sta |= occ << 2), sta |= (las & 3) << 4))
#define init (find ? (ret = bit = but = 0) : (ocp = occ, las = occ = 0, \
printf("\nL")), dfc = (prs & 192) != 64, ccl = 0)
#define doln !(dfl++ && (((prs & 3) != 2) || rrr < maxr) && \
(++cro == row || !find))
#define recu (col =- col, (ccl = find ? rcf : rcl), cro = rro, 0 _ || \
(rrc >= maxc ? 0 : (find ? rcf = ccl : (rcl = ccl), \
main(-col, row))))
#define addl (lnst || (rro = cro, find ? rcf = ccl : (rrc = 0, rcl = ccl), \
0) || main(-col, row) || (ccl = rcl + 1, 0) endb)
#define outp (find || printf("\n\nGEN %d STAT %ld\nEND\n", ++gen, \
(long)ccl << 16 | cro << 8 | (sta | occ | ocp << 1) ^ 0x66))
#define GEN endb) || (prs & 1) && addl || (outp, 0)), ret)); } int gen =
#define STAT ;long prs =
#define END ;
#define LIFE int bat, bit, but, las, gen, ret, rcl, rcf, rro, rrc, rrr, \
occ, ocp, sta, dfc; long prs; main(int col, int row) { \
int dfl = ((prs & 12) != 4), ccl = 0, cro = 0; return \
col == 1 && printf("LIFE\n"), (col < 0 ? recu : \
(((ret = 0) || (prs & 8) && addl || 0 && (0
#include "life.d"
+10
View File
@@ -0,0 +1,10 @@
LIFE
L _ _ _ _ _
L _ _ _ O _
L _ O _ O _
L _ _ O O _
L _ _ _ _ _
GEN 0
END
+9
View File
@@ -0,0 +1,9 @@
LIFE
L _ _ _ _ _
L _ O O O _
L _ _ O _ _
L _ _ _ _ _
GEN 0
END
+10
View File
@@ -0,0 +1,10 @@
LIFE
L _ _ _ _ _
L _ _ O O _
L _ O O _ _
L _ _ O _ _
L _ _ _ _ _
GEN 0
END
+15
View File
@@ -0,0 +1,15 @@
/* 0064 Can you build a puffer train? */
LIFE
L _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
L _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
L _ _ O _ _ _ _ _ _ _ _ O _ _ _ _ O _ _ _
L _ O _ _ _ _ _ O _ _ O _ _ _ _ O _ _ _ _
L _ O _ _ _ _ _ _ O O O _ _ _ _ O _ _ _ _
L _ O _ _ O _ _ _ _ _ _ _ _ _ _ O _ _ O _
L _ O O O _ _ _ _ _ _ _ _ _ _ _ O O O _ _
L _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
GEN 0
END
+43
View File
@@ -0,0 +1,43 @@
/* Howdy, Landon: */
/* Here is one of the best Life patterns found in many years. It is called */
/* a "spacefiller", for reasons which will become obvious when you run it. */
/* This was found by Hartmut Holzwart a couple of weeks ago. Enjoy! */
/* BCNU, -dbell- */
LIFE
L _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
L _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ O _ O _ _ _ _ _ _ _ _ _ _
L _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ O _ _ O _ _ _ _ _ _ _ _ _
L _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ O O _ _ _ _ _ _ _ _
L _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ O _ _ _ _ O _ _ _ _ _ _ _
L _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ O O O _ _ _ O O O _ _ _ _ O _ O O O O O _ _ _ _ _ _
L _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ O _ _ O _ O _ _ O _ _ _ _ _ _ _ _ _ _ _ _ O O _ _ _
L _ _ _ _ _ _ _ _ _ _ O O _ _ _ _ _ _ _ O _ _ _ _ _ _ _ O _ _ _ _ _ _ _ _ O O O _ _ _ O _ _
L _ _ _ _ _ _ _ _ _ O _ _ _ _ _ _ _ _ _ O _ _ _ _ _ _ _ O _ _ _ _ _ _ _ _ _ _ _ O _ _ _ O _
L _ _ _ _ _ _ _ _ O O _ _ O _ _ _ _ _ _ _ O _ O _ O _ O _ _ _ _ _ _ _ _ _ _ O _ _ _ _ _ O _
L _ _ _ _ _ _ _ O _ _ _ _ O _ _ _ _ _ _ _ O _ O _ O _ O _ _ _ _ _ _ _ _ _ _ O _ _ O _ _ O _
L _ _ _ _ _ _ O O O O O _ _ _ _ _ _ _ _ _ _ O _ _ _ O _ _ _ _ _ _ _ _ O _ O O _ _ O _ O _ _
L _ _ _ O O _ _ _ _ _ O O _ _ _ _ O _ _ _ O O O _ O O O _ _ _ _ _ _ _ O _ _ _ _ _ _ _ _ _ _
L _ _ O _ _ _ O O O _ _ O _ _ O O O _ _ _ _ _ _ O _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ O O O _
L _ O _ _ _ O _ _ _ _ _ O O _ O O _ _ _ O O O O O O O O O _ _ _ _ _ _ _ _ _ _ _ _ _ _ O O _
L _ O _ _ _ _ _ O _ _ _ O _ _ _ O _ _ O _ _ _ _ _ _ _ _ _ O _ _ _ _ _ _ _ _ _ _ _ _ O O O _
L _ O _ _ O _ _ O _ _ _ _ _ O O O _ O O O O O O O O O O O O _ _ _ _ _ O _ _ _ _ _ _ _ _ _ _
L _ _ O _ O _ _ O O _ O _ _ O O _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ O O _ _ O _ O O _ _ O _ O _ _
L _ _ _ _ _ _ _ _ _ _ O _ _ _ _ _ O O O O O O O O O O O O _ O O O _ _ _ _ _ O _ _ O _ _ O _
L _ O O O _ _ _ _ _ _ _ _ _ _ _ _ O _ _ _ _ _ _ _ _ _ O _ _ O _ _ _ O _ _ _ O _ _ _ _ _ O _
L _ O O _ _ _ _ _ _ _ _ _ _ _ _ _ _ O O O O O O O O O _ _ _ O O _ O O _ _ _ _ _ O _ _ _ O _
L _ O O O _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ O _ _ _ _ _ _ O O O _ _ O _ _ O O O _ _ _ O _ _
L _ _ _ _ _ _ _ _ _ _ O _ _ _ _ _ _ _ O O O _ O O O _ _ _ O _ _ _ _ O O _ _ _ _ _ O O _ _ _
L _ _ O _ O _ _ O O _ O _ _ _ _ _ _ _ _ O _ _ _ O _ _ _ _ _ _ _ _ _ _ O O O O O _ _ _ _ _ _
L _ O _ _ O _ _ O _ _ _ _ _ _ _ _ _ _ O _ O _ O _ O _ _ _ _ _ _ _ O _ _ _ _ O _ _ _ _ _ _ _
L _ O _ _ _ _ _ O _ _ _ _ _ _ _ _ _ _ O _ O _ O _ O _ _ _ _ _ _ _ O _ _ O O _ _ _ _ _ _ _ _
L _ O _ _ _ O _ _ _ _ _ _ _ _ _ _ _ O _ _ _ _ _ _ _ O _ _ _ _ _ _ _ _ _ O _ _ _ _ _ _ _ _ _
L _ _ O _ _ _ O O O _ _ _ _ _ _ _ _ O _ _ _ _ _ _ _ O _ _ _ _ _ _ _ O O _ _ _ _ _ _ _ _ _ _
L _ _ _ O O _ _ _ _ _ _ _ _ _ _ _ _ O _ _ O _ O _ _ O _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
L _ _ _ _ _ _ O O O O O _ O _ _ _ _ O O O _ _ _ O O O _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
L _ _ _ _ _ _ _ O _ _ _ _ O _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
L _ _ _ _ _ _ _ _ O O _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
L _ _ _ _ _ _ _ _ _ O _ _ O _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
L _ _ _ _ _ _ _ _ _ _ O _ O _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
L _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
GEN 0
END
+66
View File
@@ -0,0 +1,66 @@
Best Abuse of the C Preprocessor:
David Gibson
University of Cape Town
1 Sweet Valley Road
Bergvliet
7945
South Africa
Judges' comments:
To use:
sh ./dgibson.sh [datafile]
where:
datafile initial pattern (default: dgibson.data1)
We have provided the shell script 'dgibson.sh' to make it easier
to run this entry. Run this shell script several times to
see what happens.
There are a number of data files available:
dgibson.data1
dgibson.data2
dgibson.data3
dgibson.data4
dgibson.data5
For dgibson.data5 you will need a large screen, lots of virtual
memory and lots of time!
Good luck trying to use a debugger on this entry! Life is not
always pretty.
Selected notes from the author:
This program plays the Game of Life.
Life is a cellular automaton invented by J. H. Conway, in which each of
a rectangular grid of cells can be alive or dead, and cells with more
than 3 or less than 2 (out of 8) live neighbours die, and empty cells
with exactly 3 neighbours give birth.
Some notes: the "STAT n" information does not have to be present in the
initial configuration; the initial configuration should not have live
cells around the edges; the grid should be a perfect rectangle.
Further features: the current generation number is preserved, and the
grid automatically resizes itself as the object gets too big or too
small.
When writing this program, my goal was to make each cell in the life
grid expand to the code which calculates the fate of that cell. In
addition, the resulting program is a single expression, which makes it
necessary to recurse on main in two "directions" simultaneously.
Copyright (c) 1993, Landon Curt Noll & Larry Bassel.
All Rights Reserved. Permission for personal, educational or non-profit use is
granted provided this this copyright and notice are included in its entirety
and remains unaltered. All other uses must receive prior permission in writing
from both Landon Curt Noll and Larry Bassel.
+53
View File
@@ -0,0 +1,53 @@
#!/bin/sh
#
# dgibson.sh - run the dgibson entry
#
# usage:
# dgibson.sh [data_file]
# parse args
#
if [ $# -eq 0 ]; then
DATA="./dgibson.data1"
else
DATA="$1"
fi
if [ ! -f "$DATA" ]; then
echo "$0: no data found in $DATA" 1>&2
exit 1
fi
# for the initial data.name if needed
#
if [ ! -f "data.name" ]; then
rm -f data.name
echo "$DATA" > data.name
fi
if [ ! -f life.d ]; then
# force a new life setup
echo "/" > data.name
fi
rm -f data.name2
echo "$DATA" > data.name2
# note if we are running a new form
#
if cmp -s data.name data.name2; then
:
else
rm -f life.d
cp "$DATA" life.d
rm -f data.name
echo "$DATA" > data.name
cat life.d
fi
# build a new copy of the program
#
rm -f dgibson
make dgibson
# form the next generation
#
chmod +w life.d
dgibson | tee life.d
+53
View File
@@ -0,0 +1,53 @@
static signed char a[] = {0x69,
110, 118, 97, 108, 105, 0x64, 1-1,
0x6d, 111, 118, 101, 1<<1<<1<<1<<1<<1,
114, 105, 0x6e, 103, 32, 'o'/3, 100,
32, 102, 114, 111, 0x6d, 32, 115, 116,
97, 100-001, 107, 32,37, 2*'2', '@'>>1,
116, '%' + '%' + '%','w'-'W',115, 0x74,
97, 3*'!', 107, 'q' - 'Q', 37, 10*'\n',
10, 0}, * b = a + (1<<1<<1<<1), * w, x,
*q, c, r; int main(int d, char *e []) {
return q = (signed char *)(e+1+1), (r =
e[0] && e[1] ? 0 : 0 * puts (a) + 1) ||
(r = e[1<<1] && d != 1 <<1 && 0 * puts(
a) + 1) || e[1- -1] || (r = atoi(e[1])
< -0200 || atoi (e [1]) > 0x7f || ( x =
atoi( e[1] ) ) == 0 ? 0 * puts(a) + 1 :
0) || e [1- -1] || (x- -x > 1-1 ? (q[0]
= x, q[1] = q[3] = 1, q[2] = 2) : (
memset ( w = ( signed char * )
malloc(-x), '1', -x), puts (w),
q[0] = x, q[1] = '0', q[2] = q[3] =
0)), r || (q[3] ? (c = 6 - q[1] - q[2],
(q[0] != 1) ? q[0]-- , d = q[2], q[2] =
c, main(2, e), c = q[2], q[2] = d, q[0]
++ : 0, printf(b, q[0], q[1], q[2]), (q
[0] != 1) ? q[0]--, d = q[1],q[1] = c ,
main(2, e), c = q[1], q[1] = d, q[0] ++
: 0) : - 1 - q[0] - 1 == 0 ? (w[- x - 1
- (q[1] & 1 ^ 1)] = q[1], puts (w), w [
- x - 1 - (q[1] & 1)] = q[1], puts(w) )
: - 1 - q[0] == 0 ? (w[- x - 1] = q[ 1
], puts(w)) : (q[0] += 1 + ( q[1] & 1
^ 1), main(2, e), q[0] -= 1 + ( q
[1] & 1 ^ 1), q[1] & 1 ? (q
[0]+=1+1, q[1]^=1, main
(2, e), q[1]^=1, q[0]-=1
+1) : 0, w[q[0] - x] = q
[1], puts(w), q[1] & 1 ?
0 : (q[0]+=1+1, q[1]^=1,
main (2, e), q[1]^=1, q
[0]-=1+1), q[0] += 1 +
(q[1] & 1),main(2,e)
, q[0] -= 1 + (q[1]
& 1) ) ), r; }
+9
View File
@@ -0,0 +1,9 @@
The Towers of Hanoi is a puzzle consisting of three posts
and several rings of various sizes. The initial
configuration of the game is that all the rings are stacked
in decreasing order of size on one post. The object of the
game is to move all the rings from one post to another
subject to two rules: only one ring can be moved at a time,
and at no time can one ring be placed on top of a smaller
ring. The number of steps necessary to solve this puzzle is
exponential in the number rings.
+141
View File
@@ -0,0 +1,141 @@
The Patience puzzle, probably of Chinese origin, consists of
an iron U-shaped piece and several rings that link around
it. The physical shape of the puzzle is very difficult to
describe verbally, but here is an attempt.
This description of the puzzle is presented as a set of
instructions for constructing the puzzle. Start with a flat
piece of iron about 15 centimeters long by about two
centimeters wide. Drill six holes in the piece of iron.
Through each hole, place a rod. The rod should have a
diameter slightly less than that of the hole so that it can
move freely. One end of the rod is like the head of a nail
and is larger than the hole to prevent it from coming free.
The other end is looped around a metal ring with a diameter
of about five centimeters. This completely prevents the
iron rod from separating from the base. Each rod, in
addition to going through the iron base, goes through the
ring at the end of the rod to its right. The only rod free
of this restriction is the rightmost rod. What has been
described so far is one of the two components of the puzzle.
The other component is another iron rod shaped like a U.
the U is as long from the tips to the base as the original
piece of iron with the holes in it. The ends of the U are
looped around another ring of about five centimeters in
diameter. In the puzzle's initial configuration, the U is
placed through the rings so that it is held in place by the
iron rods. Imagine starting with the U piece before the
iron loop is placed at the end. Slide the legs of the U
through the loops so that the iron rods securing the loops
to the metal strip go up the center of the U. Placing the
final ring at the ends of the U prevents it from coming out.
The object of the puzzle is to free the U-shaped piece from
the other piece.
The following illustration (sideways) shows a three-ring
case of this puzzle. If you look carefully, you can see
that the first ring could be lifted over the edge of the U
and slid down through the center of the U, thereby freeing
the U from the first iron rod. The second ring can also be
freed in the initial configuration since it is already over
the rod for the first ring. The third ring cannot be moved,
however, since it is blocked by the iron rod two which the
first ring is attached. If the first first is removed, then
the third ring is no longer blocked by the first ring's iron
rod and can be removed freely. The second ring, however
cannot be moved if the first ring is gone because it will
then be blocked by the first ring in its new position
outside of the U.
Here is an illustration of the three-ring case. The bottom
of the puzzle is on the left-hand side of the page.
//==\\
|| ||
|| ||
*****||** ||
*** || ***||
** || *||
|\ ** || ||**
| \ *** || || ***
| \ *** | || ===
| \ *** || // * \\
| \ *** || || ** ||
| | | ********** ||
| | || || || ||
| | || || || ||
| | *****||** || \\ ||
| | |\ | *** || ***|| ||
|==| |=========-**-===-||-============//
|==| |=========-**-===-||-===========//
| | \| | *** || || ***
| | *** || || ===
| | ***| || // * \\
| | *** || || ** ||
| | ||********** ||
| | || || || ||
| | *****||** || \\ ||
| | |\ | *** || ***|| ||
|==| |=========-**-===-||-============//
|==| |=========-**-===-||-===========//
| | \| | *** || || ***
| | *** || || ===
| | ***| || // * \\
| | *** || || ** ||
| | ||********** ||
| | || || || ||
| | || || || ||
| | | || || \\ ||
| | |\ | || || ||
|==| |================-||-============//
|==| |================-||-===========//
| | \| | || ||
| | || ||
| | || ||
| | || ||
\ | || ||
\ | \\ ||
\ | \\ ||
\ | \\ ||
\ | \\||
\| \||
This puzzle takes other forms as well. One such puzzle is
called "Spin-Out". This puzzle consists of one plastic
piece that encases another piece that can slide in and out
of it. The movement of the smaller piece is restricted by
discs that, when turned to one angle, lock the smaller piece
inside the larger one and, when turned the other way, allow
it to move. This puzzle is as difficult to describe as the
first and, since I don't have one in front of me, I will not
attempt to describe it. The object of this puzzle is to
free the smaller piece from the larger one. The other
puzzle that is like this one consists of a cylinder with
rods protruding from the top. The rods can be slid from the
center to the edge of the cylinder constrained by a series
of discs in the center. The discs have cuts in them that
allow some rods to move and force others in one place based
on the relative rotations of the discs. The object here is
to move all the rods from the inside to the outside.
What makes these puzzles similar is that the physical shapes
of the puzzles put the same restrictions on the movement of
the pieces. Specifically, there is always one piece that is
free to move. The only other piece that is free to move is
the second one that is still attached to the base it is
trying to be freed from. In the case of the original
puzzle, consider the rings numbered from 1 to 6 with ring 1
being the one at the closed send of the U. Ring 1 can
always be removed from or added to the U. In the initial
state, when all rings are around the U, ring 2 is the other
one that can be moved because it is second. If ring 1 is
removed, then only two operations are possible: the
restoration of ring 1 and the removal of ring 3. This is
because ring 1 is always movable, and ring 3 is currently
the second ring still attached to the U. This constraint
leads to a recursive solution to the puzzle. Like the
Towers of Hanoi, the number of steps to solve this puzzle is
exponential in the number of rings.
+79
View File
@@ -0,0 +1,79 @@
Best Obfuscated Algorithm:
E. Jay Berkenbilt
Engineering Research Associates
1595 Springhill Road
Vienna, VA 22182-2235
USA
Judges' comments:
To run:
make ejb
./ejb level
where:
level a value from -128 to 127
A negative argument plays the patience puzzle. An argument
greater than 0 plays the Tower of Hanoi puzzle. In either case
the absolute value of the argument specifies the size of the
respective puzzle. Refer to the files ejb.explain1 and
ejb.explain2 for more information on these puzzles.
Of course, you need a different kind of "patience" if you give
the argument 127 to this program and want to see it finish!
Selected notes from the author:
WHAT THIS PROGRAM DOES
======================
./ejb 5 Output: solution to Towers of Hanoi for five rings
./ejb -6 Output: solution to the Patience puzzle for six rings
The format of the output for the Towers of Hanoi case is simply a
text description of how to solve the puzzle. For the patience
puzzle, the output is a sequence binary codes representing
successive states of the puzzle. The rightmost digit represents
the first ring. A "1" means the ring is on the U; a "0" means it
is off the U. The program prints the word "Invalid" in response to
illegal command line parameters.
MOTIVATION
==========
Most people who have written software for other people have been
asked to count lines of code. Naturally, this brings up the
controversial question of exactly what defines a line of code.
This program serves to show that counting semicolons will not
always provide a meaningful measure of code size. This is
especially true in this program where the number of semicolons
itself is ambiguous. Does it have two or three? In addition, the
only "C" keyword this program uses besides type names and
qualifiers is "return", and the only function defined in the code
is "main". The level of complexity of the program without multiple
semicolons, statements, and functions is achieved by abusing C
operators, especially the comma operator. Considerable use of ||,
&&, and ? : helps too. In addition, main is called recursively.
The null pointer that terminates argv is used to pass additional
information into main. Even though the algorithms used by this
code are simple, this program is still hard to follow even when
indented properly. (It is pretty hard to indent this code
reasonably, however.)
Although this program is has only been tested on UNIX systems but
will probably run on just about any machine with an ANSI C
compiler. It does not use the C preprocessor at all. The only
functions it uses are atoi, malloc, memset, printf, and puts. It
does, however, require that the architecture it runs on have bytes
that are at least eight bits long and pointers that are at least
four bytes long. In addition, it requires an ANSI compiler since
it uses "signed char" and ANSI-style function declarations.
Copyright (c) 1993, Landon Curt Noll & Larry Bassel.
All Rights Reserved. Permission for personal, educational or non-profit use is
granted provided this this copyright and notice are included in its entirety
and remains unaltered. All other uses must receive prior permission in writing
from both Landon Curt Noll and Larry Bassel.
+592
View File
@@ -0,0 +1,592 @@
10th International Obfuscated C Code Contest Guidelines, Hints and Comments
Copyright (c) Landon Curt Noll & Larry Bassel, 1993.
All Rights Reserved. Permission for personal, educational or non-profit use is
granted provided this this copyright and notice are included in its entirety
and remains unaltered. All other uses must receive prior permission in writing
from both Landon Curt Noll and Larry Bassel.
ABOUT THIS FILE:
This file is intended to help people who wish to submit entries to
the International Obfuscated C Code Contest (IOCCC for short).
This is not the IOCCC rules, though it does contain comments about
them. The guidelines should be viewed as hints and suggestions.
Entries that violate the guidelines but remain within the rules are
allowed. Even so, you are safer if you remain within the guidelines.
You should read the current IOCCC rules, prior to submitting entries.
The rules are typically sent out with these guidelines.
Changes from the 1993 draft are noted by change bars. ---> |
WHAT IS NEW IN 1993:
The entry format is better (for us anyway). The program mkentry.c
has been updated. See ENTRY FORMAT.
We will reject entries that cannot be compiled using an ANSI C
compiler. Certain old Obfuscation hacks that cause ANSI C compilers
fits are no longer permitted. Some of the new issues deal with
non-integral array types, variable number of arguments, C preprocessor
directives and the exit() function. See OUR LIKES AND DISLIKES.
HINTS AND SUGGESTIONS:
You are encouraged to examine the winners of previous contests. See
FOR MORE INFORMATION for details on how to get previous winners.
Keep in mind that rules change from year to year, so some winning entries
may not be valid entries this year. What was unique and novel one year
might be 'old' the next year.
An entry is usually examined in a number of ways. We typically apply
a number of tests to an entry:
* look at the original source
* convert ANSI tri-graphs to ASCII
* C pre-process the source ignoring '#include' lines
* C pre-process the source ignoring '#define' and '#include' lines
* run it through a C beautifier
* examine the algorithm
* lint it
* compile it
* execute it
You should consider how your entry looks in each of the above tests.
You should ask yourself if your entry remains obscure after it has been
'cleaned up' by the C pre-processor and a C beautifier.
Your entry need not do well under all, or in most 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.
If you do plan to abuse the rules, we suggest that you let us know
in the remarks section. Please note that an invitation to abuse
is not an invitation to break. We are strict when it comes to the
3217 byte size limit. Also, abusing the entry format tends to
annoy more than amuse.
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.
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
int i;
j; <-- don't use such implicit type declaration
int k;
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.
Unfortunately, some ANSI C compilers require array indexes to be of |
integral type. Thus, the following classical obfuscation hacks should |
not be used in 1993. This rule may be relaxed in future contests. |
int i;
char *c;
i[c]; <--- use c[i] instead
(i+3)["string"]; <--- use "string"[i+3] instead
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 character on a line. While some
C preprocessors allow whitespace the leading '#', many do not.
Because the exit() function returns void on some systems, entries
must not assume that it returns an int.
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 or Un*x 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 under both BSD or SYS V Un*x
* abusing 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.
We allowed whitespace, and in certain cases ; { or } do not impact
your program size (up to a certain point), because we want to get
away from source that is simply a compact blob of characters.
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'
program. We are amazed at the many different sizes that claim
to be the smallest. There is nothing wrong with self-replicating
programs. In fact, a number of winners have been self-replicating.
You might want to avoid the claim of 'smallest', lest we (or others)
know of a smaller one!
X client entries should be as portable as possible. Entries that
adapt to a wide collection of environments will be favored. Don't
depend on a particular type of display. For example, don't depend
on color or a given size. Don't require backing store.
X client entries should avoid using X related libraries and
software that is not in wide spread use. We ask that such X client
entries restrict themselves to only the low level Xlib and the
Athena widget set (libX11.a, libXaw.a, libXmu.a and libXt.a).
Don't use M*tif, Xv*ew, or OpenL*ok toolkits, since not everyone
has them. Avoid depending on a particular window manager. Not
everyone has X11r5, and some people are stuck back in X11r4 (or
earlier), so try to target X11r5 without requiring X11r5. Better
yet, try to make your entry run on all version 11 X Window Systems.
X client entries should not to depend on particular items on
.Xdefaults. If you must do so, be sure to note the required lines
in the ---remark--- section.
We like programs that:
* are as concise and small as they need to be
* do something at least quasi-interesting
* pass lint without complaint (not a requirement, but it is nice)
* are portable
* are unique or novel in their obfuscation style
* MAKE USE OF A NUMBER OF DIFFERENT TYPES OF OBFUSCATION
* make us laugh and/or throw up :-)
Some types of programs can't excel in some areas. Of course, your
program doesn't have to excel in all areas, but doing well in several
areas really does help.
We freely admit that interesting, creative or humorous comments in
the ---remark--- section helps your chance of winning. If you had to
read of many twisted entries, you too would enjoy a good laugh or two.
We think the readers of the contest winners do as well.
Be creative!
ENTRY FORMAT:
In order to help us process the many entries, we must request your
assistance by formatting your entries in a certain way. This format,
in addition, allows us to quickly separate information about the
author from the program itself. (see JUDGING PROCESS)
We have provided the program, mkentry, as an example of how to
format entries. You should be aware of the following warning that
is found in mkentry.c:
This program attempts to implement the IOCCC rules. Every
attempt has been made to make sure that this program produces
an entry that conforms to the contest rules. In all cases,
where this program differs from the contest rules, the
contest rules will be used. Be sure to check with the
contest rules before submitting an entry.
You are not required to use mkentry. It is convenient, however,
as it attempts to uuencode the needed files, and attempt to check
the entry against the size rules.
If you have any suggestions, comments, fixes or complaints about
the mkentry.c program, please send Email to the judges. (see below)
The following is a sample entry:
---entry---
rule: 1993
fix: n
title: chonglab
entry: 0
date: Mon Mar 1 08:45:20 1993
host: Un*x v6, pdp11/45
2.9BSD, pdp11/70
---remark---
This is a non-obfuscated obfuscated C program.
It is likely not to win a prize. But what do you expect from
a short example!
---author---
name: Landon Curt Noll
org: IOCCC Judging Group
addr: Toad Hall
PO Box 170608
San Francisco, California
94117-0608
USA
email: {chongo,noll}@{toad,sgi}.com
anon: n
---author---
name: Larry Bassel
org: IOCCC Judging Group
addr: Toad Hall
PO Box 170608
San Francisco, California
94117-0608
USA
email: hoptoad!sun!lab
lab@sun.com
anon: n
---info---
begin 444 info.file
M0V]P>7)I9VAT("AC*2!,86YD;VX@0W5R="!.;VQL+"`Q.3DS+@I!;&P@4FEG
M:'1S(%)E<V5R=F5D+B`@4&5R;6ES<VEO;B!F;W(@<&5R<V]N86PL(&5D=6-A
M=&EO;B!O<B!N;VXM<')O9FET('5S92!I<PIG<F%N=&5D('!R;W9I9&5D('1H
M:7,@=&AI<R!C;W!Y<FEG:'0@86YD(&YO=&EC92!A<F4@:6YC;'5D960@:6X@
M:71S(&5N=&ER971Y"F%N9"!R96UA:6YS('5N86QT97)E9"X@($%L;"!O=&AE
M<B!U<V5S(&UU<W0@<F5C96EV92!P<FEO<B!P97)M:7-S:6]N(&EN('=R:71I
M;F<*9G)O;2!,86YD;VX@0W5R="!.;VQL+@H*5&AA="!T:&%T(&ES+"!I<RX*
M5&AA="!T:&%T(&ES(&YO="P*("`@(&ES(&YO="!T:&%T('1H870@;F]T(&ES
M+@I4:&%T(&ES+"!T:&%T('1H870@:7,@;F]T+"!I<R$*"@D)+2T@8VAO;F=O
M(#$Y-S0*"DQA<W0@>65A<BP@;VYE('!E<G-O;B!T;VQD('5S('1H870@=&AE
M>2!A8W1U86QL>2!D96-O9&5D('1H:7,@9FEL92X*22!W;VYD97(@:&]W(&UA
9;GD@=VEL;"!D;R!I="!T:&ES('EE87(_"@``
`
end
---build---
begin 444 build
28V,@<')O9RYC("UO('!R;V<*
`
end
---program---
begin 444 prog.c
M;6%I;B@I"GL*(VEF(&1E9FEN960H05]214=)4U1%4D5$7U9/5$527TE.7U-5
M3DY95D%,15]#04Q)1D]23DE!7U5302D*("`@('!R:6YT9B@B5F]T92!,86YD
M;VX@3F]L;"!F;W(@4W5N;GEV86QE($-I='D@0V]U;F-I;"!S96%T(",Q+EQN
:(BD["B-E;F1I9@H@("`@97AI="@P*3L*?0H`
`
end
---end---
Typically the build file should assume that the source is prog.c
and will compile into prog. If an entry wins, we will rename
its source and binary to avoid filename collision. By tradition,
we use the name of the entry's title, followed by an optional
digit in case of name conflicts.
If the above entry somehow won the 'least likely to win' award,
we would use chonglab.c and chonglab.
If your entry depends on, or requires that your build, source
and/or binary files be a particular name, please say so in the
---remark--- section. If this case applies, it would be be helpful
if you did one of the following:
* Tell us how to change the filename(s) in your entry.
* Have the build file make copies of the files. For example:
cc prog.c -o special_name need special binary
or rm -f special_src.c need special source
cp prog.c special_src.c
cc special_src.c -o special_name
or rm -f special_build need special build
tail +4 build > special_build
sh < special_build
* Assume that we will use the entry title. Send us a version of
your build/program files that uses the name convention. You
should uuencode these files in ---data--- sections.
If your entry needs to modify its source, info or binary files,
please say so in the ---remark--- section. You should try to avoid
touching your original build, source and binary files. You should
arrange to make copies of the files you intend to modify. This
will allow people to re-generate your entry from scratch.
Remember that your entry may be built without a build file. We
typically incorporate the build lines into a Makefile. If the
build file must exist, say so in the ---remark--- section.
If your entry needs special info files, you should uuencode them
into ---info--- sections. In the case of multiple info files,
use multiple ---info--- sections. If no info files are needed,
then skip the ---info--- section.
Info files are intended to be input, or detailed information that
does not fit well into the ---remark--- section. For example, an
entry that implements a compiler might want to provide some sample
programs for the user to compile. An entry might want to include a
lengthy design document, that might not be appropriate for a
'hints' file.
Info files should be used only to supplement your entry. For
example, info files may provide sample input or detailed
information about your entry. Because they are supplemental,
the entry should not require them exist.
In some cases, your info files might be renamed to avoid name
conflicts. If info files should not be renamed for some reason,
say so in the ---remark--- section.
Info files must uudecode into the current directory. If they
absolutely must be renamed, or moved into a sub-directory, say
so in the ---remark--- section.
When submitting multiple entries, be sure that each entry has
a unique entry number from 0 to 7. Your first entry should
have entry number 0.
With the exception of the header, all text outside of the entry
format may be ignored. That is, don't place text outside of the
entry and expect the judges to see it. (Our decoding tools aren't
AI progs!) If you need tell the the something, put it in the
---remark--- section, or send a Email to the judges at:
...!{apple,pyramid,sun,uunet}!hoptoad!judges (not the address for
judges@toad.com submitting entries)
The date should be given with respect to UTC. (Some systems refer
to this as GMT or GMT0) The format of the date should be that as
returned by asctime() in the C locale. An example of such a string is:
Thr Apr 01 00:47:00 1993
This format is similar to the output of the date(1) command. The
string does not include the timezone name before the year. On many
systems, one of the following command will produce a similar string:
date -u "+%a %h %d %T 19%y"
date -u | sed -e 's/... \(19[0-9][0-9]\)$/\1/'
sh -c 'TZ=UTC date | sed -e "s/... \(19[0-9][0-9]\)$/\1/"'
sh -c 'TZ=GMT date | sed -e "s/... \(19[0-9][0-9]\)$/\1/"'
sh -c 'TZ=GMT0 date | sed -e "s/... \(19[0-9][0-9]\)$/\1/"'
You are allowed to update/fix/revise your entry. To do so, set
the 'fix' line in the ---entry--- section to 'y' instead of 'n'.
Be sure that the resubmittion uses the same title and entry number
as well, as these are used to determine which entry is to be
replaced.
JUDGING PROCESS:
Entries are judged by Larry Bassel and Landon Curt Noll.
Entries are unpacked into individual directories. The Email message
is unpacked into individual files, each containing:
---entry--- section
all ---author--- sections
all ---info--- sections
---build--- section
---program--- section
any other text, including the Email message headers
Prior to judging, the 'any other text' file is scanned to be sure
it does not contain useful information (or in case the entry was
malformed and did not unpack correctly). Information from the
---author--- sections are not read until the judging process is
complete, and then only from entries that have won an award.
The above process helps keep us biased for/against any one particular
individual. We are usually kept in the dark as much as you are
until the final awards are given. We like the surprise of finding
out in the end, who won and where they were from.
We attempt to keep all entries anonymous, unless they win an award.
Because the main 'prize' of winning is being announced, we make all
attempts to send non-winners into oblivion. We remove all non-winning
files, and shred all related paper. By tradition, we do not even
reveal the number of entries that we received. (for the curious,
we do indicate the volume of paper consumed when presenting the IOCCC
winners at talks)
After the Usenix announcement, we attempt to send Email to the
authors of the winning entries. One reason we do this is to give
the authors a chance to comment on the way we have presented their
entry. They are given the chance to correct mistakes, typos. We
often accept their suggestions/comments about our remarks as well.
This is done prior to posting the winners to the wide world.
Judging consists of a number of elimination rounds. During a round,
the collection of entries are divided into two roughly equal piles;
the pile that advances on to the next round, and the pile that does
not. We also re-examine the entries that were eliminated in the
previous round. Thus, an entry gets at least two readings.
A reading consists of a number of actions:
* reading the ---entry--- section
* reading the uudecoded ---build--- section
* reading the uudecoded ---program--- section
* reading the uudecoded ---info--- section(s), if any
* passing the source thru the C pre-processor
shipping over any #include files
* performing a number of C beautify/cleanup edits on the source
* passing the beautified source thru the C pre-processor
shipping over any #include files
In later rounds, other actions are performed:
* linting the source
* compiling/building the source
* running the program
* performing misc tests on the source and binary
Until we reduce the stack of entries down to about 25 entries, entries
are judged on an individual basis. An entry is set aside because it
does not, in our opinion, meet the standard established by the round.
When the number of entries thins to about 25 entries, we begin to form
award categories. Entries begin to compete with each other for awards.
An entry often will compete in several categories.
The actual award category list will vary depending on the types of entries
we receive. A typical category list might be:
* best small one line program
* best small program
* strangest/most creative source layout
* most useful obfuscated program
* best game that is obfuscated
* most creatively obfuscated program
* most deceptive C code
* best X client (see OUR LIKES AND DISLIKES)
* best abuse of ANSI C
* worst abuse of the rules
* <anything else so strange that it deserves an award>
We do not limit ourselves to this list. For example, a few entries are so
good/bad that they are declared winners at the start of the final round.
We will invent awards categories for them, if necessary.
In the final round process, we perform the difficult tasks of
reducing the remaining entries (typically about 25) down to 8 or 10
winners. Often we are confident that the entries that make it into
the final round are definitely better than the ones that do not
make it. The selection of the winners out of the final round, is
less clear cut.
Sometimes a final round entry 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 that 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 entry. More often, the
'best' is picked because it does well in a number of categories.
ANNOUNCEMENT OF WINNERS:
The first announcement, occurs at a Summer Usenix conference. By tradition,
this is done during the latter part of the UUNET/IOCCC BOF, just prior to
the Berkeley BSD, and BSDI BOF.
Winning entries will be posted in late June to the following groups:
comp.lang.c comp.unix.wizards alt.sources
In addition, pointers to these postings are posted to the following
comp.sources.d alt.sources.d misc.misc
comp.sources.misc comp.windows.x
Winning entries will be deposited into the uunet archives. See
below for details.
Often, winning entries are published in selected magazines. 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:
...!{apple,pyramid,sun,uunet}!hoptoad!judges (not the address for
judges@toad.com submitting entries)
Questions and comments about the contest are 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.
chongo <Landon Curt Noll> /\cc/\ {chongo,noll}@{toad,sgi}.com |
Larry Bassel lab@sun.com |
+125
View File
@@ -0,0 +1,125 @@
G int i,j
K case
R return 0
S( x,y) for(x=0; x<y; x++)
I S(i,10
z I-6)B[t][u
t (X[m].b[i].i+g)
u (X[m].b[i].j+l)
M( x,y) XFillRectangles(D,p,x,a,y);
s B[i][j
W =XCreateGC(D,p,4,L)
E( W,_) k=0; I)S(j,22)if(W s]){ a[k].x=i*20; a[k].y=j*20+30; a[k].w=a[k].h=_; k++; }M(
A( W,_) &&!B[W]; if(!j){ z]=1; R; } else{ N(m); _; v(0); }
Q ]=0; I-6&&j)j=
F I-6)B[X[w].b[i].i+g][X[w].b[i].j+l
e( x) break; K x:q(c,j,x);
H (m){ G; I-6){ a[i].x=t*20; a[i].y=u*20+30; a[i].w=a[i].h=
v( _) d(m); z+_]=1; R+1;
struct{
short x,y,w,h;
} a[220],C;
struct{
struct{
G;
} b[4];
} X[99];
G,l,g=3,p,B[10][22],L[99],o[99],n,r,h,_[4],D,J,T;
f(){
*L=2;
n||XSendEvent(D,p,n=1,0,L),XFlush(D);
P();
}
Z(){
_[1]=_[3]=(9-h)*40000;
setitimer(0,_,0);
}
main(){
G,*_=(int*)X;
char*c=
"*{{{ {}{{*{{{ {}* { {{*{{{ *{{{ {* {* * { {{ { { *{* { {* *{{{ *{{{ { * { { *{{{ {{ *{{ { {{* { {*{{ {{ {{ {* { {*{{ { *{{{{ *{{ {{ ";
for(; *c; )
*_++=(unsigned)(*c+++2)%4;
srand(time(0));
L[10]=32769;
D=XOpenDisplay(0);
L[1]=L[2]=XWhitePixel(D,j=XDefaultScreen(D));
XMap@p=XCreate@XRoot@j),0,0,200,470,2,0,1,0,2056,L));
T W;
L[2]=XBlackPixel(D,j);
J W;{
G,O=0,c=0;
Z(P());
q(c,c,1);
for(; ; ){
i=lK();
j=c;
switch(i){
K 'k':c=q(c="$#&'(%)+,-*/01.3254"[c]-35,j,4)?c:j;
e('j')e('l')e(32)}
if(n){
if(!q(c,j,2)){
G,n;
for(j=21;j-1;j--){
n=1;
I&&n)n=s];
n&&(X9(j++),O++);
}
n=0;
I&&!n)n=B[i][21];
Y();
r++;
c=rand()%19;
if(!q(c,c,3))
R+puts(L);
U(Z(h=O/9));
}
n=0;
}
}
}
}
Y(){
G,E(,19)J,k)E(!,20)T,k)U();
}
lK(){
XNextEvent(D,o);
switch(*o){
K 2:R+o[2]?0:XX k){
G=1;switch(k){
K 1:z+l]=1;
d(m);R+1;
K 'j':z Q t A(t-1][u,g--)K 'l':z Q t<9
A(1+t][u,g++)K 4:F Q
u<22&&t>=0&&t<10&&!B[t][u ];
if(!j){
F]=1;
R;
}
N(w);
v(0)K 32:for(;
q(m,m,2);
)n=r++;
R+1;
K 3:l=0;
g=3;
I-6&&j)j=!B[t][u+l ];
if(!j)R;
v(l)K 2:z Q(u+1)<22 A(t][u+1,l++)}
R;
}
X9(_){
G;
for(j=_; j; j--)I)s]=s-1];
}
U(){
void*a=&C;
C.w=200;
C.h=30;
M(T,1);
sprintf(L,"Score%9d Level%9d",r,h);
XDrawString(D,p,J,7,15,L,29);}
P(){
signal(14,f);
}
+37
View File
@@ -0,0 +1,37 @@
Most Obfuscated X Program:
Jon Thingvold
University of Oslo
Sogn Studentby 8231
N 0858 Oslo
Norway
Judges' comments:
To use:
make jonth # requires the X11 library
./jonth # must be run on an X11 server
Use 'h' and 'l' to shift objects left or right. Use 'k' to
rotate and press SPACE to drop.
This program's output may be even more obfuscated when played
on inverse video. :-)
Selected notes from the author:
This is jonth (jon's t(h)etris) for the X Window System.
This program is also an example of data abstraction. The X array is
after initialization hidden by the well defined macros t, u and F.
This program is highly portable as it runs on a "Notebook" size SPARC.
This program will not work on machines with sizeof(int)!=sizeof(void *).
Copyright (c) 1993, Landon Curt Noll & Larry Bassel.
All Rights Reserved. Permission for personal, educational or non-profit use is
granted provided this this copyright and notice are included in its entirety
and remains unaltered. All other uses must receive prior permission in writing
from both Landon Curt Noll and Larry Bassel.
+128
View File
@@ -0,0 +1,128 @@
#include <stdio.h>
#include <malloc.h>
#include <string.h>
#define A(x) (e^d)&i?e:(e+=i+i/15-d,d<<=4,i<<=4,x)
#define B b+=!((e^d)&i)&&(d|=i),i<<=4,
#define C i=15,B B B B d=d<<4|d>>12,
#define D=(d=g,b=0,C b<<=4, C C C b)
#define E if(**y)goto
#define F=a[rand()%c]
#define G unsigned short
#define H e^=a[z],a[z]^=e,e^=a[z],
void
main
(int
z,char
**y)
{G*a
,b,c
,d,e
,f,g
,h,i
;*(*
y+=
strlen
(*y)
-1)^=
'd';
srand
(time
(0))
;z==
2&&
sscanf
(y[1
],"%d"
,&z)
&&z?
0:(z
=6);
if(!
(a=(
G*)
calloc(
z*z*
z*z,
sizeof
(G))
)){
printf
("No\
memory\
\n");
exit
(1);
}for
(c=1
;i=15
,d=z
,c<z
*z*z
*z&&
(e=a
[c-1
]+1,
a[c]
=A(A
(A(A
(0))
)),1
);c++
);*(
**y?
&g:&
e)F;
do{
printf
("(%d): ????\b\b\b\b"
,c);E
q0;else
goto
q1;q0:
printf
("%04X\n"
,g+
4369
);E
q2;q1:
scanf
("%hx"
,**y
?&h:
&g);
E q3
;g-=
4369
;q2:
printf
("??\b\b"
);E q1;
printf(
"%02x\n"
,h D
);q3
:for
(z=f
=0;(
z<c||
(c=f
,0))
&&(H
b D!=
h,H b
||(a[
f++]=
a[z])
,1);z
++);
}while
(h!=
64&&
c>0&&
((g F
),1)
);printf
("\n"
);}
+106
View File
@@ -0,0 +1,106 @@
Best Game:
Leonid A. Broukhis
Moscow Centre of SPARC Technology
123481 Liberty St.,
89-1-95 Moscow
Russia
Judges' comments:
To make:
make leo
To have the computer guess:
leo [colors]
To guess the computer's number:
mind [colors]
where:
colors number of possible colors (1 to 15) (default: 6)
By default, the number of colors if 6. You may specify a
value of between 1 and 15 colors. See the author's notes
for instructions of how to play.
We look forward to more entries from the newer members of the
International Internet community.
On some systems, you may need to remove the line:
#include <malloc.h>
or replace that line with:
#include <sys/types.h>
#include <sys/malloc.h>
to successfully build this entry.
Selected notes from the author:
This program plays mastermind, if you call it by a name ending by
'd', otherwise it _solves_ mastermind. Call it without parameters
to use 6 digits (colors), or indicate the number of possible digits
(you cannot change the number of positions so easily).
The number in parentheses is the number of possible combinations,
based on previous questions and answers. If you solve the puzzle,
"(1)" indicates that your previous moves are enough to give correct
answer. If the program acts as solver and terminates prematurely,
it means that you have mistaken in your answers to its guesses.
Question marks indicate the number of digits you have to enter
(either 4 when you guess or 2 when computer guesses).
Note that the program uses the same code for both player and
solver, and the only place where it makes difference is the
interactive part. Many obfuscations have been made to achieve
this. An expression giving (bulls * 16 + cows) from two numbers
is, however, quite straightforward :-) , as well as the arithmetic
of binary coded colors-base numbers is.
Limitations: maximum number of digits (colors) is 14 (1..F).
Suggestions: Use terminal (or emulator) with non-destructive
backspaces. Do "disable scrolling" on cmdtool or similar emulators.
Bugs: Please don't type ^D at the prompt!!
EXAMPLE: Suppose we think of 1234:
judges-385> leo
(1296): 6433
?? 12 # one 3 is a bull, another is a cow, and 4 is a cow
(160): 5363
?? 02 # both 3's are cows
(21): 4231
?? 22 # 2 and 3 are bulls, 4 and 1 are cows
(2): 4132
?? 13 # 3 is a bull; 1, 2 and 4 are cows
(1): 1234
?? 40 # you may enter everything there
EXAMPLE: Guess the computer's number:
judges-387> mind
(1296): ???? 1122 # my strategy isn't the best, just as example
00
(256): ???? 3344
20
(18): ???? 5566
02
(6): ???? 3654
11
(2): ???? 3355
00
(1): ???? 6444
40 # we have guessed the number
Copyright (c) 1993, Landon Curt Noll & Larry Bassel.
All Rights Reserved. Permission for personal, educational or non-profit use is
granted provided this this copyright and notice are included in its entirety
and remains unaltered. All other uses must receive prior permission in writing
from both Landon Curt Noll and Larry Bassel.
+1
View File
@@ -0,0 +1 @@
char*_=__FILE__;
+167
View File
@@ -0,0 +1,167 @@
Most Versatile Source:
Jyrki Holopainen
Oy LM Ericsson Ab
SF-02420 Jorvas
Finland
Judges' comments:
To use:
make lmfjyh
./lmfjyh
See the makefile for details.
There's more than one way to get around disk quotas. :-)
Some people have reported problems compiling this entry
with gcc 2.3.3.
The make command:
make tidy
will remove the "special" file that is created during the
make of lmfjyh.
Selected notes from the author:
"Practical and efficient method of compressing source code"
1. Introduction
I will shortly present a totally new compression method.
It may be used to compress any types of files, but it works
best with C-source code.
As an example, I have taken a simple "Hello world!" program
that should be familiar to all C-programmers.
Listing 1. A simple "Hello World" program:
main()
{
puts("Hello World!");
}
2. Packing method
Normally a file name is used only to identify the file,
but this new revolutionary method introduces a totally new concept:
THE FILE NAME IS THE PROGRAM. There is no need to waste
valuable disk space to store source code. The program is
embedded in the file name, only a minor portion of it
is inside the file.
Listing 2. Compressed "Hello world":
char*_=__FILE__;
Listing 3. Code embedded in the file name:
";main(){puts("Hello World!");}char*C=".c
The sample program in listing 1 is 36 bytes long. By using the new
compression method, the example program may be squeezed to sixteen
bytes. In the example the compression ratio is 2:1. It is evident
that the longer the program is, the better the compression ratio
is. The maximum compression ratio in a UNIX environment is 254:16
which equals approximately to 16:1. By using the method a one
megabyte of source code can be compressed to 64 kilobytes.
One might easily think that the program could be compressed to a
single byte by writing a one character long preprocessor directive
in the source file and defining the actual source code in the
command line, eg. 'cc hello.c -DX=main(){puts...'. With this
method nothing is gained, since the compiling commands must be
stored in a file, and that takes even more space than writing the
code in a source file as presented in listing 1.
3. Packing files in a UNIX environment
In a UNIX environment it is possible to write almost any program by
including the code in file names. Since '/' is used to separate
path components and cannot therefore exist in a file name, all
features of C-language cannot be used.
In C, the '/' is used as a division operator and it may also be a
part of a comment start and end identifier. This is, however, not a
dangerous limitation, since practice has shown that comments are
almost totally unnecessary. A real programmer can more easily
understand pure source code, and misleading comments are
disastrous. The division operation may be replaced with pow(x, -1)
and multiplication when using real numbers or with div() function
when using integers.
Large programs must be separated into small modules. This enforces
people to write better programs, since monolithic programming style
cannot be used. Program development will also be faster, no extra
code need not be recompiled after changes have been made.
4. Usage with currently available tools
I have tested how well this new method works with currently
available programming tools.
Any ANSI conforming C-compiler that runs under a REAL operating
system should be able to compile the code. (there may be problems
with some older UNIX variants)
4.1. Compilers:
These worked:
gcc versions 2.0, 2.1, 2.3.2 (ld failed at AIX with gcc 2.1)
cc (HP-UX)
cc (VAX)
These failed miserably:
cc (SunOs/Solaris) - could not start cpp properly
cc/xlc (AIX) - could not open source
4.2. Other tools:
4.2.1 Debuggers: (tested at SunOs 4.1.2)
dbx - Quit with a very 'informative' error message:
"dbx: fatal error: Is a directory"
gdb - Printed almost the same error message ":Is a directory".
It was, however, possible to step through the code but
not list it.
4.2.2 Lints:
- None of the lints at tested environments were able
to open the file.
5. Conclusions
The method can be used to compress any types of files, actually the
compression ratios are even better when compressing other files
than C-source. For example plain text files may be compressed with
INFINITE compression ratio. It is trivial task to compress a 100
kilobytes long text file in about 400 files whose lengths are zero
bytes. The drawback is that the files must be unpacked before they
can be used, so a large amount of temporary disk space is needed,
while C-source is totally usable in the compressed form.
Evidently, there is a long way to go before this new programming
technique may be widely used, since currently there are only few
tools supporting it. The advantages over the traditional methods
are, however, so great that there is no doubt that this method will
be new standard.
Copyright (c) 1993, Landon Curt Noll & Larry Bassel.
All Rights Reserved. Permission for personal, educational or non-profit use is
granted provided this this copyright and notice are included in its entirety
and remains unaltered. All other uses must receive prior permission in writing
from both Landon Curt Noll and Larry Bassel.
+1212
View File
File diff suppressed because it is too large. Load diff
+1
View File
@@ -0,0 +1 @@
char*_,*O;main(S,l)char**l;{*(O=*(l+++S-1)-1)=13,*l[1]=0;for(;;)for(printf(*l),_=O-1;_>=*l&&++*_>(S+*O+S)*S;*_--=(S+*O)*S);}
+81
View File
@@ -0,0 +1,81 @@
Best One Liner:
Mark Plummer
2901 Reckord Road
Fallston, MD, 21047
USA
Judges' comments:
To run:
make plummer
./plummer number arg
where:
number a number (try 21701)
arg any argument
For extra credit: What happens when 'number' contains non-numeric
characters, and why?
Selected notes from the author:
This program prints out all numbers up to a given number of digits
on a single line. When the largest number is reached, the program
starts again with 0. It takes two arguments: the first argument
specifies the number to start counting from and uses leading 0's to
indicate the number of digits, the second argument can be anything
but must be present.
Variable names are single characters chosen for their similarity to
other characters (O for 0, l for 1, S for 5 (in some fonts), and _
for ... well nothing really, but it is easy to miss). To prevent
the need for strlen(), the fact that argv is laid out sequentially
is exploited (ie. argv[i + 1] == argv[i] + strlen(argv[i]) + 1).
This is not portable (by the books), but it seems to work
everywhere I try (actually, for vms, that only holds for i > 1).
Also, I depend on the fact that a carriage return causes the line
just written to be overwritten. lint (and most compilers) complain
that there is no control path leading to a return from main(). At
125 characters, it still fits on a single line (for those of us who
don't mind ruining our eyes with 132 column screens).
The first statement points the base of l (the argument vector) to
be the first argument by incrementing it. It then assigns O to
point to the character before the first character of the second
argument which also happens to be the null termination of the first
argument. *O gets a \r assigned to it. Finally 0 is assigned to
the first character of the second argument which has the effect of
null terminating the first argument after the carriage return had
removed its null termination. I really tried to make the last part
of that statement part of the original expression, but the best I
could do was attach it with a comma (against the advice of K&R).
The for loop runs the next for loop continuously (actually until
the machine crashes or the user gets tired of seeing the
counting). The next for loop is the meat of the program. In the
initialization statement, the string pointed to by l (the first
argument containing the digits used for counting followed by a \r)
is printed, and _ is started at the least significant digit in the
string. In the test portion, _ is insured not to be past the
beginning of the string (the most significant digit), and the digit
pointed to by _ is incremented and checked to be sure that it _is_
greater than '9' (written here as (S+*O+S)*S). If the test fails,
either the string has been incremented or each digit in the string
has been reset to '0'. If the test succeeded, the iteration
statement assigns '0' (written here as (S+*O)*S (which has the
added bonus of having the code be a cry for help)) to *_ and
decrements _ to point to the next more significant digit to be
incremented; it is done only when a carry situation results (*_ has
been incremented past '9').
The inspiration for this program came from actual code which dealt
with scanning for a unique temporary filename by appending a
successively larger number to the end of a string.
Copyright (c) 1993, Landon Curt Noll & Larry Bassel.
All Rights Reserved. Permission for personal, educational or non-profit use is
granted provided this this copyright and notice are included in its entirety
and remains unaltered. All other uses must receive prior permission in writing
from both Landon Curt Noll and Larry Bassel.
+123
View File
@@ -0,0 +1,123 @@
/** J.K.Bonfield **
^ <
^ >
< # > v
< <
< > > < v
X X j
x X j
X x ^ k
^ ^
^ #
X X X X
^ v
v v
v #
v X
v x
> # < v
> >
X X l
x X l
41 20
########################################
# #
# < < < < <> < < < #
# > > > <> > > > > #
# < < < < <> < < < #
# > > > <> > > > > #
# < < < < <> < < < #
# > > > <> > > > > #
# #
# #
# #
# #
# #
# #
# #
# #
# #
# #
# X #
########################################*/
#include <stdio.h>
#include <curses.h>
#include <stdlib.h>
#include <setjmp.h>
#include <sys/time.h>
int _tty_ch;
bool _echoit;
bool _rawmode;
SGTTY _tty;
#define U char
#define G for(
#define I )malloc(sizeof(
typedef struct z {U x[20]; struct z*y; } j; j*J[2][256];
struct timeval v= {0,1<<17} ;
U**X,c,*P="noopoqqnr",d;
j*a(int Q, int i) {
G
clear(),noecho(),cbreak(); ;
)
{
int x=0,y=0,W=Q,Q=i-1,k;
G;
y<=Q;
(mvaddch(y,x,X[y][x]),++x^W-1)||(x=0,y++));
k=y=- --x;
G
refresh(),c=select(k,&y,0,0,&v)?getch():0;
k?++x-W||(x=1,++y-Q||(--k,x=W-1,y=Q-1)):--x||(y--,x=W-1),k|y;
)
{
j *t;
G
t=J[1-k][X[y][x]]; t; t=t->y) {
U*f=t->x;
if (d==f[17]|f[17]==c) {
int i=k&2,u=9,k=1,w=x,_=y,T;
G;
--u||(d-f[8]&&(X[y][x]=f[8]),w---_--,i=0,u=8,k--);) {
_+=P[T=i>u?u:i]-'o';
w+=P[4+T]-'p';
if(k) {
if (d-f[i]&&f[i]-X[_][w]) break;
i++;
} else
f[++i+8]-d && (X[_][w]=f[i+8]);
} } } } } }
jmp_buf E;
int main(int open, U**exit) {
FILE*C=fopen (
open-2?__FILE__:*++exit,P+8);
j*t;
volatile int Q,Y=0;
int i,q; d=open-2?'\t':'*'; L:
Q=0; G; setjmp(E)<256; Q--
)
longjmp(E,(J[Y][Q]=0,Q++));
G; ; ) {
if(!C)return 1;
if('\n'==(c=getc(C)))
if(!Y++)goto L; else
{ fscanf(C,"%d %d\n",&i,&q);
X=(U**I P++)*q*(i+1));
Q=0; G; Q<q; Q++)
X[Q]=(U*)&X[q]+Q*i;
fread(*X,(initscr(),q*i),1,C);
a(i,Q);
}
t=(j*I*a(Q--,--Q)));
t->y=J[Y][c]; J[Y][c]=t;
fgets(t->x,20,C); }
}
+41
View File
@@ -0,0 +1,41 @@
\#* ***** **'******
\#** **** ***/*****
\$*******/ ********
o*** **** ***o****,
=*** **** ***=****,
o******=* *o******.
o ***** * \********
\ ******* \********
'**$*****`** ******
' *#***** \********
'**#* *** ****`****
'** ***** **'******
/******=*\*********
`******=*'*********
=**** *** ****=***/
o**** *** ****o***/
/***** ** *****/***
/*****#**`*********
`******* *******`*
`*******#/*********
36 18
###################################
# #
#$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$#
#$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$#
#$$$$$$$$$$$$$#$$$#$$$$$$$$$$$$$$$#
#$$$$$$$$$$$$$#$$$#$$$$$$$$$$$$$$$#
#$$$$$$$$$$$$$#$$$#$$$$$$$$$$$$$$$#
# #
# #
# # # # #
# # # #
# # # #
# #
# #
# o #
# ==== #
# #
-----------------------------------
+55
View File
@@ -0,0 +1,55 @@
o***o@***@***d.***h
o*o****@*@*d****.*k
h***H@***@***..***h
k*K****@*@*.****.*k
o***.@***@***o.***h
O***.@***@***O.***h
h***.@***@***h.***h
j***.@***@***j.***h
k***.@***@***k.***h
l***.@***@***l.***h
o*.****@*@*o****.*k
O*.****@*@*O****.*k
h*.****@*@*h****.*k
j*.****@*@*j****.*k
k*.****@*@*k****.*k
l*.****@*@*l****.*k
@***.****.***@****h
@***d****.***@****h
@*d******.*@******k
@*.******.*@******k
o***@o***@***.d***l
o*@****o*@*.****d*j
l***@L***@***..***l
j*@****J*@*.****.*j
o***@.***@***.o***l
O***@.***@***.O***l
h***@.***@***.h***l
j***@.***@***.j***l
k***@.***@***.k***l
l***@.***@***.l***l
o*@****.*@*.****o*j
O*@****.*@*.****O*j
h*@****.*@*.****h*j
j*@****.*@*.****j*j
k*@****.*@*.****k*j
l*@****.*@*.****l*j
@****d***.****@***l
@****.***.****@***l
@******d*.******@*j
@******.*.******@*j
23 12
######################
#do#.......#..o.o.#..#
#oo#.#K###.#j.#.#.#h.#
#.@..#..H.....hh#.#od#
#oo..H..####k#d...#.o#
#######J#o.#..o#.##.o#
#dd##oo.#o.###ddo#...#
#.Od###.#.o####do#..d#
#.o.H........#####o..#
#.oo##..#O....O.O.O.o#
#d..#ooooO.o#...O....#
######################
+66
View File
@@ -0,0 +1,66 @@
m*** o***o***m ***h
m*** O***o***m.***h
M*** o***O***m ***h
M*** O***O***m.***h
m***.o***o***M ***h
m***.O***o***M.***h
M***.o***O***M ***h
M***.O***O***M.***h
o*** **** ***o****h
o***.**** ***O****h
O*** ****.***o****h
O***.****.***O****h
m* ****o*o*m**** *k
m* ****O*o*m****.*k
M* ****o*O*m**** *k
M* ****O*O*m****.*k
m*.****o*o*M**** *k
m*.****O*o*M****.*k
M*.****o*O*M**** *k
M*.****O*O*M****.*k
o* ****** *o******k
o*.****** *O******k
O* ******.*o******k
O*.******.*O******k
m***o ***o*** m***l
m***O ***o***.m***l
M***o ***O*** m***l
M***O ***O***.m***l
m***o.***o*** M***l
m***O.***o***.M***l
M***o.***O*** M***l
M***O.***O***.M***l
o**** *** ****o***l
o****.*** ****O***l
O**** ***.****o***l
O****.***.****O***l
m*o**** *o* ****m*j
m*O**** *o*.****m*j
M*o**** *O* ****m*j
M*O**** *O*.****m*j
m*o****.*o* ****M*j
m*O****.*o*.****M*j
M*o****.*O* ****M*j
M*O****.*O*.****M*j
o****** * ******o*j
o******.* ******O*j
O****** *.******o*j
O******.*.******O*j
20 15
. ####
#### # #
### o###m #
## m #
## m mm## ##
# #m## #
# # m mm # ###
# m # # m #####
#### # mm # #
#### ## m #
#. ### ########
#.. ..# ####
#...#.#
#.....#
#######
+64
View File
@@ -0,0 +1,64 @@
m*** o***o***m ***h
m*** O***o***m.***h
M*** o***O***m ***h
M*** O***O***m.***h
m***.o***o***M ***h
m***.O***o***M.***h
M***.o***O***M ***h
M***.O***O***M.***h
o*** **** ***o****h
o***.**** ***O****h
O*** ****.***o****h
O***.****.***O****h
m* ****o*o*m**** *k
m* ****O*o*m****.*k
M* ****o*O*m**** *k
M* ****O*O*m****.*k
m*.****o*o*M**** *k
m*.****O*o*M****.*k
M*.****o*O*M**** *k
M*.****O*O*M****.*k
o* ****** *o******k
o*.****** *O******k
O* ******.*o******k
O*.******.*O******k
m***o ***o*** m***l
m***O ***o***.m***l
M***o ***O*** m***l
M***O ***O***.m***l
m***o.***o*** M***l
m***O.***o***.M***l
M***o.***O*** M***l
M***O.***O***.M***l
o**** *** ****o***l
o****.*** ****O***l
O**** ***.****o***l
O****.***.****O***l
m*o**** *o* ****m*j
m*O**** *o*.****m*j
M*o**** *O* ****m*j
M*O**** *O*.****m*j
m*o****.*o* ****M*j
m*O****.*o*.****M*j
M*o****.*O* ****M*j
M*O****.*O*.****M*j
o****** * ******o*j
o******.* ******O*j
O****** *.******o*j
O******.*.******O*j
20 14
. #########
## ## #####
### # # ###
# m #m # # ... #
# # m#om## # #.#. #
# # #m # . . #
# m m # # #.#. #
# ## ##m m . . #
# m # # #m#.#. #
## m m m m... #
#m ###### ## #
# # ##########
####
+84
View File
@@ -0,0 +1,84 @@
Implementation notes
--------------------
Due to the long time this has been slowly evolving, it's hard to describe
quite whether it's been `implemented'. I think perhaps evolve is a better
term. I basic concept behind the program is to describe a game as a simple,
slightly cheaty, cellular automata system, with some of the transitions
bound to key presses.
For instance, assume you wish to make a boulder 'o' roll off a hill '/'
A standard automata would have 2 rules something like this:
o.. ...
\.. --> `o' .o. --> `.'
... .\.
However, the system I devised, in order to keep things small and neat(!),
was to define a 3x3 to 3x3 map (instead of the 3x3 to 1x1 shown above).
Hence:
.o. ...
.\. --> .\o
... ...
This does of course have the odd problem with clashes. What if we want to
roll two down boulders down simultaneously towards the same square.
I perform no buffering, and so this situation is just a 'fight it out' and
let which ever transition has priority win. Such a case may produce the
following change of maps (depending on which 'roll' transition is used
first).
o.o ..o o..
\./ changes to \o/ or to \o/
... ... ...
I claim that it is possible to perform all of the 3x3 to 1x1 transitions
in a 3x3 to 3x3 based system. One other feature added in is a work around
for the 'no buffering' problem. if we define an space ship (as in the
space invader example) to fly right, and we are 'walking through' our map
from top-left to bottom-right, then it is easy to foresee a situation where
our space ship would zip right as far as possible in only the one cycle
of the automata. However, a similar leftwards-bound space ship would only
move the required one square. For this reason I have two lists of
transitions and apply them independently of each other; first top-left to
bottom right, and the second in the reverse direction. This means that I
can make any 'object' move by any amount in a single transition.
Now comes the key important addition to make it 'game' worthy - the
addition of external control by the user. This is done by requesting that
some transitions are only valid when a certain key has been pressed.
So for example, if we (an @ symbol) wish to move right when the 'l' key
is hit we have a transition like:
Key: l
* * * * * *
* @ . * . @
* * * * * *
Here I also use wildcards. On the match side (left) of the transition, an
asterisk will match against any character. On the update side (right), an
asterisk means 'keep whatever was here before'. So the above example
simply means to swap the '@' and '.' around when 'l' is pressed. For the
purposes of space saving, this transition is shrunk to a single line.
Key: K
a b c 1 2 3
d e f 4 5 6
g h i 7 8 9
is written as:
eabcdfghi512346789K
If there are no keys needed for this transition, the character '*' should
be used instead. Now the format of the game description file is now
the following: (angle brackets denote an 'entity' to be defined).
<top-bot transition>*\n<bot-top transition>*\n<X size>[ \t]+<Y size>\n
<map>
The <X size> should take into account the newline at the end of each line
of map, and hence should also be one larger than expected.
+185
View File
@@ -0,0 +1,185 @@
Most Well Rounded:
James Bonfield
MRC Laboratory of Molecular Biology,
Hills Road,
Cambridge,
England
Judges' comments:
To run:
make rince
rince [cabbage]
where:
[cabbage] a CABBAGE description file (default: rince.c)
The author has provided several CABBAGE files for your amusement:
rince.data1 plays breakout. Keys are ',' for left, '/'
for right, and '.' for 'fire the ball'.
rince.data2 plays the old rince game from IOCCC 1991
rince.data3 Sokoban screen 11. You are the 'o' character. You
must push the money 'm' into the dotted region of
the screen. The game is considered finished when
all the 'm's are then 'M's.
rince.data4 Sokoban screen 13. Same rules as above.
For a brief design description, see rince.design.
The select(2) from SunOS says:
BUGS
...
select() should probably return the time remaining from the
original timeout, if any, by modifying the time value in
place. This may be implemented in future versions of the
system. Thus, it is unwise to assume that the timeout
pointer will be unmodified by the select() call.
Systems such as Linux does return the remaining time in timeout
field (0 if no keys were pressed), but `rince' assumes that
timeout remains unmodified.
It has been suggested that:
select(k,&y,0,0,&v)
should be replaced with:
select(k,&y,0,0,(v.tv_usec=1<<whatever_you_want,&v))
where whatever_you_want is some integer such as 17 or 19.
WARNING:
If you are running SunOS 4.1.x (assuming you can find an ANSI
compiler in the first place), this program may be used to log
out very quickly. Unfortunately, you can't do anything else
with it.
Some people may want to slow down the game by increasing the
value 17 in the line:
struct timeval v= {0,1<<17} ;
to something like 18 or 19.
One may also need to do a "stty sane" if you kill the program
to restore your terminal state.
Some people report that rince dumps core on their system.
On some systems that use gcc, the curses.h used by gcc
(typically /usr/local/include/curses.h) is not compatible with
the curses library (typically /lib/libcurses.a) used. It has
been suggested that the following gcc command may help:
gcc -fno-builtin -I/usr/include -o rince rince.c -lcurses -ltermcap
Selected notes from the author:
This is a Cellular Automata Based, Beautifully Abysmal Game Environment (or
CABBAGE for short). To execute the program simply type 'jkb gamefile',
where `gamefile' is a game description file. A couple are supplied for
your enjoyment. Alternatively, with no arguments it will default to using
it's own datafile (the source code infact). This happens to be a game of
space invaders. To prevent people from firing too often a very simple
method is employed; you must move after firing to be able to fire again.
Keys are: Left : j
Right : l
Fire : k
This is a new breed of generic games. For instance:
Game play : Whatever you define
Keys : Whatever you define
Score : If you can figure out how to update it!
Levels : Ahh well... it's not *totally* generic.
The proper definition for usage would be:
jkb [data_filename]
Portability
-----------
I have compiled in on the following systems:
System OS Compiler
-------------------------------------------------------------------------
DECstation 5000/240 Ultrix 4.2A c89 -std
SPARCstation 1+ SunOS 4.1 gcc -ansi -pedantic
SPARCstation 10/31 Solaris 2.1 gcc -ansi -pedantic (*)
DECAlpha 3000/500 OSF/1 V1.2 c89 -std
SGI Indigo (R4000) IRIX 4.0.5F cc -ansi
Alliant FX2800 Conentrix 3.0.0 fxc
(*) I never said it worked! The guidelines state that you dislike programs
that won't *compile* under both BSD or SYS V Un*x. This compiles, and
indeed runs on all the others (both BSD and SYS V) correctly.
Alas, on Solaris it compiles, but mysteriously stops displaying output
after a while until you quit with control C, when it all catches up again.
I think the problem may lie in either select(), or curses, (or perhaps
conflict of the two).
The use of select() no doubt makes it less portable to STRICT system V
machines. However I have tested this on several so-called system V
machines, and all of them support select(). In fact, the select() they
support appears to be more portable between them than their poll() call.
Obfuscation details
-------------------
I have tried to use as many different obfuscation techniques, including
some of which (such as sizeof confusion) I have not seen in any winners
(hmmm - perhaps there's a reason for that...) so far. Also, very poor
structure (yes, I use goto's) has lead to apparently having an fgets() as
the last line of main. Note that I have still tried to aim at least some
efficiency (provided it makes things slightly more obfuscated of course).
One such thing is the way I dynamically allocate a 2-dimensional array
using only ONE malloc(). Hence this program could be used as a tutorial
for all those people who consistently ask this question in the C
newsgroups.
Also, the program does require a volatile type (especially when
optimising) to perform correctly. This is the first time I have ever
truly needed this when not accessing memory external to this process :-)
Of course, all the usual obfuscation lurks within, such as combining
multiple for loops into single ones; warped and twisted logic; plus a
plethora of other minor oddities. It's up to you to discover some of them
of course... Sometimes I have sacrificed length for obfuscation. It is all
too easy to change the arguments in main to one character identifiers, but
in my opinion they add to obfuscation in this case by being longer.
Lint complains about lots of things. Firstly the use of curses immediately
makes lint complain. The Alpha's lint gave me some positive encouragement!
'precedence confusion possible: parenthesize!' :-) :-)
main() does not return correctly, because, basically, it doesn't return.
Bugs
----
Very little error checking is performed. I do check for not being able to
open the requested filename and return 1 upon failure. However, badly
formatted data files will cause major problems. No other checking (such as
insufficient memory) is performed.
There is no 'end of game' checking method. Hence games like sokoban rely
on the user to decide when they have had enough. Also, there is no quit
mechanism other than control C.
Copyright (c) 1993, Landon Curt Noll & Larry Bassel.
All Rights Reserved. Permission for personal, educational or non-profit use is
granted provided this this copyright and notice are included in its entirety
and remains unaltered. All other uses must receive prior permission in writing
from both Landon Curt Noll and Larry Bassel.
+194
View File
@@ -0,0 +1,194 @@
10th International Obfuscated C Code Contest Rules
Copyright (c) Landon Curt Noll & Larry Bassel, 1993.
All Rights Reserved. Permission for personal, educational or non-profit use is
granted provided this this copyright and notice are included in its entirety
and remains unaltered. All other uses must receive prior permission in writing
from both Landon Curt Noll and Larry Bassel.
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. :-)
NOTE: Changes from the 1993 draft are noted by change bars. ---> |
RULES:
To help us with the volume of entries, we ask that you follow these rules:
1) Your entry must be a complete program.
2) Your entry must be <= 3217 bytes in length. The number of characters
excluding whitespace (tab, space, newline), and excluding any ; { or }
followed by either whitespace or end of file, must be <= 1536.
3) Your entry must be submitted in the following format:
---entry---
rule: 1993
fix: y or n (n => this is a new entry, y => this replaces an older entry)
title: title of entry (see comments below)
entry: Entry number from 0 to 7 inclusive (your 1st entry should by 0)
date: Date/time of submission in UTC (see comments below)
host: Machine(s) and OS(s) under which your entry was tested
Use tab indented lines if needed
---remark---
Place remarks about this entry in this section. It would be helpful if
you were to indent your remarks with 4 spaces, though it is not a
requirement. Also, if possible, try to avoid going beyond the 79th
column. Blank lines are permitted.
---author---
name: your name
org: School/Company/Organization
addr: postal address
use tab indented lines to continue
don't forget to include the country
email: Email address from a well known site or registered domain.
If you give several forms, list them on separate tab indented lines.
anon: y or n (y => remain anonymous, n => ok to publish this info)
---info---
If your program needs an info file, place a uuencoded copy of it in
this section. In the case of multiple info files, use multiple info
sections. If your entry does not need a info file, skip this section.
---build---
Place a uuencoded copy of the command(s) used to compile/build your program
in this section. It must uudecode into a file named 'build'. The resulting
file must be 255 bytes or less.
---program---
Place a uuencoded copy of your program in this section. It must uudecode
into a file named is 'prog.c'. The resulting file must follow rule #2.
---end---
Regarding the above format:
* The title must match the expression: [a-zA-Z0-9_=][a-zA-Z0-9_=+-]*
and must be 1 to 12 characters in length.
It is suggested, but not required, that the title should
incorporate your username; in the case of multiple authors,
consider using parts of the usernames of the authors.
* The date in the ---entry--- section should be given with respect
to UTC. The format of the date should be as returned by asctime()
using the C locale. (see guidelines for more info)
* You may correct/revise a previously submitted entry by sending
it to the contest email address. Be sure to set 'fix' in the
---entry--- section to 'n'. The corrected entry must use the same
title and entry number as submittion that is being corrected. Be
sure that you note the resubmittion in the ---remark--- as well.
* With the exception of the header, all text outside of the above
format may be ignored by the judges. If you need tell the judges
something, put it in the ---remark--- section, or send a separate
Email message to the judges.
* Information from the ---author--- section will be published unless
'y' was given to the respective author's 'anon' line.
* To credit multiple authors, include an ---author--- section for
each author. Each should start with ---author--- line, and
should be found between the ---entry--- and ---build--- sections.
* The entry's remarks should include:
- what this program does
- how to run the program (sample args or input)
- special compile or execution instructions, if any
- special filename requirements (see rule 4 and 5)
- information about any ---data--- files
- why you think the program is obfuscated
- note if this entry is a re-submission of a previous entry.
- any other remarks (humorous or otherwise)
* Do not rot13 your entry's remarks. You may suggest that certain
portions of your remarks be rot13ed if your entry wins an award.
* Info files should be used only to supplement your entry. They
should not be required to exist.
If your entry does not need an info file, skip the ---info---
section. If your entry needs multiple info files, use multiple
---info--- sections, one per info file. You should describe
each info file in the ---remark--- section.
4) If your entry is selected as a winner, it will be modified as follows:
'build' is incorporated into a makefile, and 'build' is removed
'prog.c' is renamed to your entry's title, followed by an optional
digit, followed by '.c'
your entry is compiled into a file with the name of your entry's
title, possibly followed by a digit
If your entry requires that a build file exist, state so in your
entry's remark section. The makefile will be arranged to execute a
build shell script containing the 'build' information. The name of
this build shell script will be your entry's title, possibly followed
by a digit, followed by '.sh'.
If needed, your entry's remarks should indicate how your entry must
be changed in order to deal with the new filenames.
5) The build file, the source and the resulting executable should be
treated as read-only files. If your entry needs to modify these files,
it should make and modify a copy of the appropriate file. If this
occurs, state so in your entry's remarks.
6) Entries that cannot be compiled by an ANSI C compiler will be rejected.
Use of common C (K&R + extensions) is permitted, as long as it does not
cause compile errors for ANSI C compilers.
7) The program must be of original work. All programs must be in the
public domain. All copyrighted programs will be rejected.
8) Entries must be received prior to 07-May-93 0:00 UTC. (UTC is
essentially equivalent to Greenwich Mean Time) Email your entries to:
...!{apple,pyramid,sun,uunet}!hoptoad!obfuscate
obfuscate@toad.com
We request that your message use the subject 'ioccc entry'.
If possible, we request that you hold off on Emailing your entries
until 1-Mar-93 0:00 UTC. Early entries will be accepted, however.
We will attempt to email a confirmation to the the first author for
all entries received after 1-Mar-93 0:00 UTC.
9) Each person may submit up to 8 entries per contest year. Each entry
must be sent in a separate Email letter.
10) Entries requiring human interaction to be built are not allowed.
Compiling an entry (must) produce a file (or files) which may |
be executed. |
11) Programs that require special privileges (setuid, setgid, super-user,
special owner or group) are not allowed.
FOR MORE INFORMATION:
The Judging will be done by Landon Noll and Larry Bassel. Please send
questions or comments about the contest, to:
...!{apple,pyramid,sun,uunet}!hoptoad!judges (not the address for |
judges@toad.com submitting entries) |
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.
chongo <Landon Curt Noll> /\cc/\ {chongo,noll}@{toad,sgi}.com |
Larry Bassel lab@sun.com |
+31
View File
@@ -0,0 +1,31 @@
#include <stdio.h>
#define iii\
( I ) if ( ii(I,6\
) )I [ strlen(I ) -1]=!1
int ii(ll,lll ) char*ll; {
char *l="\"; !l ? 1.1 : l; l,printf(";int l1=1-/*+&|"); &+|-*/1,li=!1;while
( lll>l1 ) li|=! ( l[3*l1+++3
] -ll[strlen ( ll)-1] ) ;return
( li ) ;}main ( ll,lll
) char*lll[];{char l1 [ 111][21],li1[111][21 ] ,il1[111],i1l
[ 111 ] ;int lli,l11,l1l,li/* ( */,ll1,il,l;FILE*f;if(ll-2
) {f=fopen ( lll[1],"r" ) ;lli=l=ll1=il=!1;while
( fscanf(f,"%s",l1[lli] ) +1){li=ii ( l1[lli],3
) ;iii ( l1[lli] ) ;l1l=l11=!1;while
( l1l>-ll ) {iii ( lll[-l1l]
) ;strcasecmp ( lll[-l1l--],l1[lli] ) ||
( l11=++il ) ;}l11||lli++;if ( li
) {if ( ll1<il ) {ll1=il;l1l=l=lli;while
( l1l-- ) strcpy ( li1[l1l],l1[l1l]
) ;}il=lli=!1;}}if ( !ll1 ) puts
( " Beats me." ) ;else if ( !l
) puts ( " Yes." ) ;else{*li1[l1l=!1]=toupper
( *li1[!1] ) ;while ( l>l1l
) printf ( " %s",li1[l1l++] ) ;puts
( "." ) ;}}else{sprintf ( il1,"cat %s;echo",lll[1]
) ;system ( il1 ) ;}printf
( "\n? " ) ;gets ( il1
) ;sprintf ( i1l,"%s %s %s",lll[!1 ] ,lll[1],il1);system
( i1l); }
+89
View File
@@ -0,0 +1,89 @@
Obfuscated Intelligence Award:
Mark Schnitzius
1700 Woodbury Rd. #1208
Orlando, FL 32828
USA
Judges' comments:
To run:
make schnitzi
./schnitzi file
where:
file a file containing some text
After this program prints the contents of 'file', ask it
some questions related to the text.
The author suggests the following questions when using schnitzi.info:
Who is Mark Schnitzius?
What exactly does this program do?
What language is it written in?
Has the Loch Ness monster really been captured?
Who was Hitler?
Were the NASA moon landings faked?
Is it true that Elvis is alive?
Do colorless green ideas sleep furiously?
NOTE: The author may also be contacted at: marks@aldrin.ksc.nasa.gov
We suggest you try using the body (minus the header and signature line)
of a Usenet article. You might want to try something from alt.flame. :-)
Selected notes from the author:
I wanted to write a program that would read in a text file in
natural language (such as English) and answer questions about that
text file. I thought this might be a complicated task, and I was
right -- it took me over 800 bytes. Of course, it doesn't always
work, but that's AI for you.
This program accepts the name of a text file as the first
parameter. For example, to run it on the supplied data file called
'info' you would type 'schnitzi info'. It echoes the file, then
gives you a prompt where you may type in questions about that text.
The more words you use which are actually present in the text file,
the better results you get. You'll need to hit <ctrl-c> to break out
of the program. Just hitting <return> at the prompt will reprint the
paragraph.
If you're curious as to how it works, I guess you could feed in the
source as the input file and ask "How does this work?" at the prompt,
but I'm not guaranteeing any results...
Compilation notes:
o The use of 'strcasecmp' may be non-standard. 'strcmp'
can be substituted for it, with a slight performance penalty.
o This program depends on the first command-line parameter, typically
called argv[0], to hold the name of the executable. It is my under-
standing that this property of argv[0] is not guaranteed on some
systems.
This program is obfuscated in the following ways:
o It uses a hidden string to test for punctuation;
o The layout, variable names, and expression format
have been chosen in such a way as to cause visual confusion;
o It uses uses external 'system' calls to echo the text
file and break up the question into individual words with a
recursive call;
o It uses a clever hack to simulate artificial intelligence.
The text for the info file, by the way, consists largely of headlines
from the Weekly World News.
Copyright (c) 1993, Landon Curt Noll & Larry Bassel.
All Rights Reserved. Permission for personal, educational or non-profit use is
granted provided this this copyright and notice are included in its entirety
and remains unaltered. All other uses must receive prior permission in writing
from both Landon Curt Noll and Larry Bassel.
+8
View File
@@ -0,0 +1,8 @@
This program answers questions about paragraphs
of text posed to it in English. It is written
in C. Mark Schnitzius is the author of this
program.
The Loch Ness monster has been captured. Elvis
is alive. Hostler was a woman. The NASA moon
landings were clearly faked.
+26
View File
@@ -0,0 +1,26 @@
O5(O2,O7,O3)char**O7;{return!(O2+=~01+01)?00:!(O2-=02>01)?printf("\045\157\012"
,O5(012,O7+01,00)):!(O2-=02>>01)?(**O7<=067&&**O7>057?O5(03,O7,*(*O7)++-060+010
*O3):O3 ):!(O2 -=-O3- ~O3)? (072>**
O7&&060 <=**O7 ?O5(04 ,O7,012 *O3-060
+*(*O7 )++):O3 ):!(O2 -=!O3+ !!O3)?(
**O7>057 &&**O7 <=071? O5(05, O7,*(*
O7)+++ O3*020 -060): **O7<= 0106&&
00101<= **O7?O5 (05,O7 ,020*O3 +*(*O7)
++-067) :0140<** O7&&** O7<0147 ?O5(05,
O7,-0127 +*(*O7 )+++020 *O3):O3 ):!(
O2-=02- 01)?(** O7==050 ?050** ++*O7,
O5(013, O7,O5( 012,O7 ,00)):* *O7<056
&&054<* *O7?055 **++* O7,-O5( 06,O7,
00):054 >**O7&& 052<** O7?050* *(*O7)
++,O5(06 ,O7,00 ):!(** O7^0170 )||!(
0130^** O7)?*++ *O7,O5 (05,O7 ,00):*
*O7==0144 ||**O7 ==0104 ?++*O7 ,O5(04,
O7,00): O5(03 ,O7,00 )):!-- O2?(*
*O7==052 ?O5(07 ,O7,O3* (*++*O7 ,O5(06
,O7,00) )):!( 045-** O7)?O5( 07,O7,
O3%(03+( *O7)++, O5(06, O7,00) )):!(**
O7^057)?O5(07, O7,O3/( 03-*++ *O7,O5(
06,O7,00))):O3 ):!(O2 +=01-02 )?O5(07
,O7,O5(06,O7, 00)):!( O2+=-02/ 02)?(!(*
*O7-053)?O5(011,O7,O3+(++*O7,O5(010,O7,00))):!(055^**O7)?O5(011,O7,O3-(03+*(*O7
)++,O5(0010,O7,00))):O3):!(O2-=0563&0215)?O5(011,O7,O5(010,O7,00)):(++*O7,O3);}
+186
View File
@@ -0,0 +1,186 @@
Most Irregular Expression:
David Van Brackle
ISX Corporation
1165 Northchase Parkway, Suite 120
Marietta, GA 30067
USA
Judges' comments:
To run:
make vanb
./vanb 'exp'
where:
'exp' an octal expression
The octal expression may contain:
unary operators: +, -
binary operators +, -, *, /, %
hex numbers: x or X follow by hex digits
decimal numbers: d or D follow by decimal digits
octal numbers: octal digits
grouping: ()
No spaces are allowed in the expression. To avoid shell expansion,
one should surround the expression in single quotes.
It is a good thing that this program consists of only one
expression, otherwise it might become hard to understand. :-)
Selected notes from the author:
The program does no error checking - erroneous expressions will
produce spurious results. Note that unary '-' is an operator. Thus,
decimal -46 would be entered as -d46 and not d-46.
What Makes This Program Special:
0) Of course, the fact that the program takes input and produces output
in octal, rather than a more useful system like decimal, makes
it "special".
1) The entire program consists of a single expression, returned from main.
2) There are no global or local variables other than the parameters
to main
3) All of the constants in the program are expressed in octal - including
the printf string.
4) The variables are given names which cause visual confusion with the
octal constants.
5) The program is formatted like a roman numeral 8. The significance of
8 is obvious. I chose roman numerals because it is a numbering
system even more arcane than octal. It's not very 'deceptive',
but it's difficult to deceptively format a program which has no
explicit control structures (other than ?:'s).
6) Many simple tasks are done many times. I tried to do these differently
each time, to make the program harder to understand.
How It Works:
It's a recursive descent parser, calling main
for all of its recursion. O2 is a state variable, telling main
what grammar non-terminal to parse. **O7 is the next character.
O3 is an intermediate result. Whenever you see a construct like:
!(expression with O2)?
it's decrementing & testing O2 to see what state it's in. Comparisons
involving **O7 and octal constants are looking for certain characters.
Here's the grammar ('e' denotes the empty string) :
<E> ::= <T><E'>
<E'> ::= +<T><E'> | -<T><E'> | e
<T> ::= <F><T'>
<T'> ::= *<F><T'> | /<F><T'> | %<F><T'> | e
<F> ::= +<F> | -<F> | (<E><C> | d<D> | D<D> | x<X> | X<X> | <O>
<C> ::= )
<D> ::= [0-9]<D> | e
<X> ::= [0-9]<X> | [A-F]<X> | [a-f]<X> | e
<O> ::= [0-7]<O> | e
Here's how the grammar nonterminals map to octal state numbers:
<E> is 012
<E'> is 011
<T> is 010
<T'> is 07
<F> is 06
<C> is 013
<D> is 04
<X> is 05
<O> is 03
Here's a version of the program before it got formatted into the VIII,
augmented with comments showing where each state begins. N1 and N2 are
notes:
#define O5 main
O5(O2,O7,O3)char**O7;
{
return
/* N1 */ !(O2+=~01+01) ?
00:
/* N2 */ !(O2-=02>01) ?
printf("\045\157\012",O5(012,O7+01,00)):
/* O */ !(O2-=02>>01) ?
(**O7<=067 && **O7>057 ? O5(03,O7,*(*O7)++-060+010*O3):O3):
/* D */ !(O2-=-O3-~O3) ?
(072>**O7 && 060<=**O7 ? O5(04,O7,012*O3-060+*(*O7)++):O3):
/* X */ !(O2-=!O3+!!O3) ?
(**O7>057 && **O7<=071 ? O5(05,O7,*(*O7)+++O3*020-060):
**O7<=0106 && 0101<=**O7 ? O5(05,O7,020*O3+*(*O7)++-067):
0140<**O7 && **O7<0147 ? O5(05,O7,-0127+*(*O7)+++020*O3):O3):
/* F */ !(O2-=02-01) ?
(**O7==050 ? 050**++*O7,O5(013,O7,O5(012,O7,00)):
**O7<056 && 054<**O7 ? 055**++*O7,-O5(06,O7,00):
054>**O7 && 052<**O7 ? 050**(*O7)++,O5(06,O7,00):
!(**O7^0170)||!(0130^**O7) ? *++*O7,O5(05,O7,00):
**O7==0144||**O7==0104 ? ++*O7,O5(04,O7,00):O5(03,O7,00)):
/* T' */ !--O2 ?
(**O7==052 ? O5(07,O7,O3*(*++*O7,O5(06,O7,00))):
!(045-**O7) ? O5(07,O7,O3%(03+(*O7)++,O5(06,O7,00))):
!(**O7^057) ? O5(07,O7,O3/(03-*++*O7,O5(06,O7,00))):O3):
/* T */ !(O2+=01-02) ?
O5(07,O7,O5(06,O7,00)):
/* E' */ !(O2+=-02/02) ?
(!(**O7-053)?O5(011,O7,O3+(++*O7,O5(010,O7,00))):
!(055^**O7) ? O5(011,O7,O3-(03+*(*O7)++,O5(010,O7,00))):O3):
/* E */ !(O2-=0563&0215) ?
O5(011,O7,O5(010,O7,00)):
/* C */ (++*O7,O3);
}
Note N1: It should never enter this state, unless the user invokes the
program with no parameters, in which case it just returns 0.
Note N2: Since the program is properly invoked with 1 parameter, this is
the first state it will go into. This state just invokes
printf, and sends the parser to state 012 (which is <E>).
The E and T states work like this:
int e(){ return eprime( t() ); }
The E' and T' states work like this:
int eprime( int intermediate )
{
if( ch == '+' )
{
ch = nextchar();
return eprime( intermediate + t() );
}
else return intermediate;
}
The D, X and O states work like this (they assume that they're initially
called with 0):
int octal( int intermediate )
{
if( ch>='0' && ch<='7' )
{
intermediate = intermediate * 8 + ch - '0';
ch = nextchar();
return octal( intermediate );
}
else return intermediate;
}
F and C work similarly.
Copyright (c) 1993, Landon Curt Noll & Larry Bassel.
All Rights Reserved. Permission for personal, educational or non-profit use is
granted provided this this copyright and notice are included in its entirety
and remains unaltered. All other uses must receive prior permission in writing
from both Landon Curt Noll and Larry Bassel.